Merge pull request #5819 from luchua-bc/java/jpython-injection

Java: CWE-094 Jython code injection
This commit is contained in:
Chris Smowton
2021-05-18 16:38:40 +01:00
committed by GitHub
19 changed files with 1213 additions and 1 deletions

View File

@@ -0,0 +1,21 @@
edges
| JythonInjection.java:28:23:28:50 | getParameter(...) : String | JythonInjection.java:36:30:36:33 | code |
| JythonInjection.java:53:23:53:50 | getParameter(...) : String | JythonInjection.java:58:44:58:47 | code |
| JythonInjection.java:73:23:73:50 | getParameter(...) : String | JythonInjection.java:81:35:81:38 | code |
| JythonInjection.java:97:23:97:50 | getParameter(...) : String | JythonInjection.java:106:61:106:75 | getBytes(...) |
nodes
| JythonInjection.java:28:23:28:50 | getParameter(...) : String | semmle.label | getParameter(...) : String |
| JythonInjection.java:36:30:36:33 | code | semmle.label | code |
| JythonInjection.java:53:23:53:50 | getParameter(...) : String | semmle.label | getParameter(...) : String |
| JythonInjection.java:58:44:58:47 | code | semmle.label | code |
| JythonInjection.java:73:23:73:50 | getParameter(...) : String | semmle.label | getParameter(...) : String |
| JythonInjection.java:81:35:81:38 | code | semmle.label | code |
| JythonInjection.java:97:23:97:50 | getParameter(...) : String | semmle.label | getParameter(...) : String |
| JythonInjection.java:106:61:106:75 | getBytes(...) | semmle.label | getBytes(...) |
| JythonInjection.java:131:40:131:63 | getInputStream(...) | semmle.label | getInputStream(...) |
#select
| JythonInjection.java:36:13:36:34 | exec(...) | JythonInjection.java:28:23:28:50 | getParameter(...) : String | JythonInjection.java:36:30:36:33 | code | Jython evaluate $@. | JythonInjection.java:28:23:28:50 | getParameter(...) | user input |
| JythonInjection.java:58:27:58:48 | eval(...) | JythonInjection.java:53:23:53:50 | getParameter(...) : String | JythonInjection.java:58:44:58:47 | code | Jython evaluate $@. | JythonInjection.java:53:23:53:50 | getParameter(...) | user input |
| JythonInjection.java:81:13:81:39 | runsource(...) | JythonInjection.java:73:23:73:50 | getParameter(...) : String | JythonInjection.java:81:35:81:38 | code | Jython evaluate $@. | JythonInjection.java:73:23:73:50 | getParameter(...) | user input |
| JythonInjection.java:106:29:106:134 | makeCode(...) | JythonInjection.java:97:23:97:50 | getParameter(...) : String | JythonInjection.java:106:61:106:75 | getBytes(...) | Jython evaluate $@. | JythonInjection.java:97:23:97:50 | getParameter(...) | user input |
| JythonInjection.java:131:29:131:109 | compile(...) | JythonInjection.java:131:40:131:63 | getInputStream(...) | JythonInjection.java:131:40:131:63 | getInputStream(...) | Jython evaluate $@. | JythonInjection.java:131:40:131:63 | getInputStream(...) | user input |

View File

