如何跟踪log4j漏洞原理及发现绕WAF的tips

本文详细介绍了Log4j漏洞的形成原因,包括官方GitHub上的关键commit,以及如何跟进漏洞产生原理。此外,还分享了如何绕过2.15.0-rc1版本的防护,分析了URI解析过程,并提供了针对WAF的LDAP绕过提示,如IP包裹、避免特定关键字等。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

log4j漏洞的形成原因已经有很多分析文章了,这里说一说我是如何在了解到有漏洞后,跟进漏洞产生原理的,以及发现的一些绕WAF tips

跟进漏洞产生原因的思路

如何发现漏洞产生原因的

了解到log4j <=2.14.1 存在RCE的情况,我马上跑到其官方github看了一下,发现commit记录中有两个关键commit
在这里插入图片描述

  • 第一,log4j不再自动对消息中的lookup进行格式化,第一时间看到不是很懂
  • 第二,限制JNDI默认支持,限制通过LDAP访问服务器和类

这两个点很容易联想到是不是跟JNDI攻击有关系,毕竟RMI和LDAP很容易做到RCE。跟进commit看看具体的修改情况,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的tips

URI解析

看完rc1版本的绕过后,又想了一下,防御工具可能会有针对性的做一些关键字检测,所以我打算从LDAP更深层的源代码看看有没有对字符串变形的可能性。

跟着this.context.lookup(name)处向下跟进到com.sun.jndi.url.ldap.LdapURLContextFactory#getUsingURLIgnoreRootDN方法,代码如下
在这里插入图片描述
注意var0也就是输入是完整的"ldap://192.168.34.96:1389:/a",而后var2可以使用getHost和getPort方法获取host和port,说明var2对象在创建时解析了ldap地址。跟进LdapURL类到达Uri#parse方法

  • com.sun.jndi.toolkit.url.Uri#parse
private void parse(String var1) throws MalformedURLException {
   
    int var2 = var1.indexOf(58);
    if (var2 < 0) {
   
        throw new MalformedURLException("Invalid URI: " + var1);
    } else {
   
        this.scheme = var1.substring(0, var2);
        ++var2;
        this.hasAuthority = var1.startsWith("//", var2);
        int var3;
        if (this.hasAuthority) {
   
            var2 += 2;
            var3 = var1.indexOf(
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值