Author:dawu(知道創宇404實驗室)
date: 2016-11-16
0x00 漏洞概述
1.漏洞簡介
Sparkjava是一款小型的web框架,它能夠讓你以很少的代碼構建出一個java web應用。近日,某國外安全研究人員發現其存在文件遍歷漏洞,可以通過該漏洞讀取任意文件內容。在對這個漏洞進行復現與分析的時候,我們又發現了一些可能可以利用的地方,但是利用條件更加苛刻。
2.漏洞影響
Sparkjava版本 < 2.5.2
0x01 漏洞復現
1.驗證環境
Jdk-1.8.0_111 Apache maven 3.3.9 在寫好Sparkjava代碼后,在文件所在目錄打開命令行,運行mvn package進行編譯打包。
2.漏洞復現
根據官網給出的示例,我們寫了一個簡單的函數去復現這個漏洞:
public class Hello {
public static void main(String[] args) {
staticFiles.externalLocation(“/tmp”);
get("/", (req, res) -> {
return "hello from sparkjava.com";
});
}
}
pom.xml的配置為
<dependency>
<groupId>com.sparkjava</groupId>
<artifactId>spark-core</artifactId>
<version>2.5</version>
</dependency>
這里提供已經打包好的jar文件供大家下載。可以用如下命令運行:
java -jar sparkexample-jar-with-dependencies.jar
我們可以通過(..\)來改變路徑從而讀取任意文件。如圖,我們讀取到/etc/passwd:
在漏洞發現者的描述中,Spark.staticFileLocation()和Spark.externalStaticFileLocation()這兩個函數都存在這個問題。經過開發者測試,在IDE中運行時,兩個函數都可以復現這個漏洞;運行打包好的jar包時,只有Spark.externalStaticFileLocation()這個函數可以觸發漏洞。
0x02 補丁分析與深入研究
1.補丁分析
很明顯,在漏洞被發現時,官方沒有對url中的路徑做任何處理。在漏洞被修補之后,官方推出了新的版本2.5.2。這里我們對比之前的版本,并且通過調試,嘗試分析官方的修補方案。 官方修補鏈接(https://github.com/perwendel/spark/commit/efcb46c710e3f56805b9257a63d1306882f4faf9) 當我們正常請求時:
curl "127.0.0.1:4567/l.txt"
跟到關鍵代碼處,我們可以看到在判斷文件是否存在之后,官方添加了DirectoryTraversal.protectAgainstInClassPath(resource.getPath());進行判斷。
這里,path就是我們HTTP請求的地址,addedPath就是我們通過staticFiles.externalLocation()函數設置的路徑與path拼接之后的值,resource中的file的值就是addedPath值經過路徑的處理的值(例如:/tmp/test/..\l.txt先將所有的\換成/,再對路徑進行處理,最后結果為/tmp/l.txt),resource.getPath()就是addedPath的值。

在protectAgainstInClassPath()函數中,需要判斷removeLeadingAndTrailingSlashesFrom(path).startsWith(StaticFilesFolder.external())是否為false,為false就拋出。
removeLeadingAndTrailingSlashesFrom(path)為新添加的函數,作用是將path首尾的/去掉和將尾部的\去掉。在這里經過處理之后,path的值為tmp/l.txt。
StaticFilesFolder.external()則是返回external的值,在這里就是tmp。如果removeLeadingAndTrailingSlashesFrom(path)前面的字母是tmp,則進入下一步。
綜上所述,官方通過比較經過處理后的路徑的開頭和我們設置的externalLocation()的路徑是否相同來防止我們利用..\讀取任意文件。
2.深入探究
我們修改了pom.xml,使用新的Sparkjava版本進行編譯嘗試,做了如下探究。
<dependency>
<groupId>com.sparkjava</groupId>
<artifactId>spark-core</artifactId>
<version>2.5.2</version>
</dependency>
① 軟鏈接的利用
與Sparkjava(CVE-2016-9177)同時爆出來的一個漏洞GitLab的任意文件讀取(CVE-2016-9086)是利用軟鏈接的特性,我們就順手測試了軟鏈接在Sparkjava下的利用。
直接讀取文件:
路徑映射:
怎么才能利用軟鏈接呢?這里的利用條件比較苛刻。筆者想到了兩種途徑:
1.網站允許上傳壓縮包,上傳后解壓并且還能訪問到解壓后的文件才能利用
2.網站通過wget(wget配置文件中需要retr-symlinks=on)從ftp上下載文件并且能夠訪問到下載的文件。
②再次讀取文件
我們在根目錄下新建兩個文件tmp.txt,tmp2.txt
再訪問
讀取到了tmp.txt和tmp2.txt的內容。
我們分析一下能夠再次讀取的原因,當我們請求為:
curl “127.0.0.1:4567/tmp\..\..\tmp.txt”
分析過濾代碼處:
addedPath的值為/tmp/tmp/..\..\tmp.txt,經過處理后resource中的file值為/tmp.txt,對于下面的函數removeLeadingAndTrailingSlashesFrom(path).startsWith(StaticFilesFolder.external()),由于tmp.txt也是由tmp開頭,所以判斷可以通過,進而讀取到tmp.txt。
同樣的道理,我們也可以讀取到/tmp2/test.txt的內容。

通過以上分析,筆者認為這個讀取很雞肋,首先staticFiles.externalLocation()中定義的路徑只能是一級路徑,其次我們要讀取的文件的完整路徑開頭必須和staticFiles.externalLocation()中定義的路徑相同。這就限制了這個新的讀取,也許只有在某些特定的場合才能有奇效。
如有錯誤,歡迎指正:)
0x03 參考鏈接
- 1.https://www.seebug.org/vuldb/ssvid-92517
- 2.http://seclists.org/fulldisclosure/2016/Nov/13
- 3.https://github.com/perwendel/spark/commit/efcb46c710e3f56805b9257a63d1306882f4faf9
- 4.https://github.com/perwendel/spark/issues/700
- 5.http://sparkjava.com/documentation.html
本文由 Seebug Paper 發布,如需轉載請注明來源。本文地址:http://www.jmbmsq.com/115/
暫無評論