一、背景
逻辑漏洞包含:
-
未授权漏洞:未经授权的用户或攻击者可以绕过正常的身份验证、访问或执行未经授权的操作。
-
垂直越权漏洞:允许用户或攻击者在系统或应用程序中获取比其授权权限更高的权限级别。
-
水平越权漏洞:允许用户或攻击者在系统或应用程序中获取其它用户相同权限级别的访问权限。
在货运场景中,典型的例子:
-
未授权漏洞:不需要鉴权参数即可获取数据。
-
垂直越权漏洞:企业普通用户可以查看企业管理员才能看到的数据。
-
水平越权漏洞:A 用户使用自己的鉴权参数可以查看 B 用户的订单。
随着纵深防御体系建设的越来越完善,通用漏洞的攻击一般都被被WAF 等拦截,而逻辑类漏洞的利用却无法被拦截,一旦被利用,可能泄露大量的敏感信息。
二、技术调研
SAST |
静态应用程序安全测试 |
分析应用程序的源码中的语法、结构、过程、接口等来发现程序代码存在的安全漏洞。 仅能发现通用性漏洞,且无法做全链路的测试。 |
IAST |
交互式应用程序安全测试 |
通过在服务端部署Agent程序,收集、监控Web应用程序运行时函数执行、数据传输,同时可准确确定漏洞所在的代码文件、行数、函数及参数。 如果能拿到鉴权参数、用户标识、鉴权函数,可以通过采集调用堆栈识别简单的未授权漏洞。但是鉴权函数采集比较难,需要研发提供,如果函数名变化后也会有误报漏报的情况。 |
DAST |
动态应用程序安全测试 |
模拟黑客行为对应用程序进行动态攻击,分析应用程序的回应。 黑盒扫描可以通过不同账号的API 重放,对比回显识别出部分逻辑漏洞,但是要考虑过滤一些公共API等。 |
三、方案综述
图1 漏洞检测系统-1
图1 漏洞检测系统-2
四、建设方案
(一)
准备工作
网关把测试环境的HTTP Request 发到 kafka 。扫描器去 kafka 上消费。
鉴权位置就是 Cookie 或者 token,需要提供收集核心业务的鉴权位置是在 URL 的参数、Request header、或者在 Request 的 body 里面。 后面都以 token 来指代鉴权参数。
做越权漏洞检测时需要不同的账号去做测试,从而生成需要不同的账号对应的 token。
不同的业务系统的鉴权参数生成方式不同,核心业务的鉴权参数是从账号中心统一生成,接入账号中心后即可自动生成 token。
申请测试账号,用于安全测试。
4、回显判断相同
在判断水平越权时,如果越权成功,回显就是相同的,但是回显中可能包含一些时间戳、traceid 之类的信息,影响判断。不能完全使用 rsp1.body==rsp2.body 的方式来判断。
这里我们采用了模糊哈希(fuzzy hash)算法,可以参考http://ssdeep.sourceforge.net/。模糊哈希算法是基于哈希算法的,和哈希算法的不同点在于,哈希算法是将整个文件作为定义域来求算结果,而模糊哈希算法则是先对文件进行分块,计算每一块的哈希值,然后将得到的一系列哈希值利用比较函数与其他哈希值进行比较,来确定相似程度。运营一段时间后,取一个最优的相似度即可。
5、相同 API 定义
API 的去重,关系到扫描测试的周期和推送漏洞时的去重。
如 admin/index.php?id=1 和admin/index.php?id=2 会判定为 相同 API。
但是如 index.php?_m=index&_a=push 和 index.php?_m= index&_a=pull 则要判定为不同 API。
(二)
基于DAST的黑盒检测
基于不同的越权逻辑,需要采用不同的重放逻辑。(如图3)
图3 检测判断逻辑
1、未授权访问
-
无鉴权参数
-
原始数据包req0重放
判断逻辑:
-
如果原始请求本身未包含 token,但是响应中确包含敏感数据,就判定为是一个未授权访问漏洞(无鉴权参数)。
-
如果原始请求本身包含 token,且响应包包含敏感数据,进入其他检测逻辑。
-
无效的鉴权参数
-
删除 token 的数据包req1重放
-
如果 req1的响应包包含敏感数据,就判定为一个未授权访问漏洞(无效的鉴权参数)(如下图4)
判断逻辑:
2、多账号水平越权测试
-
使用测试账号生成的 token 替换原始 token 做重放req2
-
如果 rsp0.body 与 rsp2.body 相似度达到一定的阈值,就判定为一个水平越权漏洞(如图5)
判断逻辑:
图5 水平越权漏洞测试
-
前期工作
-
req0请求时将其参数缓冲到 redis
-
req1 第二个请求来到,如果和 req0属于相同 API,如果属于不同的 token 下的则进行检测
-
发包逻辑:
-
id=1&user=b 作为req2
-
id=2&user=a 作为req3
-
假设 req0的参数是 id=1&user=a,req1 的参数是id=2&user=b。需要对参数做一个去重的笛卡尔积计算,然后去掉原始的参数,最终得到这些组合。
-
判断逻辑
-
先比较 req1 和 req2 ,如果它们的响应体的框架结构相同,且不是空结果如{"ret":1,"success":true},则判定为漏洞,问题参数是 id。否则进入下一步。
-
接着比较 req1 和 req3 ......
-
如果参数多的情况下,可能 user 参数有问题,然后 user和 pwd 同时存在时也有问题,则冒泡取参数多的参数上报。(如图6)
4、总结
(三)
公共API识别
通过对一段时间内不同 API 的body_bytes_sent 做标准差计算,获取标准差为 0 的 API,则这部分API 被判断为公共 API。(如图7)
(四)
API安全分析平台
2、接口去噪
http.response.code <400
and not (http.response.code == 307)
and not (http.user_agent matches "[email protected]")
and not (http.request.method matches "HEAD|OPTIONS")
and not (http.request.uri.path matches ".js.map|.css|.png|.jpg|.jpeg|.ico|.pdf|.svg|.bcmap|.woff|.ttf|.xlsx|?|*|..|@|:|;")
and not (http.response.headers["location"] matches "sso.xxx.cn|in-sso.xxxx.com")
and not (http.host matches ".*@.*oastify.com.*")
-
自动识别
图9 TF-IDF的计算公式
在该思路的指导下,我们可以将客户端向服务端某个时段发送的所有URL条请求视为文档(documents),然后将计算单条的URL文档下的关键词。以某个登录API为例:api.example.com/login/238,其中/login/238是URL组成部分中的path,定义了资源在服务器上的路径,“238”是本次请求所携带的可变参数。
-
人工合并
对于一些接口请求量小的,可能无法达到预定阈值的,可以通过人工添加合并规则的方式进行 API 合并。(如图10)
图10 人工API合并
-
新增API监控:第一时间 发现新增API,进行风险 评估
-
僵尸API监控:一段时间内 PV持续为 0 的接口,排查是否下线,减少暴露面
-
API 清单:可以更加方便的做横向排查和渗透测试
-
推进防护能力接入:SIEM、签名等
(五)
结合IAST的调用堆栈
此处只是使用了 IAST 的插桩原理,并未部署 IAST。CI 的监控系统运行比较稳定,插桩覆盖率也比较高,也有 traceid 可以做全链路的追踪。如图12是一个完整的链路信息,包含埋点的调用堆栈、执行的 SQL。
五、不足与改进
-
API覆盖率不全
-
自动化程度有待提高
-
目前全自动化的场景需要做很多的加白操作,垂直越权场景还未覆盖
-
复杂的场景无法自动完成,如需要多个接口配合完成的场景
-
目前对不含敏感数据的越权漏洞还不支持检测
参考:
越权漏洞自动化治理实践
https://security.immomo.com/blog/215
原文始发于微信公众号(货拉拉安全应急响应中心):货拉拉在逻辑漏洞自动化检测的实践
- 左青龙
- 微信扫一扫
- 右白虎
- 微信扫一扫
评论