聊聊今天 log4j 的大瓜
今天安全圈狂欢了,Java 非常常用的日志库 Apache log4j 被爆出远程代码执行漏洞。就是说,别人可以通过一系列骚操作,在你的服务器上执行任意的程序。而且这次的漏洞利用起来简单易行,只要在日志里记录了可以通过外部输入的内容。比如 Minecraft 的开源服务器,任何人只要发一条刻意设计的消息,就可以黑掉服务器,因为 Minecraft 服务器在日志里记录了每一条聊天消息。技术细节有很多文章分析过,就不具体讨论了。
主要想推测一下这个漏洞是怎么产生的,是因为粗心吗?
通常情况下,日志库只有一项任务:把日志字符串按照配置保存到文件或者其他什么地方,不需要管字符串里有什么。如果只是这样,很难产生什么安全漏洞。但是 log4j 不仅仅做了这件事,还支持在日志里插入变量,在运行时解析这些变量。最要命的是,还支持通过 JNDI 加载远程代码来解析变量。这个漏洞是在 2014 年发布的 log4j 2.0 中引入的^LOG4J2-313,也就是说已经存在 7 年之久了。
开发人员在这些年里,都没有意识到危险性。2017 年增加选项允许关闭和漏洞密切相关的 lookup 功能的时候,并不是出于安全考虑^LOG4J2-2109。同样,在漏洞公开前 10 天把这个选项从默认不关闭 lookup 改为关闭时,也只是出于设计上造成“困惑”的考虑,也不是意识到存在重大安全隐患^LOG4J2-3198。
这个漏洞生效,需要服务器使用相对老旧的 JDK 版本,因为 JDK 8u191 之后的版本, com.sun.jndi.ldap.object.trustURLCodebase
被设置为 false
,JNDI 不再能使用 LDAP 加载远程代码,而在此之前是有明确的方法进行代码注入的。[^8u191][left]
现在我们来按时间顺序回顾一下这个漏洞是怎么来的。
90 年代,远程对象调用技术很流行,JNDI 支持通过 LDAP 加载远程代码是个特性;
JNDI 作为 J2EE 规范的一部分,成为 Java 应用实现模块解耦,让系统更可维护的重要技术;
log4j 的开发人员认为支持 JNDI 很有用,可以给记录日志提供便利,就加进去了;
JDK 8u191 之前,JNDI 通过 LDAP 加载远程代码这条路是通着的,于是……
几点思考:
所有用户产生的内容,都不可信任,务必小心处理;
一个复杂的历史久远的系统,没有人能全盘掌握,很容易存在潜在安全问题;
系统的默认选项应该是只提供必要功能,不要有 Magic;
系统需要保持简单,必要时革命,背负太多历史包袱,迟早被坑。
版权声明: 本文为 InfoQ 作者【Justin】的原创文章。
原文链接:【http://xie.infoq.cn/article/9bf63bde0a1b83cb0d7e9d839】。文章转载请联系作者。
评论