干货 | Xray POC编写指南

admin 2024年3月25日08:49:08评论8 views字数 4627阅读15分25秒阅读模式

前言

一份 Xray POC 的简单食用指南
脚本编写

建议先过一遍参考文档: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

# 基本信息
# POC名称,一般格式为 poc-yaml-<组件名>-<漏洞编号>-<漏洞类型>
name: poc-yaml-test
# 区分是否手工编写,Xray有一些poc是自动生成的
manual: true

脚本部分

  • set:定义全局变量

    • 随机整数:变量名: randomInt(min, max)

    • 随机字符:变量名: randomLowercase(length)

  • transport:通信协议,tcp/udp/http

  • rules:语法规则

    • search字段定义匹配的正则表达式,返回一个字典

    • info:search["info"]

    • info是自定义的变量名,后面可以用{{info}}进行调

    • search["info"]search字典中Key为info的值

    • request字段:定义请求方式和目标路径

    • expression字段:判断规则是否命中,返回true/false

    • out字段:可以从响应包中获取数据

  • expression:全部rule的执行顺序,遵循短路求值

    • r1() && r2() && r3(),全部规则命中时返回true

    • r1() || r2() || r3(),任一规则命中时返回true

    • r1() || (r2() && r3())r1规则命中,或者r2、r3规则同时命中时返回`true````yaml

      脚本部分

      全局变量

      set:

      范围随机整数/字符

      randInt0: randomInt(1000, 9999)
      randStr1: randomLowercase(10)

    • 短路求值:即r1() || r2(),如果r1()的结果为true,那么r2()不会执行

    • 示例:

通信协议

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/
# 还有一些指纹和漏洞信息,可以参考文档

完整POC:

# 基本信息
# 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

匹配响应包:

expression: response.status == 200                    # Status-Code
expression: "zbx_session" in response.headers # Header
expression: response.body.bcontains(b"verify_string") # Body

# 前面使用了md5加密随机值: md5({{randNum}}), 后面可使用以下语句来进行匹配:
expression: response.body.bcontains(bytes(md5(string(randNum))))

搜索字符:

# 搜索Body
search: |
""verify_string":"(?P<token>\w+)"".bsubmatch(response.body)

常用字段

output - rule完成后的全局变量

定义了这条 rule 运行完成之后的一些变量,该字段定义的变量会被添加到全局变量

out字段下的变量是全局变量,如果2条rule里在匹配正则时,都用到search变量,后面的search的内容会和前面的search一样,也就是说第2条正则不会生效,所以后面info2自然和前面info1一样。不会覆盖也不会报错,第一次遇到的时候排查了很久,记录一下

# 错误示例

r0:
request:
method: GET
path: /
expression: response.status == 200
output:
search: "?P<info>\w+".bsubmatch(response.body)
info1: search["info"]
r1:
request:
method: GET
path: /test.php
expression: response.status == 200
output:
search: "?P<info>\w+".bsubmatch(response.body)
info2: search["info"]

正确写法应该是命名不同的变量

# 正确示例

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跳转

举例场景:如果需要从一个 302 跳转的包中取值并设置到Cookie中,这个时候就需要显式设置follow_redirectsfalse,然后再手动发起一次新的请求包。否则如果跟随跳转的话,则会携带原来Cookie

payload - 全局变量载荷

该字段用于定义多个 Payload,来实现发送不同 Payload 的效果。

这个字段是POCv2版本新增的,Gamma 语法检查时会报错,但是实际可以运行

变量名/函数名 类型 说明
continue bool 命中一个之后是否继续,默认false命中即停
payloads map[string]Set 和 set 一样的结构和语法

每个 Payload 中的key必须严格一致

payloads:
payloads:
ping:
cmd: r"ping test.com"
curl:
cmd: r"curl test.com"

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 秒,并返回是否在改时间内获得了信息
set:
reverse: newReverse()
reverseURL: reverse.url

rules:
r1:
request:
method: POST
path: "/xxx/{{reverseURL}}"
expression: |
reverse.wait(5)

参考知识

CEL

  • CEL语法 - 官方文档

  • expression编写

脚本调试

Xray格式检测:使用以下命令进行格式检测,格式通过才可以在社区进行提交,否则会报错提示:POC 代码错误,建议使用Xray进行格式检测

$ xray poclint --script poc-yaml-xxx.yml

Xray功能调试:先在config.yaml中配置proxy,可以通过Burp查看数据包

$ xray --log-level debug webscan --url http://example.com -p ./poc-yaml-xxx.yml

干货 | Xray POC编写指南

Gamma:提供YAML脚本运行环境,请求响应会以Base64编码形式返回,可以使用--http-proxy参数代理到 Burp 中

# 语法检查
$ 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

干货 | Xray POC编写指南

干货 | Xray POC编写指南

最后再推荐两款 Xray POC 编写辅助工具

  • https://poc.xray.cool/

  • https://phith0n.github.io/xray-poc-generation/

声明:⽂中所涉及的技术、思路和⼯具仅供以安全为⽬的的学习交流使⽤,任何⼈不得将其⽤于⾮法⽤途以及盈利等⽬的,否则后果⾃⾏承担。所有渗透都需获取授权

文章来源: https://forum.butian.net/share/2731文章作者:Naraku如有侵权请联系我们,我们会进行删除并致歉


原文始发于微信公众号(渗透安全团队):干货 | Xray POC编写指南

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2024年3月25日08:49:08
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   干货 | Xray POC编写指南https://cn-sec.com/archives/2598694.html

发表评论

匿名网友 填写信息