xray使用初体验

前言

看到群里大师傅们都在使用xray,而且还挖出各种大厂的洞,我♥动了,于是决定入坑看看。目前社区版仍然不断处于更新状态:https://github.com/chaitin/xray/releases,当然也有企业版,这里就不说了。官方使用文档:https://chaitin.github.io/xray/#/generic/README

配置文件

默认配置文件如下,内容简介明了:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
version: 2.1
plugins:
xss:
enabled: true
ie_feature: false
baseline:
enabled: true
detect_outdated_ssl_version: false
detect_http_header_config: false
detect_cors_header_config: true
cmd_injection:
enabled: true
crlf_injection:
enabled: true
dirscan:
enabled: true
jsonp:
enabled: true
path_traversal:
enabled: true
redirect:
enabled: true
sqldet:
enabled: true
ssrf:
enabled: true
xxe:
enabled: true
upload:
enabled: true
brute_force:
enabled: true
username_dictionary: ""
password_dictionary: ""
phantasm:
enabled: true
poc:
- poc-yaml-drupal-drupalgeddon2-rce
- poc-yaml-joomla-cve-2015-7297-sqli
- poc-yaml-joomla-cve-2017-8917-sqli
- poc-yaml-thinkphp5-controller-rce
- poc-yaml-thinkphp5023-method-rce
- poc-go-tomcat-put

log:
level: info # 支持 debug, info, warn, error, fatal

mitm:
ca_cert: ./ca.crt
ca_key: ./ca.key
auth:
username: ""
password: ""
restriction:
includes: # 允许扫描的域
- '*' # 表示允许所有的域名和 path
- "example.com/admin*" # 表示允许 example.com 下的 /admin 开头的 path
excludes:
- '*google*'
queue:
max_length: 10000
proxy_header:
via: "" # 如果不为空,proxy 将添加类似 Via: 1.1 $some-value-$random 的 http 头
x_forwarded: false # 是否添加 X-Forwarded-{For,Host,Proto,Url} 四个 http 头
upstream_proxy: "" # mitm 的全部流量继续使用 proxy

basic_crawler:
max_depth: 0 # 爬虫最大深度, 0 为无限制
max_count_of_links: 0 # 本次扫描总共爬取的最大连接数, 0 为无限制
allow_visit_parent_path: false # 是否允许访问父目录, 如果扫描目标为 example.com/a/, 如果该项为 false, 那么就不会爬取 example.com/ 这级目录的内容
restriction: # 和 mitm 中的写法一致, 有个点需要注意的是如果当前目标为 example.com 那么会自动添加 example.com 到 includes 中。
includes: []
excludes:
- '*google*'

reverse:
store_events: false
token: ""
http:
enabled: true
listen_ip: 127.0.0.1
listen_port: ""
dns:
enabled: false
listen_ip: 127.0.0.1
domain: ""
client:
http_base_url: ""
dns_server_ip: ""
remote_server: false
http:
dial_timeout: 5 # 建立 tcp 连接的超时时间
read_timeout: 30 # 读取 http 响应的超时时间,不可太小,否则会影响到 sql 时间盲注的判断
fail_retries: 1 # 请求失败的重试次数,0 则不重试
max_redirect: 5 # 单个请求最大允许的跳转数
max_qps: 500 # 每秒最大请求数
max_conns_per_host: 50 # 同一 host 最大允许的连接数,可以根据目标主机性能适当增大。
max_resp_body_size: 8388608 # 8M,单个请求最大允许的响应体大小,超过该值 body 就会被截断
headers: # 每个请求预置的 http 头
User-Agent:
- Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.169
cookies: # 每个请求预置的 cookie 值,效果上相当于添加了一个 Header: Cookie: key=value
key: value
allow_methods: # 允许使用 http 方法
- HEAD
- GET
- POST
- PUT
- DELETE
- OPTIONS
- CONNECT
tls_skip_verify: true # 是否验证目标网站的 https 证书。

