0x01 前言
復現一下 S2-002 的洞
0x02 S2-002
漏洞簡介
Struts2-002 是一個 XSS 漏洞,該漏洞發生在 s:url 和 s:a 標簽中,當標簽的屬性 includeParams=all 時,即可觸發該漏洞。
漏洞影響版本
Struts 2.0.0 - Struts 2.1.8.1
0x03 環境搭建
- ? 如果不想手動搭建的話,環境我已經配好了 https://github.com/Drun1baby/JavaSecurityLearning/tree/main/JavaSecurity/Struts2/S2-002AndS2-006
因為 s2-002 的洞是一個 XSS,與處理的 Action 沒有任何關系,所以這里我們只需要配置 .jsp 文件,以及 .xml 文件
- ? resources 文件夾下
struts.xml
"1.0" encoding="UTF-8"?> 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.jspresult> <result name="error">index.jspresult> action> package> struts>
- ? webapp 文件夾下
index.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib prefix="s" uri="/struts-tags" %>
"Content-Type" content="text/html; charset=UTF-8">
S2-<span style="color: rgb(209, 154, 102);">002</span>
S2-002 Demo
"login" includeParams="all">
"%{url}">click
welcome.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@ taglib prefix="s" uri="/struts-tags" %> "Content-Type" content="text/html; charset=UTF-8"> S2-<span style="color: rgb(209, 154, 102);">002</span> Hello "username">
接著在 WEB-INF 下,web.xml
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 Exampledisplay-name> <filter> <filter-name>struts2filter-name> <filter-class>org.apache.struts2.dispatcher.FilterDispatcherfilter-class> filter> <filter-mapping> <filter-name>struts2filter-name> <url-pattern>/*url-pattern> filter-mapping> <welcome-file-list> <welcome-file>index.jspwelcome-file> welcome-file-list> web-app>
項目結構如圖,至此環境搭建完畢

0x04 漏洞復現與分析
http://localhost:8080/?%22%3E%3Cscript%3Ealert(1)%3C/script%3E%3C%22

漏洞分析
之前自己也沒有分析過 XSS 相關的漏洞,在最后我會做一個小結來思考一下如何自己挖掘出這個漏洞
我們先下一個斷點在 org.apache.struts2.views.jsp.ComponentTagSupport#doStartTag() 方法處,開始調試

當在 JSP 文件中遇到 Struts2 標簽 時,程序會先調用 doStartTag() 方法 ,并將標簽中的屬性設置到對應標簽對象相應屬性中。最后,在遇到 /> 結束標簽的時候調用 doEndTag() 方法。
進入到了 index.jsp

跟進 this.component.start()

在 index.jsp 中 includeParams=all,往下看代碼知道 88 行,跟進 mergeRequestParameters() 方法
在 includeParams=all 的情況下會調用 mergeRequestParameters() 將 Tomcat 處取來的參數,這里取到了我們輸入的 payload,并且保存在 this.parameters 中

mergeRequestParameters() 方法運行完畢,往下是 includeGetParameters() 方法,也跟進去看一下;發現也是調用了 mergeRequestParameters(),同樣是保存在了 this.parameters 中,不過這一次保存的是經過 url 編碼的數據

繼續往下,程序還調用了 includeExtraParameters() 方法,跟進;這里的意思是如果有額外的參數,會被保存進這里,然后再保存到 this.paramters

其實到這里漏洞出發點就來了,第一次調用 mergeRequestParameters() 方法的時候那一段參數是未經過 URL 編碼的,從而產生了 XSS
在執行完畢 doStartTag() 方法之后,會去到 doEndTag() 方法,我們跟進 this.component.end(),this.component 是 URL 類,所以也就是調用了 URL.end()

往下走,第 146 行,判斷目前調度器(Dispatcher)的實例是否支持這一 Struts2 組件的行為,并且判斷這一個請求是否需要 Struts2 組件調用某 Action 來處理;如果不需要調用 Action 處理,則直接進入 buildUrl() 的代碼邏輯,如果需要 Action 來處理,會先去選擇/調用 Action,再進行后續操作。
其實也就是 Struts2 運行的基本邏輯

此處因為我們定義了 action=login,所以進入到了 else 的代碼邏輯,跟進 this.determineActionURL() 方法

determineActionURL() 方法先定位到了對應的 action,再進行 buildUrl() 的操作,跟進 buildUrl()

再跟進

此時的 params 即將會被拿去拼接,造成觸發 XSS 漏洞

具體拼接是在 115 行的 buildParametersString() 方法,跟進再跟進

至此,漏洞分析結束漏洞修復
修改 pom.xml,將 Struts2 版本提升至 2.0.11(這是根據公告的,其實并沒有真正解決漏洞)
合天網安實驗室
上官雨寶
Anna艷娜
安全俠
Anna艷娜
安全圈
嘶吼專業版
Coremail郵件安全
Anna艷娜
一顆小胡椒
FreeBuf
啟明星辰集團
上官雨寶