找回密码
立即注册
搜索
热搜: Java Python Linux Go
发回帖 发新帖

3290

积分

0

好友

452

主题
发表于 14 小时前 | 查看: 0| 回复: 0

复现一下 S2-002 的洞。

漏洞简介

Struts2-002 是一个 XSS 漏洞,该漏洞发生在 s:urls:a 标签中,当标签的属性 includeParams=all 时,即可触发该漏洞。

漏洞影响版本

Struts 2.0.0 - Struts 2.1.8.1

环境搭建

因为 s2-002 的洞是一个 XSS,与处理的 Action 没有任何关系,所以这里我们只需要配置 .jsp 文件,以及 .xml 文件。

  • resources 文件夹下

struts.xml

<?xml version="1.0" encoding="UTF-8"?>  

<!DOCTYPE struts PUBLIC  
        "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"  
        "http://struts.apache.org/dtds/struts-2.0.dtd">  

<struts>  
    <package name="S2-002" extends="struts-default">  
        <action name="login" class="com.drunkbaby.action.LoginAction" method="execute">  
            <result name="success">welcome.jsp</result>  
            <result name="error">index.jsp</result>  
        </action>  
    </package>  
</struts>
  • webapp 文件夹下

index.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"  
         pageEncoding="UTF-8"%>  
<%@ taglib prefix="s" uri="/struts-tags" %>  

<html>  
<head>  
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">  
    <title>S2-002</title>  
</head>  
<body>  
<h2>S2-002 Demo</h2>  
<s:url action="login" includeParams="all"></s:url>  
<s:a href="%{url}">click</s:a>  
</body>  
</html>

welcome.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"  
         pageEncoding="UTF-8"%>  
<%@ taglib prefix="s" uri="/struts-tags" %>  

<html>  
<head>  
  <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">  
  <title>S2-002</title>  
</head>  
<body>  
<p>Hello <s:property value="username"></s:property></p>  
</body>  
</html>

接着在 WEB-INF 下,web.xml

<!DOCTYPE web-app PUBLIC  
 "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"  
 "http://java.sun.com/dtd/web-app_2_3.dtd" >  

