零信任理念有望缓解fastjson软件漏洞
动态信任,缓解漏洞
基于线程隔离的资源访问
精细化访问控制
应急响应平滑下线
实时安全策略变更
假定被攻击
使用高版本的jdk的增加攻击难度
使用反序列过滤器
按需权限原则
和RASP、安全sdk、沙盒的不同
参考资料
前言
业界公司有Google基于“Zero Trust”原则落地实现了自己的零信任架构 ---- BeyondCorp,微软对应有Azure Zero Trust Framework ,至此很多人谈零信任主要是谈论在边界的网络安全控制和数据安全层面,以为只有IT部门需要关注零信任理念。
实际上做零信任(ZT)提供了一系列概念和思想,旨在面对失陷网络时,减少在信息系统和服务中执行准确的、按请求访问决策时的不确定性。零信任架构(ZTA)是一种企业网络安全规划,它利用零信任概念,并囊括其组件关系、工作流规划与访问策略。
在软件安全领域零信任的概念远远没有被滥用,可以扩展最小权限、安全需求、资源身份控制原则,实现一种动态的零信任软件安全方法论。
很多人一边吐槽fastjson的安全性,一边被迫营业每次紧跟版本频繁升级,其实升级是完全的苦劳,基本不能解决软件安全架构问题。只想着升级fastjson的版本这一件事情未免太急,自己把自己局限攻击者的思维里了,问题焦点不是如何升级而是如何防护威胁。本文主要探讨以fastjson安全防护场景为例,演示的一种结合零信任理念的软件安全架构方法论。
动态信任,缓解漏洞
目前对于fastjson这类的第三方软件的难点是:
发现安全问题推动升级总是不容易的,业务不清楚用的当前版本是多少,该如何升级,验证起来又费时费力。升级是解决分析的手段,不是安全工作的目的,也不是软件安全要达成的效果。
如果一次升级是苦逼的全员覆盖,大伙儿大干三十天搞定,技术复查验证也OK,只能说是仅仅成功了一半,做出新意、超出预期的ROI比才是好的。
只有谷歌这样具备project zero这样的团队才能提前发现如ghostscript的第三方漏洞,跟风者以攻待防,以有涯待无涯,case by case紧跟漏洞的思路不能保证安全措施会不会失效。威胁情报时效性不足?安全资产的梳理?修复方案的有效性?jackson\gson有没有类似的问题?都是”黑盒“状态,这就让fastjson升级这件事的安全效果也不是绝对的了。
业务部门不需要安全赋能,如果安全和法务、行政一样,从来没见过法务这么想去赋能,安全应该是简单的,单纯从业务方的角度谈谈如何通过不升级来简单缓解此类的风险。
思考路线是:什么是以最低的成本做安全,不担心黑白名单反复绕过?处置安全风险不仅仅有解决这一条路,缓解、阻断、监控和隔离风险也是个安全工作合理做法。
在我们这个行业是不能不创新的,下文将不考虑黑白盒工具,rasp之类的安全视角的纵深防御措施,只谈谈未来在软件安全领域借鉴零信任原则处理fastjson之类的第三方软件的三种办法。
基于线程隔离的资源访问
不信任代码和应用,对数据资源的访问默认隔离。线程隔离的策略引擎技术可以参考Hystrix\Sentinel 为代表的技术,提供基于调用关系分析的信号量或者线程隔离的资源保护思路。核心在于定义runtime.getRuntime.exec()、RMI网络连接请求等敏感方法是需要保护的”资源“,灵活配置规则作为策略管理器,实现不论线上fastjson是否是低版本,利用”监控和隔离“保护应用程序只容许执行业务定义的动作,客观上缓解漏洞风险。
底层原理是每次调用敏感的线程时,请求通过计数信号量进行限制,当信号大于了最大请求数0,即触发危险函数场景,进行限制,调用fallback接口记录日志或者安全介入处理。
以下是示例代码:
进入资源方法之前,基于创建Entry,Entry获取查找资源关联的Chain信息,如果找不到则创建,并基于安全责任链模式调用entry()方法
资源方法调用检查
资源方法调用完成后,通过Entry触发的exit()逻辑
精细化访问控制
现在安全普遍给业务的一揽子解决方案是基于服务、主机、git仓库层面,让代码直接升级fastjson版本文件,业务想到咱也不懂安全,咱也不敢问,主要工作量是频繁的单测,业务联调,担心fastjson升级引起的的线上兼容性问题。
线程链路隔离的理念通过来源访问控制,即根据资源的请求来源(origin)限制资源是否通过,若配置白名单则只有请求来源位于白名单内时才可通过(通过打标调用链区分业务正常调用JNDI请求的,还是反序列gadget触发的链路);
若配置黑名单模式则请求来源命中黑名单时不通过,其余的请求通过(自查没有JNID或执行命令的需求,阻断runtime调用)。将安全的边界从主机网络下钻为“资源组”,基于状状会话的数据进行动态评估。以零信任理念控制资源的细粒度到最小的维度,让解决安全问题的侵入性动作最小。
应急响应平滑下线
说句大实话,基于安全投入的性价比,老板们是可以接受非重点业务被黑的,但是不能接受被黑后安全团队不能发现。使用微服务的隔离理念,在业务机器A触发fastjson漏洞利用的逻辑时按照保护算法自动下线,线上流量灰度并自动迁移到别的机器B,实现漏洞秒级止损,然后由安全人员分析服务,实际攻击行为完全不影响业务运行,机器被入侵也不影响内网其他资产。
实时安全策略变更
Never Trust, Always Verify。在云服务PaaS的企业内网场景下,不知道业务方真正执行的代码是什么,不知道是不是升级了fastjson,不知道市面会不会有新的0DAY利用,根据动态规则处理Thread线程数策略、根据监控数据随时下发调用链处理逻辑,可以 通过自动化的身份管理、认证及授权能力,有效减少安全人员工作量,实现秒级的规则变更,实现关键基础设施安全性和稳定性之间的权衡。
假定被攻击
使用高版本的jdk的增加攻击难度
基于rmi的利用方式:适用jdk版本:JDK 6u132, JDK 7u122, JDK 8u113之前、基于ldap的利用方式:适用jdk版本:JDK 11.0.1、8u191、7u201、6u211之前。业务可以使用高版本的jdk阻碍漏洞的直接利用,项目代码中增加如下的jvm配置。
System.setProperty("java.rmi.server.useCodebaseOnly", "true");System.setProperty("com.sun.jndi.rmi.object.trustURLCodebase", "false");System.setProperty("com.sun.jndi.cosnaming.object.trustURLCodebase", "false");System.setProperty("com.sun.jndi.ldap.object.trustURLCodebase", "false");
当然利用LDAP返回序列化数据,触发本地Gadget可以绕过高版本的限制,所以我们需要多种防御方式配合。
使用反序列过滤器
反序列化过滤器是jdk的新机制,反序列化漏洞本身不是java的问题,一般是反序列工具的程序设计问题,当然这个措施对fastjson效果有限。
https://docs.oracle.com/javase/10/core/serialization-filtering1.htm#JSCOR-GUID-55BABE96-3048-4A9F-A7E6-781790FF3480
按需权限原则
Runtime Security Manager Integration with Java Card Runtime …
Securitymanager是JAVA沙箱安全最核心的部分,SecurityManager类包含了大量访问控制的方法。开启安全管理器意味着程序将在沙箱环境下运行。policy策略是指定某些代码对某些资源具有哪些操作权限,策略文件包含了将代码来源映射为权限的指令。下面是一个使用于fastjson的的策略文件,对应禁止网络连接,禁止执行命令:
效果为在业务的启动方法中,添加上面的不到10行代码,就可以阻断fastjson的ldap、rmi协议的外链,解决ssrf、RCE风险。如果业务有对外的网络需求,自定义放宽ip请求的名单即可。
极端情况下攻击者使用自定义的类加载器、反射手段都可以绕过securitymanager,实际场景中需要更细化的风险处理。
和RASP、安全sdk、沙盒的不同
零信任和软件安全关联的思路对于刚接触零信任的读者们很难理解,这仍然是一个相对较新的概念。不过框架并不重要,真正有难度的是工程化落地。根据笔者观察,国内公司有蚂蚁金服有内部落地 Workload 场景下的服务鉴权能力的零信任架构体系,改造jvm和k8s解决了身份标识和授权模型问题。未来基于滴滴的SDS和Alibaba JVM-SANDBOX容器搭配lstio架构同样可具备这样的能力。
为大家留一个思考问题,上述的基于线程隔离的漏洞缓解方案和百度rasp,陌陌安全sdk、系统级沙盒有什么不同,欢迎留言探讨。
参考资料
https://www.anquanke.com/post/id/151526
https://xz.aliyun.com/t/3210
https://kingx.me/Restrictions-and-Bypass-of-JNDI-Manipulations-RCE.html
https://yq.aliyun.com/articles/57223?&utm_source=qq
https://www.anquanke.com/post/id/151398
https://yq.aliyun.com/articles/740195