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(這是根據公告的,其實并沒有真正解決漏洞)