The REST Plugin is using a XStreamHandler with an instance of XStream for deserialization without any type filtering and this can lead to Remote Code Execution when deserializing XML payloads.
可以看出问题出在struts2-rest-plugin插件上,本质还是XStream的反序列化问题。
根据官方demo分析,Action经过struts2-rest-plugin处理时会被ContentTypeInterceptor这个拦截器处理,重写的intercept方法如下:
public String intercept(ActionInvocation invocation) throws Exception {
HttpServletRequest request = ServletActionContext.getRequest();
ContentTypeHandler handler = selector.getHandlerForRequest(request);
Object target = invocation.getAction();
if (target instanceof ModelDriven) {
target = ((ModelDriven)target).getModel();
}
if (request.getContentLength() > 0) {
InputStream is = request.getInputStream();
InputStreamReader reader = new InputStreamReader(is);
handler.toObject(reader, target);
}
return invocation.invoke();
}
首先getHandlerForRequest会判断该action的请求类型,分别返回不同的ContentTypeHandler,如下
当请求的Content-Type为 application/xml时,返回的ContentTypeHandler为XStreamHandler对象。
之后判断该请求的Content-Length是否大于0,如果不为空则以数据流的形式读取post请求数据,之后给InputStreamReader对象。然后调用XStreamHandler的函数toObject对输入进行反序列化操作:
public void toObject(Reader in, Object target) {
XStream xstream = createXStream();
xstream.fromXML(in, target);
}
目前公开的利用方法基本和XStream的思路相同,触发的原理如图:
详细可参考github上的marshalsec及paper。下载程序通过maven编译生成jar包,然后使用命令生成payload即可:
java -cp marshalsec-0.0.1-SNAPSHOT-all.jar marshalsec.XStream ImageIO "open /Applications/Calculator.app" > poc.xml