添加证书

xray genca之后会在目录下生成ca.key、ca.crt手动添加证书至浏览器即可

xray主动扫描

xray指定本次运行的插件

xray --config <config_FILE> webscan --plugins cmd_injection,sqldet --url http://example.com
xray --config <config_FILE> webscan --plugins cmd_injection,sqldet --listen 127.0.0.1:7777

xray运行自编poc

xray --config <config_FILE> webscan --plugins phantasm --poc /home/test/1.yml --url http://example.com/

xray被动扫描

xray --log_level debug --config <config_FILE> webscan --listen <ip>:<port> --html-output <FILE_name>

config_FILE在windows最好使用绝对路径

这里可以限制漏洞扫描的范围

1
2
3
4
5
6
restriction:
includes: # 允许扫描的域
- '*' # 表示允许所有的域名和 path
- "example.com/admin*" # 表示允许 example.com 下的 /admin 开头的 path
excludes:
- '*mozilla.org*'

编写poc

推荐案例:https://chaitin.github.io/xray/#/guide/poc

expression表达式上下文暂时只包含如下:

变量名 类型 说明
status int 返回包的status code
body []byte 返回包的Body,因为是一个字节流(bytes)而非字符串,后面判断的时候需要使用字节流相关的方法
content_type string 返回包的content-type头的值
headers map[string]string 返回包的HTTP头,是一个键值对(均为小写),我们可以通过headers['server']来获取值。如果键不存在,则获取到的值是空字符串

expression表达式上下文包含所有CEL文档中支持的函数,同时还包含xray引擎中自定义的函数,常用的函数如下:

函数名 函数原型 说明
contains func (s1 string) contains(s2 string) bool 判断s1是否包含s2,返回bool类型结果。
bcontains func (b1 bytes) bcontains(b2 bytes) bool 判断一个b1是否包含b2,返回bool类型结果。与contains不同的是,bcontains是字节流(bytes)的查找。
matches func (s1 string) matches(s2 string) bool 使用正则表达式s1来匹配s2,返回bool类型匹配结果。
bmatches func (s1 string) bmatches(b1 bytes) bool 使用正则表达式s1来匹配b1,返回bool类型匹配结果。与matches不同的是,bmatches匹配的是字节流(bytes)。
startsWith func (s1 string) startsWith(s2 string) bool 判断s1是否由s2开头
endsWith func (s1 string) endsWith(s2 string) bool 判断s1是否由s2结尾

用一些简单的例子来覆盖大部分我们可能用到的表达式:

body.bcontains(b'test')

返回包body包含test,因为body是一个bytes类型的变量,所以我们需要使用bcontains方法,且其参数也是bytes

content_type.contains('application/octet-stream') && body.bcontains(b'\x00\x01\x02')

返回包的content-type包含“application/octet-stream”,且body中包含0x000102这段二进制串

content_type.contains('zip') && r'^PK\x03\x04'.bmatches(body)

这个规则用来判断返回的内容是否是zip文件,需要同时满足条件:content-type包含关键字“zip”,且body匹配上正则r’^PK\x03\x04’(就是zip的文件头)。因为startsWith方法只支持字符串的判断,所以这里没有使用。

status >= 300 && status < 400

返回包的status code在300~400之间

(status >= 500 && status != 502) || r'<input value="(.+?)"'.bmatches(body)

返回包status code大于等于500且不等于502,或者Body包含表单

expression表达式返回的必须是一个bool类型的结果,这个结果作为整个Rule的值,而rules由多个Rule组成。值为true的Rule,如果后面还有其他Rule,则继续执行后续Rule,如果后续没有其他Rule,则表示该POC的结果是true;如果一个Rule的expression返回false,则不再执行后续Rule,也表示本POC的返回结果是false。

也就是说,一个POC的rules中,最后一个Rule的值,决定是否存在漏洞。

-------------本文结束感谢您的阅读-------------