点击上方·关注我们吧
发现有个地方截图错了,重新发一下-。-
首先查看常规项目中,amf的配置入口,MessageBrokerServlet类处理/messagebroker/*请求
接下来跟下去查看流程,在MessageBrokerServlet的service方法中,先将HttpServletRequest等对象存到FlexContext的变量ThreadLocalObjects中
随后根据endpointPath去获取对应的endpoint
而web.xml已经指定过配置文件
在配置文件中可以看到是由AMFEndpoint来处理/messagebroker/amf这个请求(endpointPath),即endpointPath的endpoint就是AMFEndpoint类
回到MessageBrokerServlet.class
在得到处理请求的类后就使用该类的service方法处理请求
在前面的代码中可以看到endpoint的对象类型是Endpoint,而Endpoint是一个接口,所以要找到该接口的实现类
所以实际就是BaseHTTPEndpoint的service方法来处理/amf请求
在service方法中,会交由filterChain.invoke处理上下文内容
filterChain:
createFilterChain是一个抽象方法
需要找到实现他的子类,即AMFEndpoint
跟进SerializationFilter类查看invoke方法
其会获取输入流封装到deserializer对象
具体可以看到getHttpRequest方法返回的内容就是之前存在threadLocalObject里的信息
initialize方法:
随后进入到readMessage处理上下文内容
在readMessage方法中,会执行三次readUnsignedShort方法分别获取version、headersCount和bodyCount
漏洞触发主要在bodyCount
走到readBody
进入到readObject方法
因为之前初始化的时候赋值过,所以这的amfIn就是Amf0Input对象,即这里的readObject其实是Amf0Input的readObject
跟进Amf0Input查看readObject方法,该方法会先读取传入的数据字节,然后根据不同的属性进入对应的方法进行处理
查看readObjectValue
已知type是amfIn.readUnsignedShort 获取得来,type是2字节,这里会首先读取1字节,当读取的值是17时(序列化时写入)就会再初始化一次avmPlusInput,并进入到readObject方法
在readObject方法中,再读取1字节
跟进readObjectValue方法,当读到的值是10时(序列化时写入)就会进入到readScriptObject方法
在readScriptObject方法中,会根据传入的类名返回一个对象
跟进getClassFromClassName查看具体实现
createClass方法会返回一个初始化的对象
然后会将对象传进getProxyAndRegister方法查找对应的属性代理,用于处理对象的属性读写,如果注册表中存在,则传进createDefaultInstance方法实例化对象
然而注册表里只有几个异常和Map对象
具体可以看getRegistry方法:
private static boolean preregistered = false;
所以流程会将对象传入createDefaultInstance方法进行实例化
查看createDefaultInstance可以看到返回了一个实例化对象
在获得一个实例化对象后,会判断该对象是否实现了Externalizable接口,如果实现了则进入readExternalizable方法,在该方法里使用readExternal方法进行反序列化,漏洞在此触发
按照流程,想要利用这一步的反序列化,需要找一个实现了Externalizable接口且有公共无参构造函数的利用链,比如sun.rmi.server.UnicastRef
改一下ysoserial的JRMPClient即可得到一个POC:
import flex.messaging.io.SerializationContext;
服务器启动JRMP,运行POC
java -cp ysoserial-1.0.jar ysoserial.exploit.JRMPListener 1234 ROME "calc"
当然这只是基于实现了Externalizable接口的反序列化利用,在判断即使没有实现Externalizable,流程依旧会往下走其他反序列化逻辑,也就是说,哪怕没有实现Externalizable接口,也可以找实现了Serializable 接口的链来进行利用,当然还是需要有公共无参构造方法
写了个利用工具
https://github.com/novysodope/AMF\_JRMP
不出网参考
https://github.com/codewhitesec/ColdFusionPwn
ColdFusionPwn直接下载他的发布版本使用会提示找不到主类,建议下载源码用idea运行,参数直接[-s|-e] [payload type] '[command]' [outfile]
在往后的审计中,如果看到有引用
<dependency>
或者jar包中用到这种的
基本可以确定存在flex相关漏洞