xray支持用户自己编写YAML格式的POC规则,YAML是JSON的超集,也就是说,你甚至可以用JSON编写POC,但这里还是建议大家使用YAML来编写,原因如下:
设计目标:
我们希望:
使用 VSCode,进行一些配置后可以提供一些智能提示,方便编写 POC。
首先安装 https://marketplace.visualstudio.com/items?itemName=redhat.vscode-yaml 插件,然后在 settings 中确认 Extensions - YAML 中相关的开关已经打开。然后点击 Edit in settings.json
,将 json 内容修改为
1{ 2 "yaml.schemas": { 3 "https://raw.githubusercontent.com/chaitin/gamma/master/static/schema/schema-v2.json": ["fingerprint-yaml-*.yml", "poc-yaml-*.yml"] 4 } 5}
这样创建 poc-yaml-
开头的 yml
为拓展名的文件的时候,就可以自动提示了。
注意,由于插件的 bug,除了第一行以外,其他的内容无法直接提示,需要使用快捷键让 VSCode 显示提示,一般是 ctrl
+ Space
。
为了帮助大家更好的理解 poc 中各部分的作用,此处先介绍一下一个 yaml poc 的执行过程。
在一个 yaml poc 从文件加载到 go 的某个结构后,会首先对表达式进行预编译和静态类型检查,这一过程主要作用于 yaml 中的 set 和 expression 部分,这两部分是 yaml poc 的关键,主要用到了 CEL 表达式。
在检查完成后,内存中的 poc 就处于等待调度的状态了。每当有新的请求来临时,会执行类似如下的伪代码:
1for rule in rules:
2 newReq = mutate_request_by_rule(req, rule)
3 response = send(newReq)
4 if not check_response(response, rule):
5 break
简单来讲就是将请求根据 rule 中的规则对请求变形,然后获取变形后的响应,再检查响应是否匹配 expression
部分的表达式。如果匹配,就进行下一个 rule,如果不匹配则退出执行。
如果成功执行完了最后一个 rule,那么代表目标有漏洞,将 detail 中的信息附加到漏洞输出后就完成了单个 poc 的整个流程。
目前版本的实现对新的请求定义为: 新的目录, 比如下面几个 url 依次进入检查队列时,执行情况如下:
http://exmaple.com/ 会执行, 上下文为 /
http://example.com/a 不会再次执行,因为上下文同样为 /
http://example.com/a/b 会执行,上下文为 /a/
http://example.com/a/c/ 不会执行, 超过深度限制 (depth)
其中 depth
是 phantasm 插件的一个配置项,用于指定检测深度,可以参考: 插件配置
在编写expression表达式的时候,尤其要注意一个问题:yaml字符串的转义,与CEL表达式字符串里的转义。
yaml中,如果要编写一个字符串类型的值,可以使用引号进行包裹,如:
1name: "value"
但如果value中有反斜线,会在解析yaml的时候进行转义。那么如果expression表达式代码中也存在双引号或转义符,此时转义符就已经没有了,我们需要双重转义,这个时候编写的代码就非常不可读也不可维护。
所以,建议使用yaml中支持的块样式(block style)来表示,如:
expression: |
response.status == 200 && response.body.bcontains(b'\x01\x02\x03')
此时在YAML层面无需转义。
如果 poc 无法扫出期望的结果,可以按照以下思路调试
http
段中加入 proxy: "http://proxy:port"
,比如设置 burpsuite 为代理,这样 poc 发送的请求可以在 burp 中看到,看是否是期望的样子。