背景
在企业发展过程中,内部应用数量急剧增加,且随着服务化的浪潮,内部服务之间的调用关系也日益复杂。复杂的服务调用关系也产生了复杂的安全问题。漏洞由单应用扩展到多应用服务化视角下产生,不可信数据可从边界服务输入流经多应用,最终在sink点产生危害。
目前58已有完善的Xast应用安全能力,但是对跨应用漏洞检测能力欠缺。自21年至今SRC召回漏洞中,跨应用漏洞占比达30%。为覆盖跨应用检测能力,降低整体风险暴露面,58在已有单应用静态污点分析能力下贴合devops,进行跨应用污点分析的探索与落地。
问题描述与分析
以下通过一个跨应用SQL注入问题,明确跨应用分析中需要解决的问题,及一些相关概念。
在该case中存在两个应用,WEB调用RPC服务。WEB获取name参数,调用RPC服务sayHello方法,RPC服务进行SQL拼接,最终在SQL执行处产生SQL注入问题。
为了适应devops的单应用并行CI、CD模式,及代码量等一系列问题,把相关应用代码仓库放到一起进行分析不是一个合适选择,所以我们通过单个工程的视角进行分析,通过摘要关联应用间污点信息。
1. 收集并关联应用间调用关系
根据框架代码特征收集跨应用函数调用点callsite点。(58自有RPC框架调用点会使用带有特定注解接口)
收集跨应用服务点callable点。(例中服务点会实现带有特定注解接口)
关联callsite与callable,关联跨应用调用关系。(例中服务点与调用点会使用相同接口)
2. 根据调用关系,自下而上进行逐层污点分析
下层应用对callable点进行数据流计算,设定外部入参为source点,sink点为漏洞触发点。
针对callable计算数据流,生成污点摘要,确定callable对应形参1会引起SQL注入,为上层应用提供一条sink策略。
上层应用加载下层提供sink策略,进行本层污点分析,并通过摘要关联跨应用数据流。
建模
1.应用间调用关系
1.1.收集跨应用callsite、callable
跨应用请求存在客户端调用与服务端两个端点,通过callsite记录客户端请求调用点,通过callable来记录服务端服务点。
根据不同的跨应用交互方式及不同的框架代码特征,在代码中提取callsite点及callable点,并在callsite点提取可关联外部callable关联信息,在callable提取服务信息。
以下为列举部分跨应用交互方式:
RPC
callsite:RPC函数调用点
callsite关联信息:依赖具体框架,如示例关联合约接口,客户端token
callable:RPC服务函数
callable信息:依赖具体框架,如示例关联合约接口、服务端token
HTTP
callsite:HTTP客户端请求调用点
callsite关联信息:路径、请求域名IP等信息
callable:HTTP请求controller方法
callable信息:请求路径、应用部署域名IP等
MQ
callsite:MQ客户端生产函数调用点
callsite关联信息:MQ的IP、域名、topic等信息
callable:MQ服务端消费函数
callable信息:MQ的IP、域名、topic等信息
1.2.构建应用内调用关系图
根据单个应用内收集的callable、callsite及依赖关系建立应用内调用关系图,通过点上tag记录关联信息。
图.3.1.2-应用内调用关系图
点
应用
callable:服务提供点
callstie :服务调用点,并在节点tag上记录callsite关联信息
边
应用 -> callable:表示callable归属于某个应用
应用 -> callsite:表示callsite归属于某个应用
callable -> callsite:表示该callable在执行过程中依赖了哪些外部调用。(通过应用内CG链路提取)
1.3.建立应用间调用关系图
通过应用间调用关系图记录全量应用间调用关系。
图.3.1.3-应用间调用关系图
点
应用
callable:服务提供点,并在节点上记录callable服务信息
边
应用 -> callable:表示callable归属于某个应用
callable -> callable:表示callable2在执行过程中,调用callable3
1.4. 图生成过程
针对单个应用callable及服务信息、callsite及关联信息、callable->callsite依赖关系进行收集
创建应用内调用关系图,创建app、callable、callsite、callable->callsite依赖关系
创建应用间调用关系图,根据应用内callableX->callsite依赖关系边中callsite关联信息,搜索应用间服务信息对应callableY节点,在应用间链接callableX->callableY,关联应用间callable依赖。如示例中图.3.1.2-应用内调用关系图中callable2->callsite2边中callsite2关联信息可找到图.3.1.3-应用间调用关系图中callable3节点,即可以在应用间图中关联callable2 -> callable3表示调用依赖关系
2.跨应用污点分析
2.1. 摘要设计
为了描述callable内数据流特征,需要设计摘要描述污点数据流特征,供上游调用方加载生成污点分析规则。
在该RPC服务中,入参为User对象,sayHello方法获取name字段并作为返回值返回。该case中sayHello可为上游提供一个由形参1到返回值的propagator摘要,且形参1是一个对象,其name字段引起了propagator行为。
根据该case,摘要的设计还需支持除sink外其他类型的数据流类型,并且需要通过Access Path支持针对类、集合等复杂数据结构的域敏感传播。
目前我们实现了Java下RPC的摘要设计:
<type, signature, from-postion, from-access-path, to-position, to-access-path>
type - 摘要数据流类型
source:RPC函数调用引入了不可信数据
propagator:污点流经RPC函数,并返回到调用点
sink:污点流入RPC函数,并触发漏洞执行
sanitizer:因RPC函数实现存在于其他仓库,在分析当前应用时,其他应用内数据流自然断开,所以策略中一般不需要生成RPC的sanitizer策略。
signature - RPC函数全限定名及参数列表
from postion - 污点传入位置
Pn :RPC函数的形参位置,表示第n个参数传入污点数据。
O :RPC函数的base对象,一般情况下,base类只是用来封装RPC函数,并不会绑定污点对象。
from access path - 污点传入位置access path支持域敏感,access path需要支持以下数据结构
Object filed
数组
集合类
to position - 污点传出位置
Pn :函数的形参位置,RPC数据传递只传值,即不会因为入参对象的filed改变导致调用方field改变。
O :RPC函数的base对象,一般情况下,base类只是用来封装RPC函数,并不会绑定污点对象。
R :RPC函数返回值,唯一会引起污点传出的位置
to access path - 污点传出位置access path支持域敏感,access path需要支持以下数据结构
Object filed
数组
集合类
2.2.运算顺序
跨应用的污点分析通过指定一入口应用开始计算:
在入口应用的应用内调用关系图提取callsite
通过callsite关联关系找到对应应用间调用关系图中callable,如图中callsite2找到callable3。
在应用间调用关系图中callable获取以该节点为根节点无环子树,如图callable3、callable4、callable5组成
在无环子树中,从叶子节点自下而上计算污点摘要。
完成根节点污点摘要,返回给入口应用加载,进行入口应用污点分析。
工程化落地
工程化落地最主要的一部分工作是怎样把整个分析过程融入devops体系,与应用、构建、环境等实体,构建、发布等行为结合。
1.应用调用关系
在CI、CD行为下,单个应用在CI阶段提取应用内调用关系,关联构建版本。在CD阶段,更新应用内、应用间调用图中对应构建版节点及调用关系。
2.污点分析扫描
跨应用污点分析扫描融入devops与单应用扫描有所不同,以下为在落地中的一些思考与解决方案:
计算不是以单个应用为单位,而是以一组有依赖关系的应用迭代计算,且这组应用在某时刻可能会因CD消息而变更。
解决方案:结合扫描需要时间,避免CD变化导致的调用关系变更,只选取某时刻调用关系来进行扫描。
构建是一个静态实体,一个构建归属于某应用,可以发布到任意环境,所以只有其发布才能明确其实际调用关系,调用关系为一个动态属性,所以跨应用污点分析不能关联到构建环节。
解决方案:在入口应用发布时触发跨应用扫描。
针对服务化的callable,可能存在大量上游应用调用同一callable。
解决方案:避免重复计算需要为callable的污点摘要进行缓存,缓存的key为以摘要计算目标callable为根节点无环子树对应应用及应用构建版本结构。即不仅需要callable相同且下游调用关系应完全对应且代码版本完全对应。
3.结合SCA
在静态分析范围只限于业务源码,而不包括依赖范围情况下,除污点数据流外还需要结合依赖版本进行漏洞判定。一般情况下,需要结合SCA的漏洞,可以在sink点所在应用关联该应用依赖版本进行联合判定。
安全运营
在跨应用视角下,漏洞威胁从单应用变更到多应用,在跨应用漏洞运营体系建设中,我们进行了以下设计:
通过制定漏洞修复点标准,把漏洞涉及多个应用问题转化为只存在一个最优修复应用问题,进而融入单应用工单体系。
在工单流程中增加二次确认机制,在安全运营确认漏洞及修复归属后,业务结合业务属性判定是否为最佳修复点,对于业务否认的,则重置漏洞归属,进行新的工单分配。
对于代码安全,修复点负责人只能看到自己应用内数据流,除此之外还需要提供全局视角信息,提供应用间数据关联信息,让修复人更明确漏洞产生场景。
未来规划
目前只支持Java场景,对于跨语言的传输方式,需要设计语言兼容的摘要。
目前只支持RPC场景,需要支持HTTP、MQ等数据传输方式。
应用间调用关系,在安全方向,可以借助其他安全能力,如IAST等动态能力补充或优化数据。也可封装应用间调用关系提供元数据,为研发提供应用间调用关系梳理提供抓手。
参考
https://www.blackhat.com/us-21/briefings/schedule/#do-you-speak-my-language-make-static-analysis-engines-understand-each-other-22797
https://mp.weixin.qq.com/s/NG9Qc8PQveu7r1_NbKZz7Q
欢迎留言讨论,也可联系作者邮箱:k6ymaker@gmail.com