脚本编写
建议先过一遍参考文档:https://docs.xray.cool/#/guide/poc/v2
YAML
一种可读的序列化数据,类似JSON。参考:YAML - Wiki
特点:
- 大小写敏感
- 可以使用
#
号注释 - 使用缩进表示层级关系,缩进不允许使用Tab,可以用空格
关于YAML字符串转义:https://stackoverflow.com/questions/3790454/
基本信息
文件命名格式为:
组件-编号-漏洞类型.yml
,如:node-cve-2017-14849-fileread.yml
```yaml基本信息
POC名称,一般格式为 poc-yaml-<组件名>-<漏洞编号>-<漏洞类型>
name: poc-yaml-test
区分是否手工编写,Xray有一些poc是自动生成的
manual: true
<a name="fglJV"></a>
### 脚本部分
- `set`:定义全局变量
- 随机整数:`变量名: randomInt(min, max)`
- 随机字符:`变量名: randomLowercase(length)`
- `transport`:通信协议,`tcp/udp/http`
- `rules`:语法规则
- `request`字段:定义请求方式和目标路径
- `expression`字段:判断规则是否命中,返回`true/false`
- `out`字段:可以从响应包中获取数据
- `search`字段定义匹配的正则表达式,返回一个字典
- `info:search["info"]`:
- `info`是自定义的变量名,后面可以用`{{info}}`进行调
- `search["info"]`:`search`字典中Key为`info`的值
- `expression`:全部`rule`的执行顺序,遵循短路求值
- 短路求值:即`r1() || r2()`,如果`r1()`的结果为`true`,那么`r2()`不会执行
- 示例:
- `r1() && r2() && r3()`,全部规则命中时返回`true`
- `r1() || r2() || r3()`,任一规则命中时返回`true`
- `r1() || (r2() && r3())`,`r1`规则命中,或者`r2、r3`规则同时命中时返回`true`
```yaml
# 脚本部分
# 全局变量
set:
# 范围随机整数/字符
randInt0: randomInt(1000, 9999)
randStr1: randomLowercase(10)
# 通信协议
transport: http
# 匹配规则
rules:
r1:
# 请求方式
request:
method: GET
path: "/"
# 最终执行结果
expression: |
response.status == 200 && response.body.bcontains(b"example")
# 从响应包获取数据
output:
# search,指定搜索语法
search: |
r'(?P<info>\|.*\|)'.bsubmatch(response.raw)'
# 变量名:匹配规则
info: search["info"]
# rule执行顺序
expression:
r1()
信息部分
- 非必填内容
```yaml
信息部分
detail: author: Chaitin(https://www.chaitin.cn/) links:- https://docs.xray.cool/
还有一些指纹和漏洞信息,可以参考文档
- https://docs.xray.cool/
- 完整POC
```yaml
# 基本信息
# POC名称,一般格式为 poc-yaml-[框架名]-<漏洞编号>
name: poc-yaml-test
# 区分是否手工编写,Xray有一些poc是自动生成的
manual: true
# 脚本部分
# 全局变量
set:
# 范围随机整数/字符
randInt0: randomInt(1000, 9999)
randStr1: randomLowercase(10)
# 通信协议
transport: http
# 匹配规则
rules:
r1:
# 请求方式
request:
method: GET
path: "/"
# 最终执行结果
expression: |
response.status == 200 && response.body.bcontains(b"example")
# 从响应包获取数据
output:
# search,指定搜索语法
search: |
r'(?P<info>\|.*\|)'.bsubmatch(response.raw)'
# 变量名:匹配规则
info: search["info"]
# rule执行顺序
expression:
r1()
# 信息部分,非必填内容
detail:
author: Chaitin(https://chaitin.com/)
links:
- https://docs.xray.cool/
# 还有一些指纹和漏洞信息,可以参考文档
expression
- 匹配响应包 ```yaml expression: response.status == 200 # Status-Code expression: “zbx_session” in response.headers # Header expression: response.body.bcontains(b”verify_string”) # Body
- 搜索
```yaml
# 搜索Body
search: |
"\"verify_string\":\"(?P<token>\\w+)\"".bsubmatch(response.body)
常用字段
output - rule完成后的全局变量
定义了这条 rule 运行完成之后的一些变量,该字段定义的变量会被添加到全局变量。
out
字段下的变量是全局变量,如果2条rule
里在匹配正则时,都用到search
变量,后面的search
的内容会和前面的search
一样,也就是说第2条正则不会生效,所以后面info2
自然和前面info1
一样。不会覆盖也不会报错,第一次遇到的时候排查了很久,记录一下 ```yaml错误示例
r0:
request:
method: GET
path: /
expression: response.status == 200
output:
search: “?P
- 正确写法应该是命名不同的变量
```yaml
# 正确示例
r0:
request:
method: GET
path: /
expression: response.status == 200
output:
r0search: "?P<info>\\w+".bsubmatch(response.body)
info1: r0search["info"]
r1:
request:
method: GET
path: /test.php
expression: response.status == 200
output:
r1search: "?P<info>\\w+".bsubmatch(response.body)
info2: r1search["info"]
follow_redirects - 跟随跳转
- 可以通过设置
follow_redirects: bool
来判断是否允许跟随30X跳转 举例场景:
这个字段是POCv2版本新增的,Gamma语法检查时会报错,但是实际可以运行 | 变量名/函数名 | 类型 | 说明 | | —- | —- | —- | | continue | bool | 命中一个之后是否继续,默认
false
命中即停 | | payloads | map[string]Set | 和 set 一样的结构和语法 |每个 payload 中的 key 必须严格一致 ```shell payloads: payloads: ping:
cmd: r"ping test.com"
curl:
cmd: r"curl test.com"
<a name="ndzce"></a>
### reverse - 反连平台
- 设变量名为`reverse`,需要先使用`newReverse()`生成实例)
| **变量名/函数名** | **类型** | **说明** |
| --- | --- | --- |
| reverse.url | urlType | 反连平台的 url |
| reverse.domain | string | 反连平台的域名 |
| reverse.ip | string | 反连平台的 ip 地址 |
| reverse.is_domain_name_server | bool | 反连平台的 domain 是否同时是 nameserver |
| reverse.wait(timeout) | func (timeout int) bool | 等待 timeout 秒,并返回是否在改时间内获得了信息 |
```yaml
set:
reverse: newReverse()
reverseURL: reverse.url
rules:
r1:
request:
method: POST
path: "/xxx/{{reverseURL}}"
expression: |
reverse.wait(5)
参考知识
CEL
文档
Xray调试:先在
config.yaml
中配置proxy
,可以通过Burp查看数据包 ```shell $ xray —log-level debug webscan —url http://example.com -p ./poc-yaml-xxx.yml
![image.png](https://cdn.nlark.com/yuque/0/2022/png/520228/1645687966683-80b0aa97-9e6d-4bd8-8885-a2e963d61f92.png#clientId=ub141f219-a495-4&from=paste&height=426&id=LhSZR&margin=%5Bobject%20Object%5D&name=image.png&originHeight=852&originWidth=1087&originalType=binary&ratio=1&size=249794&status=done&style=none&taskId=ufb0e0e26-b76f-4d57-881b-d95714012e8&width=543.5)
- [Gamma](https://github.com/chaitin/gamma):提供YAML脚本运行环境,请求响应会以Base64编码形式返回,可以使用`--http-proxy`参数代理到Burp中
```shell
# 语法检查
$ gamma lint --script xxx.yml
# 运行
$ gamma run --target "http://xxx.com" --script xxx.yml
# 调试运行
$ GAMMA_LOG_LEVEL=debug ./gamma run --no-cache --target "http://xxx.com" --script xxx.yml
# 搭配Burp调试
$ gamma run --target "http://xxx.com" --script xxx.yml --http-proxy http://127.0.0.1:8080
作业
- Node.js目录穿越漏洞-CVE-2017-14849
- 向日葵RCE-CNVD-2022-10270