Merge pull request #3839 from luchua-bc/uncaught-servlet-exception

Java: Uncaught servlet exception
This commit is contained in:
Anders Schack-Mulligen
2020-12-02 15:12:59 +01:00
committed by GitHub
12 changed files with 610 additions and 1 deletions

View File

@@ -0,0 +1,19 @@
edges
| UncaughtServletException.java:13:15:13:43 | getParameter(...) : String | UncaughtServletException.java:14:44:14:45 | ip |
| UncaughtServletException.java:16:19:16:41 | getRemoteUser(...) : String | UncaughtServletException.java:17:20:17:25 | userId |
| UncaughtServletException.java:54:16:54:44 | getParameter(...) : String | UncaughtServletException.java:55:45:55:46 | ip |
| UncaughtServletException.java:75:21:75:43 | getRemoteUser(...) : String | UncaughtServletException.java:76:22:76:27 | userId |
nodes
| UncaughtServletException.java:13:15:13:43 | getParameter(...) : String | semmle.label | getParameter(...) : String |
| UncaughtServletException.java:14:44:14:45 | ip | semmle.label | ip |
| UncaughtServletException.java:16:19:16:41 | getRemoteUser(...) : String | semmle.label | getRemoteUser(...) : String |
| UncaughtServletException.java:17:20:17:25 | userId | semmle.label | userId |
| UncaughtServletException.java:54:16:54:44 | getParameter(...) : String | semmle.label | getParameter(...) : String |
| UncaughtServletException.java:55:45:55:46 | ip | semmle.label | ip |
| UncaughtServletException.java:75:21:75:43 | getRemoteUser(...) : String | semmle.label | getRemoteUser(...) : String |
| UncaughtServletException.java:76:22:76:27 | userId | semmle.label | userId |
#select
| UncaughtServletException.java:14:44:14:45 | ip | UncaughtServletException.java:13:15:13:43 | getParameter(...) : String | UncaughtServletException.java:14:44:14:45 | ip | $@ flows to here and can throw uncaught exception. | UncaughtServletException.java:13:15:13:43 | getParameter(...) | User-provided value |
| UncaughtServletException.java:17:20:17:25 | userId | UncaughtServletException.java:16:19:16:41 | getRemoteUser(...) : String | UncaughtServletException.java:17:20:17:25 | userId | $@ flows to here and can throw uncaught exception. | UncaughtServletException.java:16:19:16:41 | getRemoteUser(...) | User-provided value |
| UncaughtServletException.java:55:45:55:46 | ip | UncaughtServletException.java:54:16:54:44 | getParameter(...) : String | UncaughtServletException.java:55:45:55:46 | ip | $@ flows to here and can throw uncaught exception. | UncaughtServletException.java:54:16:54:44 | getParameter(...) | User-provided value |
| UncaughtServletException.java:76:22:76:27 | userId | UncaughtServletException.java:75:21:75:43 | getRemoteUser(...) : String | UncaughtServletException.java:76:22:76:27 | userId | $@ flows to here and can throw uncaught exception. | UncaughtServletException.java:75:21:75:43 | getRemoteUser(...) | User-provided value |

View File

