既然我们要讲解的是 Web 漏洞扫描器,那么就先假设是 AMF over HTTP (这里并不须要你理解 AMF,你只须要知道 AMF 是一种数据格式类型就行)。
假设我们须要测试一个 AMF 格式数据的 SQL 注入问题,那么按照常日的思路便是在 SQL 注入模块中:
1.先解析 HTTP 中 AMF 格式数据

2.然后在测试参数中填写 payload
3.重新封装 AMF 格式数据
4.发送 HTTP 要求
伪代码如下:
1req = {"method": "POST", "url": "http://fatezero.org", "body": "encoded data"}2data = decode_amf(req["body"])3for key, value in data.items():4 d = copy.deepcopy(data)5 d[key] = generate_payload(value)6 body = encode_amf(d)7 requests.request(method=req["method"], url=req["url"], body=body)
全体流程下来没什么问题,但是如果又来了一个 X 协议(X over HTTP),那么我们就得连续修正 SQL 注入模块以便支持这种 X 协议,但是扫描器中可不是只有 SQL 注入检测模块,还有其他同类模块,难道每加一个新协议我还得把所有检测模块都改一遍?
以是我们须要把这些协议解析和封装单独抽出来放在一个模块中。
伪代码如下:
1# utils.py 2def decode(data): 3 if is_amf(data): 4 data = decode_amf(data) 5 6 if is_X(data): 7 data = decode_X(data) 8 9 # 递归 decode10 for i in data:11 data[i] = decode(data[i])1213 return data141516# detect_module.py17req = {"method": "POST", "url": "http://fatezero.org", "body": "encoded data"}18data = decode(req["body"])19for key, value in data.items():20 d = copy.deepcopy(data)21 d[key] = generate_payload(value)22 body = encode(d)23 requests.request(method=req["method"], url=req["url"], body=body)
上面的递归 decode 紧张是为理解码某种格式的数据里面还有其余一种格式的数据,虽然看起来这种场景比较少见,但是仔细想一下 multipart 带着 json,json 里的字符串是其余一个 json 字符串,是不是又以为这种情形也并不少见。
那 encode/decode 剥离出来就可以了吗?请把稳到上面伪代码利用了 requests. request 发送要求,那如果某天须要我们去测试 websocket 协议,是不是又得在检测模块中多加一套 websocket client 发送要求?
以是我们也须要将详细的网络操作给剥离出来,详细的协议类型直接由上面来处理,检测模块只须要关注详细填写的 payload。
伪代码如下:
1for key, value in x.items():2 data.reset()3 x[key] = generate_payload(value)4 x.do() # 卖力将数据重新组装本钱来的格式,并按照原始协议发送56 # check
由于每个检测模块的检测依据大致就几种:
返回内容花费韶光 (time based)其余一条信道的数据 (比方说 dnslog)以是即便是我们将网络操作剥离出来也不会影响检测的效果。
在编写检测模块的时候,编写者可以不用关心根本协议是什么,怎么对数据编码解码,只用关心根据 value 天生 payload 并填写到相对应的 key 中。
如果某天涌现了这么一种盛行编码格式 http://www.a.com/key1, value1,key2,value2,那我们所有的检测模块也无需修正,仅仅须要在上一层再添加一套 encode/decode 操作即可。如果某天涌现了一种比较盛行的协议,我们也仅须要在上一层供应一套 client 即可。检测模块的事情就仅仅剩下天生并填写 payload。
0x02 PoC 分类在 2014 年的时候,我做了大量的竞品剖析,包括利用逆向工程逆向商业的 Acunetix WVS, HP Webinspect, IBM AppScan, Netsparker 扫描逻辑,也包括阅读开源的 w3af, arachni 代码。
如果不谈扫描质量,只关注整体项目设计以及产品中利用到的猥琐技巧,那么个中最让我面前一亮确当属 AWVS,接下来我将详细先容一下我从 AWVS 中学习到的 PoC 分类。
PoC 分类:
类型描述PerServer用于检测 Web Server 级别中存在的漏洞,比方说各种中间件,Web 框架的漏洞PerFile用于检测某个文件中是否存在漏洞,比如对应文件的备份,Bash RCE 等PerFolder用于检测某个目录中是否存在漏洞,比如敏感信息的泄露,路径中的 SQL 注入等PerScheme用于检测某个参数中是否存在漏洞,比如 SQL 注入,XSS 等PostCrawl在爬虫结束之后启动,直策应用爬虫的资源进行检测PostScan在扫描结束之后启动,用于检测二阶注入,存储 XSS等WebApps用于检测比较常用的 Web 运用的漏洞
大致的流程图如下:
在获取到爬虫资产,对干系资产格式化之后,便下发到各个不同类型的 PoC 中进行检测,这样做的好处是分类明确,覆盖大多数检测阶段,也避免为了减少重复要求的下发而须要额外记录中间状态的行为。
0x03 IASTAWVS 有个比较有趣的功能 AcuMonitor ,也就大家熟知的 dnslog、反连平台。在 2014 年看到 AWVS 的这个功能时,就建议 WooYun 出个类似的功能,也便是 cloudeye,tangscan 也就算是海内比较早利用这种技能的扫描器,当然后续又涌现了各种类似 cloudeye 的项目,自然而然也涌现了各种利用该技能的扫描器。
不过本日我们不打算连续先容 AcuMonitor,而是先容其余一个也很有趣的功能 AcuSensor 。AcuSensor 便是IAST,只要轻微理解过 Web 漏洞扫描器的,都该当会知道 IAST 是干啥的。那为什么我要单独拎出来讲这个呢?
紧张是由于 AcuSensor 的实现办法非常有趣。AcuSensor 供应了 Java、 .NET、PHP 这三个措辞版本,个中比较有趣的是 PHP 版本的实现。
PHP版本的AcuSensor利用方法是下载一个acu_phpaspect.php文件,再通过 auto_prepend_file 加载这个文件, 众所周知,PHP 是不能改直接 hook PHP 内置函数的,那么单单依赖一个 PHP 脚本,AcuSensor是如何做到类似 IAST 功能的呢?
很大略,直接更换所有关键函数。嗯,真的就那么大略。
我们来详细先容一下这个过程,在 acu_phpaspect.php 中:
1.获取用户实际要求的文件内容
2.检讨一下有没有干系 cache,如果有 cache 那么直接加载实行 cache,然后结束
3.利用 token_get_all获取所有 token遍历每一个 token,对自己感兴趣的函数或者语句利用自己定义的函数进行 wrap 并更换
4.将更换后的内容保存到 cache 中并利用 eval 实行
5.__halt_compiler中断编译
举个详细的例子:
1<?php23$link = NULL;4$sql = "select from user where user_id=".$_GET["id"];56mysqli_prepare($link, $sql);
经由 acu_phpaspect.php 转换之后:
1<?php23$link = NULL; 4$sql = "select from user where user_id=".$_GET[_AAS91("hello.php", 4, "\$_GET", "id")]; 56_AAS86("hello.php",6,"mysqli_prepare",Array($link, $sql));
全体过程大略粗暴有效,这样做的优点在于:
实现大略,只须要编写 PHP 即可安装大略,无需安装扩展,只需修正配置文件可以兼容性强,比较随意马虎兼容性各种环境,各种版本 PHP如果故意向去做 IAST 或者想做类似我的 prvd http://github. com/fate0/prvd项目,但又不太喜好写 PHP 扩展,那么我强烈建议你完全的看一遍 PHP 版本 AcuSensor 的实现。如果对自己实现的检测逻辑效率比较自傲的话,乃至可以基于这个事理直接实现一个 PHP 版本的 RASP 项目。
0x04 限速在 Web 漏洞扫描器中,无论作为乙方的商业产品、甲方的自研产品,限速都是一个至关主要的功能,乃至可以说如果你的扫描器没有限速功能,那压根就不能上线利用。接下来我们将先容一下在扫描器中限速的几种方法。
1.代理利用代理做限速功能,将所有实行扫描任务的 worker 的测试流量全转发proxy 做事器上:
由 proxy 做事器统一调度发送测试要求频率,直策应用 proxy 方案优点是可以兼容之前没做限速功能的扫描器,缺陷是所有基于 time based 的检测均无效(当然也可以让 proxy 返回真正的相应韶光来进行判断,不过仍须要修正检测模块),也不许可在检测模块中加入超时设置。
2.双重行列步队其余一种方法是利用双重行列步队实现限速功能,流程图如下:
1.worker1 从行列步队中取到名为 target1 的任务
2.worker1 从 target1 行列步队中取出和 target1 干系的任务
3.默认单并发实行和 target1 干系任务,根据设置的 QPS 限定,主动 sleep 或者增加并发
这种方案的缺陷是扫描器设计之初的时候就得利用这种方法,优点是每个并发可以稳定的和远程做事器保持链接,也不影响扫描功能。
0x05 漏洞检测实际上这一节并不会讲详细某个漏洞检测方法,只是大略谈一下漏扫模块每个阶段该干的事情。
项目之初,没有干系积累,那么可以选择看一下 AWVS 的检测代码,虽然说网上公开的是 10.5 的插件代码,但实在从 8.0 到 11 的插件代码和 10.5 的也差不多,无非新增检测模块,修复误漏报的情形,也可以多看看 SQLMap 代码,看看检测逻辑,但是千万不要学习它的代码风格。从这些代码中可以学习到非常多的小技巧,比如动态页面检测,识别 404 页面等。看代码很随意马虎理解干系的逻辑,但我们须要去理解为什么代码这样处理,历史背景是什么,以是多用 git blame。
到了中期,须要提升漏洞检测的精准度,漏洞检测的精准度是建立在各种 bad case 上,误报的 case 比较随意马虎网络和解决,漏报的 case 就须要其他资源来合营。作为甲方如果有漏洞网络平台,那么可以结合白帽子以及自己部门渗透团队提交的漏洞去优化漏报情形。
如果扫描器是自己的一个开源项目的话,那么就必须适当的推广自己的项目,让更多的人去利用、反馈,然后才能连续完善项目,从而连续推广自己的项目,这是一个循环的过程。总而言之,提升漏洞检测的精准度须要两个条件:1. bad case,2. 掩护精力
到了后期,各种常规的漏洞检测模块已经实现完成,也有精力持续提升检测精准度,日常漏洞 PoC 也有职员进行补充。
那么事情就结束了么?
不,依旧有很多事情我们可以去做,扫描器的紧张目标是在不影响业务的情形下,不择手段的创造漏洞,以是除了常规的资产网络办法之外,我们还可以从公司内部各处获取资产干系的数据,比方说从 HIDS 中获取所有的端口数据、系统数据,从流量中或业务方日志中获取 url 干系数据等。
当然除了完善资产网络这块,还有赞助提升检测效果的事情,比如说上面提到的 AcuSensor,这部分事情可以结合公司内部的 RASP 做到同样效果,还有剖析 access log、数据库 log 等事情。总的来说,做漏扫没有什么条条框框限定,只要能创造漏洞就行。
以上都是和技能干系的事情,做漏扫须要处理的事情也不仅仅只有技能,还须要去搞定详细可操作的漏洞描述及其办理方案,申报请示可量化的指标数据,最主要的是拥有有理有据、令人信服的甩锅技巧