在设计IAST时,我们可能会遇到一些困境。这些困难不仅仅来自于技术层面,而且可能来自于架构基础的局限。
IAST的模式
IAST模式可能有很多,如果目前就笔者之前接触过的场景,大致分为以下几种:
代理扫描模式
镜像旁路模式
插桩扫描模式
IAST其实并不算是单一产品,简单来说它是借助多个实体的联动,通过主被动发包,最后进行命中结果判定的安全产品。
代理扫描模式
这种模式的流量一般是定向的,在代理处可以通过数据包打标进行隔离。如果数据包有特征标记,是很难触发引擎的错误判定的。
但是这里的问题在于,代理扫描如果要打入污点数据(payload),那就必须牺牲测试的效率,将总流量放大不少。
一般这种情况,可以通过容器化单独启动安全测试环境,这样的话可以隔离流量,对业务方的数据污染和运维压力也会更小一些。
但是这样有几个弊端:
安全测试环境的迭代很难保持,产品如果有新的的特性,可能不一定来得及在该环境中更新。
业务维护成本高,如果安全侧有需求,QA测试需要单独花人力去维护和造数。
某些场景下,代理模式比较难以适应,比如说双向HTTPS加密、内容自定义加密、不接受脏数据、存在csrf token、存在大量验证码等场景。
镜像旁路模式
这个其实是比较普遍使用的,作为大部头流量落地 的主力军,离线分析是能让业务方少诟病的。
镜像旁路的好处在于,我们在代理集群(服务器)配置好加解密措后,再导向流量清洗集群。
这样的话,能弥补代理模式的一些遗憾,比如对实时性要求不高,流量不会放大太多,流量加解密更方便。
但是,这也会带来代理模式没有的难题,比如在清洗时会加重安全侧的压力,而且也会把污点数据无差别的带入QA测试的结果中,让安全部门和业务技术方的资源矛盾提升。
当然,如果需要重放流量,也会遇到一些跟代理模式类似的难题。
插桩扫描模式
这个agent不同于代理proxy,不是在pc端/代理服务器部署,而是在业务服务器上部署的。
业界做过的实践,可以是runtime agent或是RASP等等,这些都是为了拿hook关键函数,去确认流量链路的。
当然,除了在server端启动应用时加载包,也可以在Idea等编辑器调试时使用IAST插件,作为流量的补充。
而插桩扫描模式,又分为主动扫描和被动扫描两种:
主动插桩模式
在关键函数hook到流量后,会添加poc或者flag进行扫描,这样能解决代理/镜像层面不好解决的一些难题。
被动插桩模式
主要是在监控source-sink流,是否进行了安全过滤。如果没有则判定最终会流向的风险函数,可能会导致漏洞的发生。
其实被动插桩模式,有点类似于针对白盒AST树的方式,区别在于是否有流量输出罢了。
IAST终端分类
对于IAST而言如果要分段(定义可能有差异),初始态是source,风险态是sink,落地态是result。
如果是讨论落地态,比如数据库执行记录,或是落到了表达式调用,或是命令级别执行的监控里,那就说明这个链路是可能存在问题的。
那么,我们如何选择终端去判定结果呢?这里主要有几个选择:
数据库代理(防火墙)
在sql语句落库的时候,我们能通过数据库防火墙或者类似的产品,检查是否有污点数据带入。
如果有的话,针对sql记录后进行拦截,也能达成我们IAST-sqli联动的效果。
笔者记得似乎有人用Nginx代理的方案,实现sql旁路监控。 如果代理旁路检测有sqli语句执行,构造相反的语句进行翻转,或者发送命令让数据库进行sql事务回滚。
但是这种模式也有些问题,一是兼容各种数据库比较难,二是通信可能加密,三是检测功能单一只能用于模块集成。
所以,这种检测局限性还是比较高的。
Hook Agent
这种模式的实现讲起来其实也不难,这里拿java agent举例。
1. premain
在启动态时,目标JVM启动的同时加载Agent,启动时随同–javaagent
一起传入的程序参数。
在启动时,类加载前定义类的TransFormer,在类加载的时候更新对应的类的字节码。
2. agentmain
在运行态时,通过修改类字节码,重新hook关键函数,实现结果落地记录,步骤整体分为两步:
- 注册类的TransFormer
- 调用retransformClasses函数进行类的重加载
但是Hook Agent的实现方式也有其固有的局限性,java是基于jvm启动项的。一般这类模式,对于项目侵入性一般不小,处理兼容性和升级运营问题的时候,会花费安全运营团队特别多的精力。
而且,Hook Agent模式有点像为了IAST而IAST,没有其他附加的实用功能的话,很难说服业务方诚心推进接入。
本身这种东西也只能在测试环境上,如果不能一键化容器化,很好的嵌入CI/CD,就更鸡肋了。
当然,目前也有了一些开源的IAST产品,譬如之前火线出品的洞态IAST,这块儿设计的相对成熟。
RASP agent
RASP agent要实用些,但相对来说臃肿了很多。
你说如果RASP部署到生产非核心环境还好,如果部署到测试环境,着实有点脱裤子放的味道,RASP对资源的占用率也需要着重控制的。
而且生产环境你用这个做被动IAST还行,如果要上主动模式,出事儿的时候,运维开发都得往安全身上甩锅,然后大家集体背C滚蛋就不太划算了。
目前市面上百度RASP和字节的Elkeid(主要功能HIDS)都做的不错,拿来联动可以考虑下。
应用日志埋点
这个其实要看日志系统的内容丰富度,有些在终端埋点丰富的应用日志系统,联动流量入口打上flag,就能检测到在终端落地的流量。
当然,想要检测诸如XSS和模板注入之类的漏洞就没有必要依赖这个了。如果真想关联检测,可以用dns请求的方式进行佐证。
业内的实践的话,可以看看PAB利用开源的日志系统CAT做的IAST,检测精确度可能有待提升,毕竟是依赖中间态而不是终态做检测的。
但不得不说,这确实是性价比高的一类检测手法,也把兼容性的压力分给了架构运维部门,安全部门的成本要降低很多。
IAST的使用延伸
安全工程师在做IAST检测的时候,是可以用于挖掘xday的。
但实际上使用IAST发现漏洞时,人本身是更注重结果的,更多的会关注漏洞成因,最多梳理单系统的sink-source。
然鹅,我们利用IAST做联动标记,是可以尝试梳理出完整的攻击链条的。
在业内的话,记得好像鹅厂和V厂也做过类似的实践。
另外笔者在之前,也尝试过借助流量链路作为其中一环来构建资产库,最后可以用威胁建模模式的方式输出成果。通过半自动化架构评审的模式,能覆盖45%+的项目,此处就不多赘言了。