@@ -0,0 +1,106 @@
import java.io.IOException;
import java.net.InetAddress;
import java.net.UnknownHostException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.ServletException;
class UncaughtServletException extends HttpServlet {
// BAD - Tests `doGet` without catching exceptions.
public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
String ip = request.getParameter("srcIP");
InetAddress addr = InetAddress.getByName(ip); // getByName(String) throws UnknownHostException
String userId = request.getRemoteUser();
Integer.parseInt(userId); // Integer.parse(String) throws RuntimeException
}
// GOOD - Tests `doPost` with catching exceptions.
public void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
try {
String ip = request.getParameter("srcIP");
InetAddress addr = InetAddress.getByName(ip);
String userId = request.getRemoteUser();
Integer.parseInt(userId); // Integer.parse(String) throws RuntimeException
} catch (UnknownHostException uhex) {
uhex.printStackTrace();
} catch (RuntimeException re) {
re.printStackTrace();
}
}
// GOOD - Tests `doPut` without user provided data and without catching exceptions.
public void doPut(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
String ip = "10.100.10.81";
InetAddress addr = InetAddress.getByName(ip); // GOOD: hard-coded variable value or system property not controlled by attacker
}
// GOOD - Tests rethrowing caught exceptions without stack trace, which the typical programming practice.
public void doDelete(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
try {
String ip = request.getParameter("srcIP");
InetAddress addr = InetAddress.getByName(ip);
} catch (UnknownHostException uhex) {
throw new IOException("Host not found "+uhex.getMessage());
}
}
// BAD - Tests rethrowing caught exceptions with stack trace.
public void doOptions(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
try {
String ip = request.getParameter("srcIP");
InetAddress addr = InetAddress.getByName(ip);
} catch (UnknownHostException uhex) {
uhex.printStackTrace();
throw uhex;
}
}
// GOOD - Tests invoking another top-level method.
public void doHead(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
doGet(request, response);
}
// BAD - Tests nested try-blocks without catching runtime exceptions.
public void service(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
try {
String ip = request.getParameter("srcIP");
InetAddress addr = null;
try {
addr = InetAddress.getByName(ip);
String userId = request.getRemoteUser();
Integer.parseInt(userId); // Integer.parse(String) throws RuntimeException
} catch (UnknownHostException uhex) {
throw new UnknownHostException("Got exception "+uhex.getMessage());
}
} catch (IOException ie) {
ie.printStackTrace();
}
}
// GOOD - Tests nested try-blocks with catching all exceptions.
public void doTrace(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
try {
try {
String ip = request.getParameter("srcIP");
InetAddress addr = null;
try {
addr = InetAddress.getByName(ip);
String userId = request.getRemoteUser();
Integer.parseInt(userId); // Integer.parse(String) throws RuntimeException
} catch (UnknownHostException uhex) {
throw new UnknownHostException("Got exception "+uhex.getMessage());
}
} catch (IOException ie) {
ie.printStackTrace();
}
} catch (RuntimeException re) {
re.printStackTrace();
}
}
}

View File

@@ -0,0 +1 @@
experimental/Security/CWE/CWE-600/UncaughtServletException.ql

View File

@@ -0,0 +1,59 @@
import java.io.IOException;
import java.net.InetAddress;
import java.net.UnknownHostException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.ServletException;
class UncaughtServletException2 extends HttpServlet {
// BAD - Tests rethrowing caught exceptions with stack trace using `initCause(...)`
// Note this special case is not being handled by the query since in 99% of cases we're looking for `catch(Exception e) { ... throw e; }`
public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
try {
String ip = request.getParameter("srcIP");
InetAddress addr = InetAddress.getByName(ip);
} catch (UnknownHostException uhex) {
IOException ioException = new IOException();
ioException.initCause(uhex);
throw ioException;
}
}
// BAD - Tests rethrowing caught exceptions with stack trace using the same exception variable.
// Note this special case is not being handled by the query since in 99% of cases we're looking for `catch(Exception e) { ... throw e; }`
public void doHead(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
try {
String ip = request.getParameter("srcIP");
InetAddress addr = InetAddress.getByName(ip);
} catch (UnknownHostException uhex) {
throw new IOException(uhex);
}
}
// BAD - Tests rethrowing caught exceptions with stack trace using `addSuppressed(...)`.
// Note this special case is not being handled by the query since in 99% of cases we're looking for `catch(Exception e) { ... throw e; }`
public void doTrace(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
try {
String ip = request.getParameter("srcIP");
InetAddress addr = InetAddress.getByName(ip);
} catch (UnknownHostException uhex) {
IOException ioException = new IOException();
ioException.addSuppressed(uhex);
throw ioException;
}
}
// BAD - Tests rethrowing caught exceptions with stack trace using `initCause(...)`
// Note this special case is not being handled by the query since in 99% of cases we're looking for `catch(Exception e) { ... throw e; }`
public void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
try {
String ip = request.getParameter("srcIP");
InetAddress addr = InetAddress.getByName(ip);
} catch (UnknownHostException uhex) {
IOException ioException = new IOException();
throw new IOException(ioException.initCause(uhex));
}
}
}

View File

@@ -0,0 +1 @@
// semmle-extractor-options: --javac-args -cp ${testdir}/../../../../stubs/servlet-api-2.4

View File

@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
id="myapp" version="3.0">
<display-name>myapp</display-name>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
<welcome-file>index.xhtml</welcome-file>
</welcome-file-list>
<!-- error-page>
<location>/index.jsp</location>
</error-page -->
</web-app>