背景
在做渗透测试过程中,脆弱点评估是一个枯燥的过程,目标系统 Web 接口可能成百上千个,每个接口都需要做认证,授权,输入检测,错误管理,业务逻辑等安全问题。特别是针对输入检测模块,XSS,SQL 注入,命令注入测试等不仅仅针对接口,还需要针对参数进行挨个的遍历测试,这个工作量可想而知。
Web 接口绝大多数是 GET 方式和 POST 方式的请求。如果是 GET 方式,那可能在 URI 中带有多个参数,比如http://exp.com?param1=a¶m2=b¶mN=x
如果是 POST 方式请求,不仅 URI 中可能带参数,POST 的 data 中也可能是带多个参数,比如
POST /test
...
param1=a¶m2=b¶mN=x
这种情况下要么是手动挨个参数排查,是否存在各类输入检测脆弱点,特别是 SQL 注入,XSS,命令注入等,这种方式优点是结果较准确,一般不会出现误报漏洞,缺点是工作量太大,有时候大到测试人员只是抽样进行测试,而不是全量测试。
基于上述背景,一个很自然的想法是使用自动化工具去跑 payload,先考虑最简单的情况,就是只替换 URI 和 POST data 中键值对的模型,URI 的参数采用键值对是可以确定的,但是 POST 的 data 可能是 json,可能是文件等较复杂情况,本文还是基于键值对来进行描述。
当前 Web 扫描工具有很多,比如 AWVS,APP Scan,Netsparker 这些基于爬虫的全自动扫描器,也有 Burpsuit,Xray 等基于代理的被动式扫描器。这两类扫描器各有优缺点,全自动扫描器的优点是省时省力,配置一下扫描信息,即可一键扫描。缺点是爬虫可能不够智能,另外一些测试点可能无法涉及到。被动式扫描器的优点是扫描的接口及数据会比较准确,各类信息数据都是用户操作输入的,缺点是需要人工配合操作,正常使用目标系统,让流量经过被动式扫描器后进行智能扫描。
备注:Xray 当然也有爬虫功能可以自动化扫描,但是笔者基本上是使用该工具进行被动式扫描,如果全自动扫描更偏向于 AWVS,因为客户也会用 AWVS 扫描产品。
上述这些扫描器笔者基本都用过,基于本文的背景,Xray 是最贴近的一个扫描器,首先感谢开发 xray 的前辈大佬的努力以及慷慨分享,xray 有个不太友好的缺点是该工具只以二进制模式发布,不可定制 payload。假设一种场景你是甲方渗透测试人员,你对公司的产品很熟悉,你比较清楚 xss 漏洞,SQL 漏洞可能出现在哪个产品的哪些地方,基于这些信息,你可以定制一些 payload 去测试,你们制定了测试计划以及测试用例,在这种场景下,使用 xray 就会凸显出不方便的地方,你有 payload,但是无法定制。
扫描器设计思路
基于上述的背景和现状,笔者考虑了一种基于 mitmproxy 的被动式扫描器,基于 mitmproxy 是考虑到该工具已经是一款非常成熟的代理工具,而且是开源的,且插件开发起来也特别的简单,非常适合在当前场景下使用。
整个扫描器设计思路如下图所示
1)正常访问路径是 浏览器–目标服务器,或者是 浏览器–Burpsuit–目标服务器,为了让流量经过 mitmproxy,借助浏览器插件如 SwitchyOmega 或者 burpsuit 的 upstream proxy servers 功能,把流量导入到 mitmproxy
2)mitmproxy 运行后,会调用插件,插件过滤掉不需要的流量,把需要处理的流量封装处理,把流量通过 udp 转发给扫描器引擎,插件把流量转发后,不会阻塞正常访问,插件的唯一作用是封装流量发送给扫描器引擎
3)mitm 插件通过 udp 协议把请求包发给扫描器引擎,这么设计的目的是让 mitm 和扫描器分离,可以分开部署两个组件,这样有个好处是如果要重启 mitmproxy,可以不影响扫描器进程,http 请求队列不需要重置
4)扫描器引擎启动扫描器线程,收到 mitm 插件的包后,做 md5 校验,如果包没问题,就放入 http 请求队列
5)扫描器线程实时查看 http 请求队列是否有数据,如果有,则从队列头部取出一个请求,接下来把请求依次分发给各个扫描组件执行
6)扫描器线程把请求分发给扫描组件,扫描组件包括 SQL 注入,未授权访问,等等一些比较容易自动化操作的漏洞
扫描组件设计思路
站在巨人的肩膀上,我先看看 xray 有哪些功能
XSS 漏洞检测 (key: xss)
SQL 注入检测 (key: sqldet)
命令/代码注入检测 (key: cmd_injection)
目录枚举 (key: dirscan)
路径穿越检测 (key: path_traversal)
XML 实体注入检测 (key: xxe)
poc 管理 (key: phantasm)
文件上传检测 (key: upload)
弱口令检测 (key: brute_force)
jsonp 检测 (key: jsonp)
ssrf 检测 (key: ssrf)
基线检查 (key: baseline)
任意跳转检测 (key: redirect)
CRLF 注入 (key: crlf_injection)
Struts2 系列漏洞检测 (高级版,key: struts)
Thinkphp 系列漏洞检测 (高级版,key: thinkphp)
把上面这些功能点进行分类,大体可以总结出这两类,输入检测类,第三方组件及 poc 验证类。
如果自研的扫描工具要支持这些功能,想想看这些扫描组件的设计思路。
SQL 注入检测
我们用 Burpsuit 测试的时候,测 SQL 注入常见的方法是把请求包放到 repeater 模块,依次尝试一些可疑参数,输入单引号,双引号,括号等,看返回是否有异常,比如输入 x’ and 1=1 / x’ and 1=2 如果返回的结果不一样,说明很可能这里是一个注入点,接下来再用 SQLmap 去跑注入点。
如果自动化跑这个测试应该要怎么做?首先事先准备好 payload,把各种场景的注入情况都考虑清楚,比如以下这个简单的 payload
1 or sleep(5)#
" or sleep(5)#
' or sleep(5)#
" or sleep(5)="
' or sleep(5)='
1) or sleep(5)#
") or sleep(5)="
') or sleep(5)='
1)) or sleep(5)#
")) or sleep(5)="
')) or sleep(5)='
把数字注入,字符注入,带 1 个括号,带两个括号的情况都考虑了
其次 payload 要方便探测结果,用基于时间的 SQL 注入 payload 就很好探测结果,如果服务器返回时间超过 sleep 的时间,就认为是存在漏洞,当然了因为网络原因可能出现误报,但是这个误报在可控范围,是能接受的。
最后遍历所有的参数,把 payload 附加到参数后面,这时候有两种思路,一种是每个参数依次遍历,假设一个 http 请求 URI 加 body 总共有 10 个参数,假设 payload 总共 100 个,那么依次遍历共产生 1000 个请求,如果每个请求间隔 100ms,就要 100s 的时间,另一种思路是所有参数同时遍历 100 个 payload,这样只有 100 个请求,总共只要 10s 时间,两种方法各有优劣,第一种方法优势是测试点精确,缺点是时间消耗比较长,第二种方法的优势是时间消耗短,缺点是容易出现假阴性,举一个例子,假设某个参数只允许纯数字,替换 payload 后整个请求就无效了,其他参数的注入点就会测不出来。
未授权访问
未授权访问测试方式较简单,我们平时测未授权访问是把请求包放到 repeater 模块,把 cookie 的内容删除后重新把请求发给服务器,如果返回的结果和未删除之前是一样的,那么就认为是未授权访问,当然人工测试的时候会选择性的测,针对静态文件不会测试这个漏洞,另外针对不需要权限的页面也不会测试,如果是自动化测试的话,没有人工筛选阶段,静态文件可以通过后缀来识别,而不需要权限页面就不方便识别,所有存在假阳性漏洞。
这里还有另外一个问题是并不是所有的站点都是通过 cookie 进行认证信息传输的,当然大部分站点都还是通过 cookie 传输认证凭证,有些站点会在 http 的头部新增一些凭证字段比如 token,这种场景下,就需要定制处理。
命令注入
回到上面的 SQL 注入测试,命令注入也类似,只是把 sql 注入的 payload 替换为命令注入的 payload,把所有的延时操作都替换为 sleep 命令,在 Linux 中,可以使用下面的命令连接符
&
&&
|
||
;
Newline (0x0a or \n)
` injected command `
$( injected command )
那么就可以构造出命令注入盲注
& sleep 5
&& sleep 5
| sleep5 |
|| slepp 5
; sleep 5 ;
\n sleep 5 \n
`sleep 5`
$(sleep 5)
另外还有一些通用的 payload,如
echo 1;sleep${IFS}9;#${IFS}';sleep${IFS}9;#${IFS}";sleep${IFS}9;#${IFS}
echo '1;sleep${IFS}9;#${IFS}';sleep${IFS}9;#${IFS}";sleep${IFS}9;#${IFS}
echo "1;sleep${IFS}9;#${IFS}';sleep${IFS}9;#${IFS}";sleep${IFS}9;#${IFS}
echo 1/*$(sleep 5)`sleep 5``*/-sleep(5)-'/*$(sleep 5)`sleep 5` #*/-sleep(5)||'"||sleep(5)||"/*`*/
echo "YOURCMD/*$(sleep 5)`sleep 5``*/-sleep(5)-'/*$(sleep 5)`sleep 5` #*/-sleep(5)||'"||sleep(5)||"/*`*/"
echo 'YOURCMD/*
来源:freebuf.com 2020-10-26 14:55:13 by: nobodyshome
请登录后发表评论
注册