<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/5107

            作者:京東安全團隊 Lupin

            0x00 前言


            ElasticSearch是一個JAVA開發的搜索分析引擎。2014年,曾經被曝出過一個遠程代碼執行漏洞(CVE-2014-3120),漏洞出現在腳本查詢模塊,由于搜索引擎支持使用腳本代碼(MVEL),作為表達式進行數據操作,攻擊者可以通過MVEL構造執行任意java代碼,后來腳本語言引擎換成了Groovy,并且加入了沙盒進行控制,危險的代碼會被攔截,結果這次由于沙盒限制的不嚴格,導致遠程代碼執行,目前網上還沒看到公開的poc,經過一番研究,發現了利用方式,下面來看看漏洞是如何產生的。

            Groovy是一種運行在JVM上的腳本語言,語法和java很像,同樣可以調用java中的各種對象和方法,但是Groovy的語法更簡單。

            0x01 細節


            首先,我們執行一段帶腳本的查詢代碼:

            POST http://127.0.0.1:9200/_search?pretty HTTP/1.1
            User-Agent: es
            Host: 127.0.0.1:9200
            Content-Length: 184
            
            {
            "size":1,
                "script_fields": {
                    "lupin": {
                        "script": "1 + 6"
                    }
                }
            }
            

            上面的請求中1+6,就是我們執行的腳本代碼,下面的返回中的7就是執行結果:

            enter image description here

            下面再試著執行一下這段代碼:

            POST http://127.0.0.1:9200/_search?pretty HTTP/1.1
            User-Agent: es
            Host: 127.0.0.1:9200
            Content-Length: 184
            
            {
            "size":1,
                "script_fields": {
                    "lupin": {
                        "script": "new java.lang.ProcessBuilder(\“calc\”)"
                    }
                }
            }
            

            執行之后,報了錯,從錯誤中可以看到,構造java.lang.ProcessBuilder對象是不允許的:

            enter image description here

            下面我們看看ElasticSearch沙盒的相關代碼,實現沙盒的類是com.elasticsearch.script.groovy.GroovySandboxExpressionChecker,它訂制了Groovy的沙盒,對表達式進行了安全檢測,但是這個沙盒與JAVA的SecurityManager那種沙盒是不同的,從代碼中可以看到這個沙盒,只是根據黑白名單,在表達式語義上判斷表達式是否合法的,可以說是一個“淺”沙盒,簡單來來說,比如沙盒設置不允許調用shell()這個方法,直接調用shell()方法,沙盒在表達式中發現了shell()這個字符串,就會報非法調用,但是如果有一個方法叫poc()這個方法中調用了shell()方法(poc(){shell()}),當調用poc()方法的時候,shell()方法也就被間接調用了沙盒并不會報錯。 具體來說isAuthorized(Expression expression)方法如果返回false,說明表達式非法,true則合法,從isAuthorized方法的實現中可以看到,它根據黑白名單對方法調用和對象構造都進行了檢測:

            enter image description here

            enter image description here

            enter image description here

            從上面的白名單中可以看到,允許構造對象和方法調用的類,都是一些常規類,沒有我們可以利用的類,而且如果我們想要利用反射去調用我們想調用的類,方法黑名單中又限制了getClass的調用,我們無法通過getClass方法獲取Class對象,但是我們可以看到方法白名單中,并沒有對forName方法進行限制,也就是說,如果我們能獲取到Class對象,再調用forName方法就可以獲取到我們想訪問的類。 那么我們如何能夠獲取一個Class對象呢?首先我想到的是通過java.lang.String.class這樣的方式,通過class讓JVM返回String類的class對象,可以看到的確獲取到了Class對象:

            enter image description here

            那么我們在試試可不可以通過這個Class對象調用forName方法,加載java.lang.Runtime這個我們最想要的類,可惜報錯了:

            enter image description here

            出錯的原因是java.lang.String這個類是不允許進行方法調用的,只有在上面defaultReceiverWhiteList這個白名單中的類,才可以進行方法調用,這個控制是在Groovy沙盒類org.codehaus.groovy.control.customizers.SecureASTCustomizer中做的判斷:

            enter image description here

            既然這樣,思路就又有了,我們就拿這個白名單中的類獲取Class對象,然后再調用forName方法,是不是就可以突破這個限制了,我這里使用java.lang.Math這個類來試試,這個類是在recevicer白名單中的,可以看到成功獲取了java.lang.Runtime類:

            POST http://127.0.0.1:9200/_search?pretty HTTP/1.1
            User-Agent: es
            Host: 127.0.0.1:9200
            Content-Length: 132
            
            {
            "size":1,
                "script_fields": {
                    "lupin": {
                        "script": "java.lang.Math.class.forName(\“java.lang.Runtime\”)"
                    }
                }
            }
            

            enter image description here

            有了Runtime類,后面的事情就好辦了要調用到的各種方法都不在方法黑名單里面,我這里就不公布具體POC了,看懂上面原理的同學自然明白:

            enter image description here

            0x02 參考


            http://www.elasticsearch.org/blog/elasticsearch-1-4-3-and-1-3-8-released/

            https://github.com/elasticsearch/elasticsearch/blob/4dc060527cd7d35817085a3926e65d071e3b1321/src/main/java/org/elasticsearch/script/groovy/GroovySandboxExpressionChecker.java

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

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

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

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

                      亚洲欧美在线