Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit ede9cec

Browse files
committed
Uncaught Servlet Exception
1 parent 0f8dd7c commit ede9cec

9 files changed

Lines changed: 414 additions & 1 deletion

File tree

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
import java.io.InputStream;
2+
import java.io.IOException;
3+
import java.net.InetAddress;
4+
import java.net.UnknownHostException;
5+
6+
class UncaughtServletException extends HttpServlet {
7+
// BAD: Uncaught exceptions
8+
{
9+
public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
10+
String ip = request.getParameter("srcIP");
11+
InetAddress addr = InetAddress.getByName(ip); //BAD: getByName(String) throws UnknownHostException.
12+
13+
String username = request.getRemoteUser();
14+
Integer.parseInt(username); //BAD: Integer.parse(String) throws RuntimeException.
15+
}
16+
}
17+
18+
// GOOD
19+
{
20+
public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
21+
try {
22+
String ip = request.getParameter("srcIP");
23+
InetAddress addr = InetAddress.getByName(ip);
24+
} catch (UnknownHostException uhex) { //GOOD: Catch the subclass exception UnknownHostException of IOException.
25+
uhex.printStackTrace();
26+
}
27+
}
28+
}
29+
30+
// GOOD
31+
{
32+
public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
33+
String ip = "10.100.10.81";
34+
InetAddress addr = InetAddress.getByName(ip); // OK: Hard-coded variable value or system property is not controlled by attacker.
35+
}
36+
}
37+
38+
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
<!DOCTYPE qhelp PUBLIC
2+
"-//Semmle//qhelp//EN"
3+
"qhelp.dtd">
4+
<qhelp>
5+
<overview>
6+
<p>
7+
Even though the signatures for methods in a servlet include throws IOException, ServletException, it's a bad idea to let such exceptions be thrown. Failure to catch exceptions in a servlet could leave a system in a vulnerable state, possibly resulting in denial-of-service attacks, or the exposure of sensitive information because when a servlet throws an exception, the servlet container typically sends debugging information back to the user. And that information could be very valuable to an attacker.
8+
</p>
9+
</overview>
10+
11+
<recommendation>
12+
<p>
13+
Handle method calls that throw IOExceptions and/or RuntimeExceptions and display custom error messages without stack traces and sensitive information.
14+
</p>
15+
</recommendation>
16+
17+
<example>
18+
<p>
19+
In the first and second examples, subclasses of IOException and RuntimeException are not caught, which disclose stack traces.
20+
</p>
21+
22+
<p>
23+
In the third example, the code catches the exception. In the fourth example, the code is not of concern since the variable cannot be controlled by attackers thus no unexpected exceptions can be thrown.
24+
</p>
25+
<sample src="UncaughtServletException.java" />
26+
</example>
27+
28+
<references>
29+
<li>CWE: <a href="https://cwe.mitre.org/data/definitions/600.html">CWE-600: Uncaught Exception in Servlet</a>.</li>
30+
<li>Sonarsource: <a href="https://rules.sonarsource.com/java/tag/owasp/RSPEC-1989">Exceptions should not be thrown from servlet methods</a>.</li>
31+
<li>OWASP: <a href="https://cheatsheetseries.owasp.org/cheatsheets/Error_Handling_Cheat_Sheet.html">Error Handling Cheat Sheet</a>.</li>
32+
</references>
33+
</qhelp>
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
/**
2+
* @name Uncaught Servlet Exception
3+
* @description Uncaught exceptions in a servlet could leave a system in a vulnerable state, possibly resulting in denial-of-service attacks or the exposure of sensitive information disclosed in stack traces.
4+
* @kind path-problem
5+
* @id java/uncaught-servlet-exception
6+
* @tags security
7+
* external/cwe-600
8+
*/
9+
10+
import java
11+
import semmle.code.java.dataflow.FlowSources
12+
import semmle.code.java.dataflow.TaintTracking
13+
import semmle.code.java.frameworks.Servlets
14+
import DataFlow::PathGraph
15+
16+
/** The type `java.io.IOException`. */
17+
class IOException extends RefType {
18+
IOException() { this.hasQualifiedName("java.io", "IOException") }
19+
}
20+
21+
/** Check whether a given exception type is caught. */
22+
private predicate catchesEx(TryStmt t, RefType exType) {
23+
exists(CatchClause cc, LocalVariableDeclExpr v |
24+
t.getACatchClause() = cc and
25+
cc.getVariable() = v and
26+
v
27+
.getType()
28+
.(RefType)
29+
.getASubtype*()
30+
.hasQualifiedName(exType.getPackage().getName(), exType.getName()) //Detect the case that a subclass exception is thrown but its parent class is declared in the catch clause.
31+
)
32+
}
33+
34+
/** Servlet methods of `javax.servlet.http.HttpServlet`. */
35+
private predicate isServletMethod(Callable c) {
36+
c.getDeclaringType() instanceof ServletClass and
37+
c.getNumberOfParameters() = 2 and
38+
c.getParameter(1).getType() instanceof HttpServletResponse and
39+
(
40+
c.getName() = "doGet" or
41+
c.getName() = "doPost" or
42+
c.getName() = "doPut" or
43+
c.getName() = "doDelete"
44+
)
45+
}
46+
47+
/** Sink of uncaught IO exceptions or runtime exceptions since other exception types must be explicitly caught. */
48+
class UncaughtServletExceptionSink extends DataFlow::ExprNode {
49+
UncaughtServletExceptionSink() {
50+
exists(Method m, MethodAccess ma | ma.getMethod() = m |
51+
isServletMethod(ma.getEnclosingCallable()) and
52+
(
53+
m.getAThrownExceptionType().getASupertype*() instanceof IOException or
54+
m
55+
.getAThrownExceptionType()
56+
.getASupertype*()
57+
.hasQualifiedName("java.lang", "RuntimeException")
58+
) and
59+
ma.getAnArgument() = this.getExpr() and
60+
not exists(TryStmt t |
61+
t.getBlock() = ma.getEnclosingStmt().getEnclosingStmt*() and
62+
catchesEx(t, m.getAThrownExceptionType())
63+
)
64+
)
65+
}
66+
}
67+
68+
class UncaughtServletExceptionConfiguration extends TaintTracking::Configuration {
69+
UncaughtServletExceptionConfiguration() { this = "UncaughtServletException" }
70+
71+
override predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource }
72+
73+
override predicate isSink(DataFlow::Node sink) { sink instanceof UncaughtServletExceptionSink }
74+
}
75+
76+
from DataFlow::PathNode source, DataFlow::PathNode sink, UncaughtServletExceptionConfiguration c
77+
where c.hasFlowPath(source, sink)
78+
select sink.getNode(), source, sink, "$@ flows to here and can throw uncaught exception.",
79+
source.getNode(), "User-provided value"
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
edges
2+
| UncaughtServletException.java:12:15:12:43 | getParameter(...) : String | UncaughtServletException.java:13:44:13:45 | ip |
3+
| UncaughtServletException.java:15:19:15:41 | getRemoteUser(...) : String | UncaughtServletException.java:16:20:16:25 | userId |
4+
nodes
5+
| UncaughtServletException.java:12:15:12:43 | getParameter(...) : String | semmle.label | getParameter(...) : String |
6+
| UncaughtServletException.java:13:44:13:45 | ip | semmle.label | ip |
7+
| UncaughtServletException.java:15:19:15:41 | getRemoteUser(...) : String | semmle.label | getRemoteUser(...) : String |
8+
| UncaughtServletException.java:16:20:16:25 | userId | semmle.label | userId |
9+
#select
10+
| UncaughtServletException.java:13:44:13:45 | ip | UncaughtServletException.java:12:15:12:43 | getParameter(...) : String | UncaughtServletException.java:13:44:13:45 | ip | $@ flows to here and can throw uncaught exception. | UncaughtServletException.java:12:15:12:43 | getParameter(...) | User-provided value |
11+
| UncaughtServletException.java:16:20:16:25 | userId | UncaughtServletException.java:15:19:15:41 | getRemoteUser(...) : String | UncaughtServletException.java:16:20:16:25 | userId | $@ flows to here and can throw uncaught exception. | UncaughtServletException.java:15:19:15:41 | getRemoteUser(...) | User-provided value |
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
import java.io.IOException;
2+
import java.net.InetAddress;
3+
import java.net.UnknownHostException;
4+
5+
import javax.servlet.http.HttpServlet;
6+
import javax.servlet.http.HttpServletRequest;
7+
import javax.servlet.http.HttpServletResponse;
8+
import javax.servlet.ServletException;
9+
10+
class UncaughtServletException extends HttpServlet {
11+
public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
12+
String ip = request.getParameter("srcIP");
13+
InetAddress addr = InetAddress.getByName(ip); // BAD: getByName(String) throws UnknownHostException
14+
15+
String userId = request.getRemoteUser();
16+
Integer.parseInt(userId); //BAD: Integer.parse(String) throws RuntimeException
17+
}
18+
19+
public void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
20+
try {
21+
String ip = request.getParameter("srcIP");
22+
InetAddress addr = InetAddress.getByName(ip);
23+
} catch (UnknownHostException uhex) {
24+
uhex.printStackTrace();
25+
}}
26+
27+
public void doPut(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
28+
String ip = "10.100.10.81";
29+
InetAddress addr = InetAddress.getByName(ip); // GOOD: hard-coded variable value or system property not controlled by attacker
30+
}
31+
32+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
experimental/Security/CWE/CWE-600/UncaughtServletException.ql
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
// semmle-extractor-options: --javac-args -cp ${testdir}/../../../../stubs/servlet-api-2.4

0 commit comments

Comments
 (0)