<web-app>  
  <display-name>S2-002 Example</display-name>  
  <filter>  
    <filter-name>struts2</filter-name>  
    <filter-class>org.apache.struts2.dispatcher.FilterDispatcher</filter-class>  
  </filter>  
  <filter-mapping>  
    <filter-name>struts2</filter-name>  
    <url-pattern>/*</url-pattern>  
  </filter-mapping>  
  <welcome-file-list>  
    <welcome-file>index.jsp</welcome-file>  
  </welcome-file-list>  
</web-app>

项目结构如图,至此环境搭建完毕。
IDE项目文件结构截图

漏洞复现与分析

访问以下包含恶意脚本的URL进行触发:

http://localhost:8080/?%22%3E%3Cscript%3Ealert(1)%3C/script%3E%3C%22

浏览器弹出XSS警告框截图

漏洞分析

我们先下一个断点在 org.apache.struts2.views.jsp.ComponentTagSupport#doStartTag() 方法处,开始调试。
IDE调试界面截图,显示ComponentTagSupport.java的doEndTag方法

当在 JSP 文件中遇到 Struts2 标签 <s: 时,程序会先调用 doStartTag() 方法 ,并将标签中的属性设置到对应标签对象相应属性中。最后,在遇到 /> 结束标签的时候调用 doEndTag() 方法。

进入到了 index.jsp
IDE调试界面截图,显示index.jsp源码及调用栈

跟进 this.component.start()
IDE代码界面截图,显示URL类的start方法

index.jspincludeParams=all,往下看代码知道 88 行,跟进 mergeRequestParameters() 方法。

includeParams=all 的情况下会调用 mergeRequestParameters() 将 Tomcat 处取来的参数,这里取到了我们输入的 payload,并且保存在 this.parameters 中。
IDE调试界面截图,显示mergeRequestParameters方法中的参数合并逻辑

mergeRequestParameters() 方法运行完毕,往下是 includeGetParameters() 方法,也跟进去看一下;发现也是调用了 mergeRequestParameters(),同样是保存在了 this.parameters 中,不过这一次保存的是经过 url 编码的数据。
IDE代码界面截图,显示includeGetParameters方法及extractQueryString逻辑

继续往下,程序还调用了 includeExtraParameters() 方法,跟进;这里的意思是如果有额外的参数,会被保存进这里,然后再保存到 this.paramters
IDE代码界面截图,显示includeExtraParameters方法逻辑

其实到这里漏洞出发点就来了,第一次调用 mergeRequestParameters() 方法的时候那一段参数是未经过 URL 编码的,从而产生了 XSS。

在执行完毕 doStartTag() 方法之后,会去到 doEndTag() 方法,我们跟进 this.component.end()this.component 是 URL 类,所以也就是调用了 URL.end()
IDE代码界面截图,显示URL类的end方法入口

往下走,第 146 行,判断目前调度器(Dispatcher)的实例是否支持这一 Struts2 组件的行为,并且判断这一个请求是否需要 Struts2 组件调用某 Action 来处理;如果不需要调用 Action 处理,则直接进入 buildUrl() 的代码逻辑,如果需要 Action 来处理,会先去选择/调用 Action,再进行后续操作。
其实也就是 Struts2 运行的基本逻辑。
IDE调试界面截图,显示end方法中的逻辑分支判断

此处因为我们定义了 action=login,所以进入到了 else 的代码逻辑,跟进 this.determineActionURL() 方法。
IDE代码界面截图,显示determineActionURL方法实现

determineActionURL() 方法先定位到了对应的 action,再进行 buildUrl() 的操作,跟进 buildUrl()
IDE代码界面截图,显示UrlHelper.buildUrl方法调用

再跟进。
IDE代码界面截图,显示buildUrl方法的内部实现

此时的 params 即将会被拿去拼接,造成触发 XSS 漏洞。
IDE调试界面截图,显示构建URL时的参数包含XSS Payload

具体拼接是在 115 行的 buildParametersString() 方法,跟进再跟进。
IDE代码界面截图,显示参数拼接逻辑及XSS脚本注入

至此,漏洞分析结束。

漏洞修复

修改 pom.xml,将 Struts2 版本提升至 2.0.11(这是根据公告的,其实并没有真正解决漏洞)。

经过对 2.0.11.1 的代码阅读,在 UrlHelperbuildUrl() 方法里,第 136 行增加了如下修复代码:

 // link是最终的生成的url
        for(result = link.toString(); 
        result.indexOf("<script>") > 0; 
        result = result.replaceAll("<script>", "script")) {
        }

太鸡肋,基本算不上修复。。。

小结

因为是 XSS 漏洞,成因基本都是未进行 URL 编码或某种转码,所以我们可以去看处理参数的过程进行漏洞挖掘。这类 Web安全 问题,深入理解框架对请求参数的处理流程是关键。S2-002 还是比较简单的一个漏洞,但对于理解 Struts2 的标签处理机制和常见的编码疏漏很有帮助。如果你对更多类似的技术分析和实战感兴趣,可以到 云栈社区 的相应板块交流讨论。

Ref

https://github.com/Y4tacker/JavaSec/tree/main/7.Struts2%E4%B8%93%E5%8C%BA/S2-002%E6%BC%8F%E6%B4%9E%E5%88%86%E6%9E%90




上一篇:JWT与Token+Redis登录方案实战对比:80%项目选择后者的真实原因
下一篇:Vibe Coding:AI时代编程方式的演进与程序员角色的重新定位
您需要登录后才可以回帖 登录 | 立即注册

手机版|小黑屋|网站地图|云栈社区 ( 苏ICP备2022046150号-2 )

GMT+8, 2026-2-27 19:06 , Processed in 1.799326 second(s), 46 queries , Gzip On.

Powered by Discuz! X3.5

© 2025-2026 云栈社区.

快速回复 返回顶部 返回列表