struts2 s2-032漏洞分析

0x01Brief Descriptionhtml

      最近面試幾家公司,不少都問到了s2漏洞的原理,以前調試分析過java反序列化的漏洞,以爲s2漏洞應該不會太難,今天就分析了一下,而後發現其實漏洞的原理不難,可是搭建j2ee調試的環境花了將近半天的時間QAQ.java

      Struts 是Apache軟件基金會(ASF)贊助的一個開源項目,經過採用JavaServlet/JSP技術,實現基於Java EEWeb應用的MVC設計模式的應用框架,Struts 2是Struts的下一代產品,是在 Struts 1和WebWork的技術基礎上進行了合併的全新的Struts 2框架。
Struts2框架普遍應用於政府、公安、交通、金融行業和運營商的網站建設,做爲網站開發的底層模板使用。Struts2漏洞,主要指的是J2EE開源框架struts2出現的命令執行漏洞,危害巨大,可致使遠程執行任意系統命令,進而獲取系統控制權,數據庫控制權,致使信息泄露。全部使用struts2框架開發的系統都會受到影響。(copy from Link),以前大學的時候學習過,工做以後就不多接觸過了,基本上就是用用工具測試一下s2的漏洞。git

      OGNL是Object-Graph Navigation Language的縮寫,它是一種功能強大的表達式語言,經過它簡單一致的表達式語法,能夠存取對象的任意屬性,調用對象的方法,遍歷整個對象的結構圖,實現字段類型轉化等功能。它使用相同的表達式去存取對象的屬性。OGNL通常是配合struts框架一塊兒使用的,表達式語言通常是爲了方便數據的存取所自定義的語言,然而邪惡攻擊者卻在Struts2中Ognl執行Java代碼,一樣的Elasticsearch能夠用Groovy能夠實現任意Java功能。更多ognl的介紹可參考 Link百科。github

0x02 s2-032漏洞分析面試

     s2-032漏洞影響的s2版本:Struts 2.3.20 - Struts 2.3.28 (except 2.3.20.3 and 2.3.24.3)數據庫

     官方的公告:https://struts.apache.org/docs/s2-032.htmlapache

     這次漏洞存在於struts2的動態方法引用功能。只要在struts2配置文件中開啓該功能,就可能被利用。設計模式

 在配置了 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方法進行命令執行,這裏是打開計算器的操做。session

ognl表達式分析:app

@符號的做用:在對靜態方法或者變量訪問的時候使用@class@member或者@class@method(args),因此這裏就是經過反射調用了Runtime class的exec method(後者)。

一、「#」符號有三種用途:

(1)、訪問非根對象(struts中值棧爲根對象)如OGNL上下文和Action上下文,#至關於ActionContext.getContext();下表有幾個ActionContext中有用的屬性:

parameters
包含當前HTTP請求參數的Map
#parameters.id[0]做用至關於request.getParameter("id")

request
包含當前HttpServletRequest的屬性(attribute)的Map
#request.userName至關於request.getAttribute("userName")

session
包含當前HttpSession的屬性(attribute)的Map
#session.userName至關於session.getAttribute("userName")

application
包含當前應用的ServletContext的屬性(attribute)的Map
#application.userName至關於application.getAttribute("userName")


注:attr 用於按request > session > application順序訪問其屬性(attribute),#attr.userName至關於按順序在以上三個範圍(scope)內讀取 userName屬性,直到找到爲止。用於過濾和投影(projecting)集合,如books.{?#this.price<100};構造 Map,如#{'foo1':'bar1', 'foo2':'bar2'}。

(2)、用於過濾和投影(projecting)集合,如: books.{?#this.price>35}

books.{?#this.price>35}

(3)、構造Map,如: #{'foo1':'bar1', 'foo2':'bar2'}

#{'foo1':'bar1', 'foo2':'bar2'}這種方式經常使用在給radio或select、checkbox等標籤賦值上。若是要在頁面中取一個map的值能夠這樣寫:

<s:property value="#myMap['foo1']"/>

<s:property value="#myMap['foo1']"/>

 將_memberAccess賦值成DEFAULT_MEMBER_ACCESS是爲繞過SecurityMemberAccess爲false的限制。

簡單的payload分析以後,咱們來調試一下代碼。

首先添加存在漏洞版本的struts2包(這裏使用的是2.3.28)以及對應的source Attachement(爲方便調試查看到源代碼)。以下圖所示。

 

而後呢,構造一個有效的Action,這裏就不實現具體的功能。

    struts.xml中配置action對應的處理方法。

    

 下一步就是下斷點,斷點下在哪裏?參考他人的文章,聰明的咱們天然就下在了該下的地方,讓它在該斷下的地方斷下(這不廢話麼。。)

1.在DefaultActionMapper.java中,DefaultActionMapper方法將method的值存入到ActionMapping的method屬性中。

2.在DefaultActionProxyFactory.java中,DefaultActionProxy方法將ActionMapping的method值通過escapeEcmaScript,escapeHtml4過濾後傳到了ActionProxy的method屬性中。

3.最後DefaultActionInvocation.java中的invokeAction將ActionProxy的method值放入到了ognlUtil.getValue()方法中執行表達式。

最終,執行完這一步就執行了咱們的命令。

0x03 關於escapeHtml4的疑問

咱們注意到在整個參數的傳遞過程當中有這樣一個函數escapeHtml4的函數會對傳輸的參數進行處理,查看文檔能夠知道這個函數的做用是對特殊的符號進行過濾,那麼咱們的payload中有那麼多的特殊符號,像#@,([])/&._= 按理說應該是會被html encode的啊

關於html4 entities 可參考 https://www.w3schools.com/charsets/ref_html_entities_4.asp

爲什麼還能成功,咱們嘗試在payload中添加雙引號,而後再跟一下執行過程。

http://localhost:8080/Demo/index.action?method:#_memberAccess=@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS"",#f=@java.lang.Runtime@getRuntime().exec(#parameters.cmd[0]),#f.close&cmd=open /Applications/Calculator.app

跟蹤發現,雙引號在這裏確實是進行了html encode

爲什麼&不會呢?在此猜想應該是#$等符號是ognl裏面的一些符號,因此這個函數並不會對這些符號進行htmlencode。

0x03Diff Patch

可見,修復的版本在對method參數進行了cleanActionName的過濾,具體的過濾是

protected Pattern allowedActionNames = Pattern.compile(「[a-zA-Z0-9._!/\\-]*」);,這樣咱們payload中的]./等就被過濾掉了。

0x04 Reference

1.http://rickgray.me/2016/05/06/review-struts2-remote-command-execution-vulnerabilities.html

2.http://dogewatch.github.io/2016/04/29/struts2/

3.http://blog.topsec.com.cn/ad_lab/apache-structs2-s2-032%E6%8A%80%E6%9C%AF%E5%88%86%E6%9E%90%E5%8F%8A%E6%BC%8F%E6%B4%9E%E6%A3%80%E6%B5%8B%E8%84%9A%E6%9C%AC/

4.http://www.cnblogs.com/LittleHann/p/4606891.html

相關文章
相關標籤/搜索