文章插图
log4j漏洞的形成原因已经有很多分析文章了,这里说一说我是如何在了解到有漏洞后,跟进漏洞产生原理的,以及发现的一些绕WAF tips跟进漏洞产生原因的思路如何发现漏洞产生的原因的
了解到log4j <=2.14.1 存在RCE的情况,我马上跑到其官方github看了一下,发现commit记录中有两个关键commit
文章插图
- 第一,log4j不再自动对消息中的lookup进行格式化,第一时间看到不是很懂
- 第二,限制JNDI默认支持,限制通过LDAP访问服务器和类
https://github.com/Apache/logging-log4j2/commit/d82b47c6fae9c15fcb183170394d5f1a01ac02d3 这个commit中,对
org.apache.logging.log4j.core.net.JndiManager.JAVA进行了大量修改,特别是在lookup方法中,加了很多代码
【私信回复“资料”获取log4j的复现/修复教程】点击查看网络安全学习攻略
文章插图
仔细看了一下,没有修改前,lookup方法直接通过this.context.lookup(name)执行JNDI操作,没有任何过滤或者限制,而新增加的代码在限制JNDI服务器、类 。当天晚上看到payload后,马上对log4j 2.14.1版本尝试验证一下,并在JndiManager#lookup方法中断点看到如下
文章插图
很明显,name就是payload中给定的,仔细看一下调用栈就可以发现,log4j会对字符串中的${}自动解析,也就是前面提到的commit备注信息中写到的 。
如何绕过2.15.0-rc1版本
看到rc1版本存在绕过的消息,又来看看官方github仓库的commit记录,里面有一条在更新到2.15.0-rc1版本后的commit记录,提交的信息是"handle URI exception",即处理了URI出错的情况 。修改代码的情况如下图
文章插图
JndiManager#lookup方法处给catch语句中添加了两行代码,记录URI解析错误并返回null 。而添加这两行代码前,此处只有一行注释,因此catch报错后会继续向下执行this.context.lookup,也就意味着前面try语句中的代码报错后,会继续执行JNDI操作,绕过也就来自于这里 。
来看看try语句是怎么写的
文章插图
代码比较长没有完全截进来,关键点是进入lookup方法后,立即将name变量送入URI类的构造函数中,此时只要URI的构造函数对name字符串解析出错,即可跳转到catch语句,进而向下执行到JNDI操作 。
那么我们要关注的点就是让new URI(name)处报错,但是name又能被jndi正常识别 。好在我们用marshalsec构造ldap服务时,不需要关心uri长什么样,所以可以在uri上做文章 。
跟踪源代码可以查看到URI对字符的支持情况
文章插图
数字、字母大小写这些就不说了,其它可打印字符也不多,从上面的注释中可以看到URI对反引号`,空格,尖括号<>并不支持,基于这一点,可以做个简单的实验
文章插图
空格和括号同样报错,就不重复截图了 。回到前面提到的2.15.0-rc1版本对JndiManager#lookup方法的修复情况,并没有在catch语句中添加返回操作或报错,程序遇到报错后,会继续向下执行,从而造成危险 。
由于找了很久都没有找到log4j-core-2.15.0-rc1.jar这个包,所以自己写了个函数模拟一下绕过的场景
文章插图
LDAP绕WAF的tipsURI解析
看完rc1版本的绕过后,又想了一下,防御工具可能会有针对性的做一些关键字检测,所以我打算从LDAP更深层的源代码看看有没有对字符串变形的可能性 。
跟着this.context.lookup(name)处向下跟进到
com.sun.jndi.url.ldap.LdapURLContextFactory#getUsingURLIgnoreRootDN方法,代码如下
文章插图
注意var0也就是输入是完整的"
推荐阅读
- 微服务项目到底如何分模块?
- 扬声器如何检测
- XAI 可解释的AI :如何使用LIME 和 SHAP更好地解释模型的预测
- 春季养生该如何健康补血 需做好饮食调理
- 长期酗酒易可引发酒精肝 经常喝酒的人如何养肝
- 春季经常喝酒如何养肝 节后多吃枸杞养肝排毒
- 春季如何让宝宝更好的午睡 睡多长时间比较好
- 春季如何养肝最有效 不同体质人养肝方法不同
- 红茶种类味道差别大吗,红茶伊丽莎白
- 如何处理打印机卡纸