紅隊第2篇:區分Spring與Struts2框架的幾種新方法
Part1前言
在近幾年的HW比賽、紅隊項目中,攻擊隊在外圍打點時,越來越依賴于對Java站點的漏洞挖掘。Java站點的主流框架大致就是兩個:Struts2系列(包括Webwork等)及Spring系列(包括Spring MVC、SpringBoot等)。很多攻擊隊員在查找網站漏洞時,由于無法判斷出網站所使用的框架,對于.do結尾的網站上去就是用Struts2工具、Spring漏洞工具開掃,這樣的做法效率極低,容易被WAF封禁IP,進而導致錯過相關漏洞。
網上的區分Struts2與Spring的方法,大多數是通過查看.do及.action后綴、網頁報錯、網站error異常、瀏覽器favicon.ico圖標、Struts2攔截器報錯等等,但是這些方法適用范圍比較窄。
本人前幾年在調試分析S2-016、S2-032等漏洞的時候,無意中發現了幾個特別簡單實用的方法,現分享給大家。簡單來說,就是利用Struts2框架和Spring框架在處理一些特殊的URL路徑時,返回結果不一樣的特性。
Part2方法匯總
方法1、URL中添加不存在路徑
在URL的反斜杠部分添加網站不存在的路徑,最好是隨機字符串組成的較長路徑,如果返回同樣的頁面,則大概率是Struts2框架,如果返回404或者是報錯,則大概率是Spring框架。
比如說:http://192.168.237.128:8080/struts2_032/example/aaaaaa1/bbbbbbbb2/ccccccccc3/HelloWorld.action
在Struts2框架下,完全可以正常返回頁面。

而Spring框架會出錯

具體判斷過程應參考如下步驟,一會兒講講具體原因:
對于如下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根目錄為止。
原理1:Struts2的URL構造
如果了解Struts2框架的讀者,一眼就能看明白這種方法的原理,對于其他讀者,要想弄明白這個方法的原理,首先需要看一下Struts2的URL構造:
Struts2站點的URL路徑包括四部分組成:工程名+namespace命名空間+action名+Struts2擴展名,舉個例子,對于如下URL:http://127.0.0.1:9999/S2_016_war/barspace/login.action
如果在Struts2框架中,大致應該這樣去分析這個URL:
/S2-016-war/部分是war包部署的工程名,也可以說是項目名、上下文等等,說法不一。
/barspace/部分是Struts2的命名空間namespace。
/login部分是Struts2的action名,指向具體處理請求的Java類。
.action部分是Struts2的擴展名,也可以定義為.do、.dw等等。
參考如下的struts.xml配置文件:
同樣對于URL:http://127.0.0.1:9999/S2_016_war/barspace/login.action
如果網站應用直接部署在Tomcat根目錄下,則工程名可以為空,此時URL如下所示:
http://127.0.0.1:9999/barspace/login.action
如果namespace設置為空,則URL如下:
http://127.0.0.1:9999/login.action
如果Struts2請求的擴展名為空,則URL如下:
http://127.0.0.1:9999/login(由此可見,這種URL路徑也可能是Struts2框架的)
其中namespace可以配置為/barspace/spac1、action也可以配置為/login/user.action。這也是為什么有時候,我們需要在URL的每一個反斜杠前都添加一次不存在URL路徑的原因,因為很難直接從URL中判斷出哪一部分是namespace、哪一部分是action名。
原理2:Struts2向上查找action名
在了解了Struts2的URL構造之后,接下來看一下如下URL,在Struts2下是可以返回正常頁面的:http://127.0.0.1:9999/S2_016_war/barspace/aaaaaaaaaa1/bbbbbbbb2/ccccccccc3/ddddddddddddd4/login.action
因為按照Struts2框架規則,首先會在當前路徑下找action名login,如果沒有找到去上一層找,還沒有找到會去上上層找,一直找到應用程序的根路徑為止。層層向上查找,直接找到應用程序為止。(真實的流程比這個復雜)
注:在網站的前端如果有nginx時,這種方法可能會無效,因為nginx可能會配置一些特殊URL轉發,這時候就是nginx轉發優先了。
方法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/下面去找資源,然后讀取此文件內容。
舉例如下:
http://192.168.237.128:8080/struts2_032/example/HelloWorld.action

在網站根目錄下添加/struts/domTT.css后訪問,返回css代碼。
http://192.168.237.128:8080/struts2_032/struts/domTT.css

注: 有一些低版本的Struts2框架,domTT.css文件不存在,需要更換為其它靜態文件路徑。
方法3、404、500響應碼返回信息
輸入一個不存在的路徑,返回404頁面,或者傳入一些亂碼字符,造成當前頁面500響應碼報錯,拋出異常信息。
Struts2常用的關鍵字有這些:例如no action mapped、struts2、namespace、defined for action等。



Spring的報錯信息如下:含有Whitelabel Error Page 關鍵字

方法4:看網站圖標favicon.ico
注意看下圖的左上角,有一片小綠葉的圖標,那基本上就是Spring了,而Struts2框架沒有常用的favicon.ico圖標。

Part3總結:
- URL擴展名不能用于區分Struts2、Spring框架,.do結尾的URL可能是Struts2、也可能是Spring,具體看程序員在配置文件中怎么寫。
- 利用處理特定URL時返回頁面不相同的方法,可以區分不同的框架。
- 總結各種報錯信息,可以區分不同Web應用所采用的框架。
- 多調試分析一下公開的漏洞,也會發現很多有趣的東西。還有其它的方法,有待大家挖掘。