@@ -0,0 +1,144 @@
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.python.core.BytecodeLoader;
import org.python.core.Py;
import org.python.core.PyCode;
import org.python.core.PyException;
import org.python.core.PyObject;
import org.python.util.InteractiveInterpreter;
import org.python.util.PythonInterpreter;
public class JythonInjection extends HttpServlet {
private static final long serialVersionUID = 1L;
public JythonInjection() {
super();
}
// BAD: allow execution of arbitrary Python code
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType("text/plain");
String code = request.getParameter("code");
PythonInterpreter interpreter = null;
ByteArrayOutputStream out = new ByteArrayOutputStream();
try {
interpreter = new PythonInterpreter();
interpreter.setOut(out);
interpreter.setErr(out);
interpreter.exec(code);
out.flush();
response.getWriter().print(out.toString());
} catch(PyException ex) {
response.getWriter().println(ex.getMessage());
} finally {
if (interpreter != null) {
interpreter.close();
}
out.close();
}
}
// BAD: allow execution of arbitrary Python code
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType("text/plain");
String code = request.getParameter("code");
PythonInterpreter interpreter = null;
try {
interpreter = new PythonInterpreter();
PyObject py = interpreter.eval(code);
response.getWriter().print(py.toString());
} catch(PyException ex) {
response.getWriter().println(ex.getMessage());
} finally {
if (interpreter != null) {
interpreter.close();
}
}
}
// BAD: allow arbitrary Jython expression to run
protected void doPut(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType("text/plain");
String code = request.getParameter("code");
InteractiveInterpreter interpreter = null;
ByteArrayOutputStream out = new ByteArrayOutputStream();
try {
interpreter = new InteractiveInterpreter();
interpreter.setOut(out);
interpreter.setErr(out);
interpreter.runsource(code);
out.flush();
response.getWriter().print(out.toString());
} catch(PyException ex) {
response.getWriter().println(ex.getMessage());
} finally {
if (interpreter != null) {
interpreter.close();
}
}
}
// BAD: load arbitrary class file to execute
protected void doTrace(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType("text/plain");
String code = request.getParameter("code");
PythonInterpreter interpreter = null;
ByteArrayOutputStream out = new ByteArrayOutputStream();
try {
interpreter = new PythonInterpreter();
interpreter.setOut(out);
interpreter.setErr(out);
PyCode pyCode = BytecodeLoader.makeCode("test", code.getBytes(), getServletContext().getRealPath("/com/example/test.pyc"));
interpreter.exec(pyCode);
out.flush();
response.getWriter().print(out.toString());
} catch(PyException ex) {
response.getWriter().println(ex.getMessage());
} finally {
if (interpreter != null) {
interpreter.close();
}
}
}
// BAD: Compile Python code to execute
protected void doHead(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType("text/plain");
PythonInterpreter interpreter = null;
ByteArrayOutputStream out = new ByteArrayOutputStream();
try {
interpreter = new PythonInterpreter();
interpreter.setOut(out);
interpreter.setErr(out);
PyCode pyCode = Py.compile(request.getInputStream(), "Test.py", org.python.core.CompileMode.eval);
interpreter.exec(pyCode);
out.flush();
response.getWriter().print(out.toString());
} catch(PyException ex) {
response.getWriter().println(ex.getMessage());
} finally {
if (interpreter != null) {
interpreter.close();
}
}
}
}

View File

@@ -0,0 +1 @@
experimental/Security/CWE/CWE-094/JythonInjection.ql

View File

@@ -1,2 +1,2 @@
//semmle-extractor-options: --javac-args -cp ${testdir}/../../../../stubs/springframework-5.2.3:${testdir}/../../../../stubs/mvel2-2.4.7:${testdir}/../../../../stubs/jsr223-api:${testdir}/../../../../stubs/apache-commons-jexl-2.1.1:${testdir}/../../../../stubs/apache-commons-jexl-3.1:${testdir}/../../../../stubs/scriptengine:${testdir}/../../../../stubs/java-ee-el:${testdir}/../../../../stubs/juel-2.2:${testdir}/../../../stubs/groovy-all-3.0.7:${testdir}/../../../../stubs/servlet-api-2.4
//semmle-extractor-options: --javac-args -cp ${testdir}/../../../../stubs/springframework-5.2.3:${testdir}/../../../../stubs/mvel2-2.4.7:${testdir}/../../../../stubs/jsr223-api:${testdir}/../../../../stubs/apache-commons-jexl-2.1.1:${testdir}/../../../../stubs/apache-commons-jexl-3.1:${testdir}/../../../../stubs/scriptengine:${testdir}/../../../../stubs/java-ee-el:${testdir}/../../../../stubs/juel-2.2:${testdir}/../../../stubs/groovy-all-3.0.7:${testdir}/../../../../stubs/servlet-api-2.4:${testdir}/../../../../stubs/jython-2.7.2