从源码看Log4j2、FastJson漏洞( 三 )


文章插图
 
查看StrSubstitutor类的
org.apache.logging.log4j.core.lookup.StrSubstitutor#substitute方法,美滋滋的发现调用 resolveVariable 方法后获取到了解析的值 。

从源码看Log4j2、FastJson漏洞

文章插图
 
resolveVariable 方法内部调用getVariableResolver()方法获取对应的值解析器,此次获取 JavaLookUp 。继续追下去发现version的获取就是从系统环境变量中取得的 。
从源码看Log4j2、FastJson漏洞

文章插图
 

从源码看Log4j2、FastJson漏洞

文章插图
 
终极解决方案2.15.0读完源码不难得出结论:如果不让代码执行${}的解析不就行了,即不使用LookUp机制 。
如下图表示了noLookUps的默认值 。这也说明了为什么解决方案是增加JVM启动参数:
-Dlog4j2.formatMsgNoLookups=true 。
从源码看Log4j2、FastJson漏洞

文章插图
 
为什么升级为2.15.0后Bug就修复了呢?因为在新版本中默认会使用
SimpleMessagePatternConverter,同时不使用 LookUp 机制 。
如下图所示:
从源码看Log4j2、FastJson漏洞

文章插图
 
2.16.0
  • 默认禁用JNDI的访问,用户需要通过配置 log4j2.enableJndi 参数开启
  • 默认允许协议限制为:java、ldap、ldaps,并将ldap协议限制为仅可访问Java原始对象
  • Message Lookups被完全移除,加固漏洞的防御
在Log4j2升级至 2.16.0 时我们天真的认为已经结束了,万万没想到,2.16.0 又爆出来新的 DOS 拒绝服务攻击漏洞(没完了不是) 。
从源码看Log4j2、FastJson漏洞

文章插图
【从源码看Log4j2、FastJson漏洞】 
具体说来是,Apache Log4j2 的 2.0-alpha1 到 2.16.0 版本,均未能防止自引用查找的不受控递归 。
当日志配置使用了带有上下文查找的非默认模式布局时(例如$${ctx:loginId}),控制线程上下文映射(MDC)数据输入的攻击者,便可制作一份包含递归查找的恶意输入数据,从而导致进程因堆栈溢出报错而被终止 。
如果目前不方便升级版本的话,可以采用下面的两种方法来缓解此漏洞:
在日志配置的 PatternLayout 中,用 %X、%mdc 或 %MDC 来替换
从源码看Log4j2、FastJson漏洞

文章插图
 
或${ctx:loginId} 等Context Lookups
在使用外部数据(HTTP Header或用户输入等)的地方,删除对Context Lookups的引用(如
从源码看Log4j2、FastJson漏洞

文章插图
 
或${ctx:loginId} )
2.17.0
  • 只有配置中的lookup字符串才允许递归解析 。并且仅解析最顶层的lookup,不解析任何嵌套的lookups 。
  • 将 JNDI 仅限于 java 协议 。默认情况下,JNDI 将保持禁用状态 。将 JNDI 启用属性从"log4j2.enableJndi"重命名为"log4j2.enableJndiLookup"、"log4j2.enableJndiJms"和"log4j2.enableJndiContextSelector" 。
  • JNDI 仅限于 java 协议 。默认情况下,JNDI 将保持禁用状态 。启用属性已重命名为"log4j2.enableJndiJava" 。
扩展:FastJson 漏洞远程代码执行漏洞在业内还是比较多见的,除了此次的 Log4j 漏洞,我们再来看看其他工具的漏洞吧!
在2017年3月15日,fastjson官方主动爆出fastjson在1.2.24及之前版本存在远程代码执行高危安全漏洞 。攻击者可以通过此漏洞远程执行恶意代码来入侵服务器 。
关于漏洞的具体详情可参考:
https://github.com/alibaba/fastjson/wiki/security_update_20170315 。
漏洞原因FastJson 提供 autoType 功能,在对JSON字符串进行反序列化的时候,会读取@type到内容,试图把JSON内容反序列化成这个对象,并且会调用这个类的setter方法 。黑客可以利用这个特性,自己构造一个JSON字符串,并且使用@type指定一个自己想要使用的攻击类库 。
常用的攻击类库是
com.sun.rowset.JdbcRowSetImpl,这是sun官方提供的一个类库,这个类的dataSourceName支持传入一个rmi的源,当解析这个uri的时候,就会支持rmi远程调用,去指定的rmi地址中去调用方法 。
{"@type":"com.sun.rowset.JdbcRowSetImpl","dataSourceName":"rmi://localhost:1099/bad","autoCommit":true} FastJson 的修复方案在 1.2.25 版本中 FastJson 新增了黑名单机制,如果@type中的类是黑名单中的则直接抛异常 。


推荐阅读