<span id="7ztzv"></span>
<sub id="7ztzv"></sub>

<span id="7ztzv"></span><form id="7ztzv"></form>

<span id="7ztzv"></span>

        <address id="7ztzv"></address>

            原文地址:http://drops.wooyun.org/papers/5738

            0x00 前言


            這個漏洞已經出來很久了,以前簡單分析過,但是由于時間關系,沒能深入研究原理,網上對這個漏洞的分析也不太多,最近由于工作原因,深入分析了一下這個漏洞的原理,這里重點將漏洞調試過程,以及一些之前遇到的一些奇怪問題的原因記錄下來。

            首先來看一下官方對這個漏洞的描述,如下圖:

            enter image description here

            可以看到,這個漏洞的形成,是因為在早于JSP2.0的版本上,由于沒有EL表達式的支持,Spring標簽為了兼容這部分版本,Spring的一部分標簽獨立于Servlet/JSP容器添加了對EL表達式的支持。但這樣做引起了一個問題,就是當這部分標簽在支持EL表達式的容器中運行的時候,Spring標簽的屬性會被當做EL表達式執行兩次,第一次是被容器當做EL執行,第二次是被Spring標簽自身執行。所以,如果攻擊者可以控制標簽屬性的內容,就可以執行自己提交的EL表達式,會造成信息泄露、代碼執行等風險。

            0x01 漏洞原理


            首先編寫一段測試JSP代碼,并且引入存在漏洞的Spring標簽,我這里使用的是Tomcat 7.0.57和Spring 3.0.5

            #!html
            <%@ taglib uri="http://www.springframework.org/tags" prefix="spring"%>
            <spring:message  text="${param.a}"></spring:message>
            

            這里使用message標簽,text屬性用el表達式從請求參數中取值,這樣當訪問

            http://localhost/tag.jsp?a=${applicationScope}
            

            ${applicationScope}這個字符串,就會被當做EL表達式執行,如下圖

            enter image description here

            下面我們就從代碼中,研究一下這個漏洞的原理。

            首先,${param.a}這個EL表達式要在JSP里面執行,這里有必要簡單說一下JSP的執行原理,tag.jsp在執行的時候,會先通過規則變成tag_jsp.java,這個文件可以在tomcatRoot/ work/Catalina/localhost/項目名稱/org/apache/jsp/路徑下找到,這個類其實是一個servlet,通過查看這個文件的代碼,我們可以發現${param.a}這個EL表達式,其實是被轉化成了這樣的代碼org.apache.jasper.runtime.PageContextImpl.proprietaryEvaluate("${param.a }", .......),這行代碼調用了Tomcat的一個專用方法來執行EL表達式,這段代碼執行了之后,我們通過請求參數提交的${applicationScope}就被容器獲取,并且傳入了Spring標簽,如下圖:

            enter image description here

            還需要說一下關于標簽的一些內容,標簽都有一個tld文件,這個文件里面有標簽的各種信息,包括標簽實現類、屬性信息等等,這個標簽對應的spring.tld文件可以在Spring的jar包中找到,打開這個文件搜索message,就可以定位到如下圖的位置:

            enter image description here

            從上面可以看到org.springframework.web.servlet.tags.MessageTag就是這個標簽的實現類,關于標簽的規范,我就不多說了,有興趣的朋友可以去翻翻相關的規范。

            Debug程序,在doStartTagInternal方法下斷點,如下圖:

            enter image description here

            然后跟進resolveMessage方法,因為程序執行到這里,容器已經第一次執行了EL表達式${parm.a},將參數值${applicationScope}取了出來,可以看到text變量,這時候就是我們傳入的${applicationScope},如下圖:

            enter image description here

            最后跟蹤到org.springframework.web.util.ExpressionEvaluationUtils類的evaluateExpression方法,在這里可以看到Spring的代碼調用了getExpressionEvaluator方法獲取了容器執行El表達式求值對象,并執行了EL表達式,到這里可以看到我們通過請求參數提交的字符串,被當做EL表達式執行了,如下圖:

            enter image description here

            從上面的過程可以看到,容器第一次執行EL表達式${param.a}獲得了我們輸入的${applicationScope},然后Spring標簽獲取容器的EL表達式求值對象,把${applicationScope}再次執行掉,形成了漏洞。

            0x02 Tomcat不能遠程代碼執行研究


            這個漏洞既然能執行攻擊者提交的EL表達式,那么獲取敏感信息、XSS等攻擊自然不是問題,我這里主要說一下代碼執行的一些問題。 這個漏洞之所以能造成遠程代碼執行,是因為從JEE6開始,EL(EL2.2)表達式不僅支持獲取對象屬性,還加入了對方法調用的支持,而Tomcat、Resin等容器都加入了EL表達式對方法調用的支持,之前知識庫里面已經有大牛公布的針對Resin和GlassFish的代碼執行POC,雖然由于容器對EL表達式的執行實現上有差異,每個容器POC有所差異,但是都可以成功實現方法調用,我這里就不多說了,而我在最初測試這個漏洞的時候,發現Tomcat始終沒法調用方法,當時沒有深入研究,通過前面的分析,其實原因已經可以看出來了,這里還是測試一下,先寫一段JSP測試代碼:

            #!html
            <body>
            ${“aaa”.replace(‘a’,’b’)}
            </body>
            

            打開這個頁面,發現a都已經被b替換,說明replace方法被成功調用:

            enter image description here

            但是當我們通過之前的tag.jsp嘗試提交http://localhost/tag.jsp?a=${“aaaa”.replace(‘a’,’b’)}的時候卻爆出了錯誤,如下圖:

            enter image description here

            從Tomcat 7開始已經支持EL表達式方法調用,為什么第二次會失敗呢?

            其實前面的分析中已經看到,在JSP中直接寫EL表達式,Tomcat調用了org.apache.jasper.runtime.PageContextImpl.proprietaryEvaluate方法,這個方法已經加入了對EL表達式方法調用的支持,而通過Spring標簽執行EL表達式,前面已經看到是通過pageContext的getExpressionEvaluator方法,而在EL表達式的新標準中這個方法已經“廢棄”,Tomcat并沒有在這個方法的實現中加入對方法調用的支持,所以造成執行失敗,這也讓這個漏洞在Tomcat上顯得有點雞肋了,誰能保證Tomcat哪天不會抽風,改變代碼呢?說不定到時候,這個漏洞,就可以在Tomcat上造成代碼執行了。

            參考

            http://support.springsource.com/security/cve-2011-2730

            http://drops.wooyun.org/tips/2892

            <span id="7ztzv"></span>
            <sub id="7ztzv"></sub>

            <span id="7ztzv"></span><form id="7ztzv"></form>

            <span id="7ztzv"></span>

                  <address id="7ztzv"></address>

                      亚洲欧美在线