Skip to content

Commit 8a20395

Browse files
authored
Merge pull request github#5940 from pwntester/main
Remove XSS sink for Java
2 parents c0e562d + a3a215a commit 8a20395

File tree

9 files changed

+89
-64
lines changed

9 files changed

+89
-64
lines changed
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
lgtm,codescanning
2+
* The query "Cross-site scripting" (`java/xss`) has been improved to report fewer false positives by removing the `javax.servlet.http.HttpServletResponse.sendError` sink since Servlet API implementations generally already escape the error message, preventing script injection.
Lines changed: 42 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,42 +1,42 @@
1-
package,sink,source,summary,sink:bean-validation,sink:create-file,sink:header-splitting,sink:ldap,sink:open-url,sink:set-hostname-verifier,sink:url-open-stream,sink:xpath,sink:xss,source:remote,summary:taint,summary:value
2-
android.util,,16,,,,,,,,,,,16,,
3-
android.webkit,3,2,,,,,,,,,,3,2,,
4-
com.esotericsoftware.kryo.io,,,1,,,,,,,,,,,1,
5-
com.esotericsoftware.kryo5.io,,,1,,,,,,,,,,,1,
6-
com.fasterxml.jackson.databind,,,2,,,,,,,,,,,2,
7-
com.google.common.base,,,28,,,,,,,,,,,22,6
8-
com.google.common.io,6,,69,,,,,,,6,,,,68,1
9-
com.unboundid.ldap.sdk,17,,,,,,17,,,,,,,,
10-
java.beans,,,1,,,,,,,,,,,1,
11-
java.io,3,,20,,3,,,,,,,,,20,
12-
java.lang,,,1,,,,,,,,,,,1,
13-
java.net,2,3,4,,,,,2,,,,,3,4,
14-
java.nio,10,,2,,10,,,,,,,,,2,
15-
java.util,,,13,,,,,,,,,,,13,
16-
javax.naming.directory,1,,,,,,1,,,,,,,,
17-
javax.net.ssl,2,,,,,,,,2,,,,,,
18-
javax.servlet,4,21,2,,,3,,,,,,1,21,2,
19-
javax.validation,1,1,,1,,,,,,,,,1,,
20-
javax.ws.rs.core,1,,,,,1,,,,,,,,,
21-
javax.xml.transform.sax,,,4,,,,,,,,,,,4,
22-
javax.xml.transform.stream,,,2,,,,,,,,,,,2,
23-
javax.xml.xpath,3,,,,,,,,,,3,,,,
24-
org.apache.commons.codec,,,2,,,,,,,,,,,2,
25-
org.apache.commons.io,,,22,,,,,,,,,,,22,
26-
org.apache.commons.lang3,,,313,,,,,,,,,,,299,14
27-
org.apache.commons.text,,,203,,,,,,,,,,,203,
28-
org.apache.directory.ldap.client.api,1,,,,,,1,,,,,,,,
29-
org.apache.hc.core5.function,,,1,,,,,,,,,,,1,
30-
org.apache.hc.core5.http,1,2,39,,,,,,,,,1,2,39,
31-
org.apache.hc.core5.net,,,2,,,,,,,,,,,2,
32-
org.apache.hc.core5.util,,,22,,,,,,,,,,,18,4
33-
org.apache.http,2,3,66,,,,,,,,,2,3,59,7
34-
org.dom4j,20,,,,,,,,,,20,,,,
35-
org.springframework.ldap.core,14,,,,,,14,,,,,,,,
36-
org.springframework.security.web.savedrequest,,6,,,,,,,,,,,6,,
37-
org.springframework.web.client,,3,,,,,,,,,,,3,,
38-
org.springframework.web.context.request,,8,,,,,,,,,,,8,,
39-
org.springframework.web.multipart,,12,,,,,,,,,,,12,,
40-
org.xml.sax,,,1,,,,,,,,,,,1,
41-
org.xmlpull.v1,,3,,,,,,,,,,,3,,
42-
play.mvc,,4,,,,,,,,,,,4,,
1+
package,sink,source,summary,sink:bean-validation,sink:create-file,sink:header-splitting,sink:information-leak,sink:ldap,sink:open-url,sink:set-hostname-verifier,sink:url-open-stream,sink:xpath,sink:xss,source:remote,summary:taint,summary:value
2+
android.util,,16,,,,,,,,,,,,16,,
3+
android.webkit,3,2,,,,,,,,,,,3,2,,
4+
com.esotericsoftware.kryo.io,,,1,,,,,,,,,,,,1,
5+
com.esotericsoftware.kryo5.io,,,1,,,,,,,,,,,,1,
6+
com.fasterxml.jackson.databind,,,2,,,,,,,,,,,,2,
7+
com.google.common.base,,,28,,,,,,,,,,,,22,6
8+
com.google.common.io,6,,69,,,,,,,,6,,,,68,1
9+
com.unboundid.ldap.sdk,17,,,,,,,17,,,,,,,,
10+
java.beans,,,1,,,,,,,,,,,,1,
11+
java.io,3,,20,,3,,,,,,,,,,20,
12+
java.lang,,,1,,,,,,,,,,,,1,
13+
java.net,2,3,4,,,,,,2,,,,,3,4,
14+
java.nio,10,,2,,10,,,,,,,,,,2,
15+
java.util,,,13,,,,,,,,,,,,13,
16+
javax.naming.directory,1,,,,,,,1,,,,,,,,
17+
javax.net.ssl,2,,,,,,,,,2,,,,,,
18+
javax.servlet,4,21,2,,,3,1,,,,,,,21,2,
19+
javax.validation,1,1,,1,,,,,,,,,,1,,
20+
javax.ws.rs.core,1,,,,,1,,,,,,,,,,
21+
javax.xml.transform.sax,,,4,,,,,,,,,,,,4,
22+
javax.xml.transform.stream,,,2,,,,,,,,,,,,2,
23+
javax.xml.xpath,3,,,,,,,,,,,3,,,,
24+
org.apache.commons.codec,,,2,,,,,,,,,,,,2,
25+
org.apache.commons.io,,,22,,,,,,,,,,,,22,
26+
org.apache.commons.lang3,,,313,,,,,,,,,,,,299,14
27+
org.apache.commons.text,,,203,,,,,,,,,,,,203,
28+
org.apache.directory.ldap.client.api,1,,,,,,,1,,,,,,,,
29+
org.apache.hc.core5.function,,,1,,,,,,,,,,,,1,
30+
org.apache.hc.core5.http,1,2,39,,,,,,,,,,1,2,39,
31+
org.apache.hc.core5.net,,,2,,,,,,,,,,,,2,
32+
org.apache.hc.core5.util,,,22,,,,,,,,,,,,18,4
33+
org.apache.http,2,3,66,,,,,,,,,,2,3,59,7
34+
org.dom4j,20,,,,,,,,,,,20,,,,
35+
org.springframework.ldap.core,14,,,,,,,14,,,,,,,,
36+
org.springframework.security.web.savedrequest,,6,,,,,,,,,,,,6,,
37+
org.springframework.web.client,,3,,,,,,,,,,,,3,,
38+
org.springframework.web.context.request,,8,,,,,,,,,,,,8,,
39+
org.springframework.web.multipart,,12,,,,,,,,,,,,12,,
40+
org.xml.sax,,,1,,,,,,,,,,,,1,
41+
org.xmlpull.v1,,3,,,,,,,,,,,,3,,
42+
play.mvc,,4,,,,,,,,,,,,4,,

java/documentation/library-coverage/flow-model-coverage.rst

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@ Java framework & library support
1212
`Apache Commons IO <https://commons.apache.org/proper/commons-io/>`_,``org.apache.commons.io``,,22,,,,,,,,
1313
Google,``com.google.common.*``,,97,6,,6,,,,,
1414
Java Standard Library,``java.*``,3,41,15,13,,,,,,2
15-
Java extensions,``javax.*``,22,8,12,,,1,,1,1,
15+
Java extensions,``javax.*``,22,8,12,,,,,1,1,
1616
`Spring <https://spring.io/>`_,``org.springframework.*``,29,,14,,,,,14,,
1717
Others,"``com.esotericsoftware.kryo.io``, ``com.esotericsoftware.kryo5.io``, ``com.fasterxml.jackson.databind``, ``com.unboundid.ldap.sdk``, ``org.dom4j``, ``org.xml.sax``, ``org.xmlpull.v1``, ``play.mvc``",7,5,37,,,,,17,,
18-
Totals,,84,821,91,13,6,7,,33,1,2
18+
Totals,,84,821,91,13,6,6,,33,1,2
1919

java/ql/src/Security/CWE/CWE-209/StackTraceExposure.ql

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
import java
1616
import semmle.code.java.dataflow.DataFlow
1717
import semmle.code.java.dataflow.TaintTracking
18-
import semmle.code.java.security.XSS
18+
import semmle.code.java.security.InformationLeak
1919

2020
/**
2121
* One of the `printStackTrace()` overloads on `Throwable`.
@@ -83,14 +83,14 @@ predicate stackTraceExpr(Expr exception, MethodAccess stackTraceString) {
8383
)
8484
}
8585

86-
class StackTraceStringToXssSinkFlowConfig extends TaintTracking::Configuration {
87-
StackTraceStringToXssSinkFlowConfig() {
88-
this = "StackTraceExposure::StackTraceStringToXssSinkFlowConfig"
86+
class StackTraceStringToHttpResponseSinkFlowConfig extends TaintTracking::Configuration {
87+
StackTraceStringToHttpResponseSinkFlowConfig() {
88+
this = "StackTraceExposure::StackTraceStringToHttpResponseSinkFlowConfig"
8989
}
9090

9191
override predicate isSource(DataFlow::Node src) { stackTraceExpr(_, src.asExpr()) }
9292

93-
override predicate isSink(DataFlow::Node sink) { sink instanceof XssSink }
93+
override predicate isSink(DataFlow::Node sink) { sink instanceof InformationLeakSink }
9494
}
9595

9696
/**
@@ -105,8 +105,8 @@ predicate printsStackExternally(MethodAccess call, Expr stackTrace) {
105105
/**
106106
* A stringified stack trace flows to an external sink.
107107
*/
108-
predicate stringifiedStackFlowsExternally(XssSink externalExpr, Expr stackTrace) {
109-
exists(MethodAccess stackTraceString, StackTraceStringToXssSinkFlowConfig conf |
108+
predicate stringifiedStackFlowsExternally(DataFlow::Node externalExpr, Expr stackTrace) {
109+
exists(MethodAccess stackTraceString, StackTraceStringToHttpResponseSinkFlowConfig conf |
110110
stackTraceExpr(stackTrace, stackTraceString) and
111111
conf.hasFlow(DataFlow::exprNode(stackTraceString), externalExpr)
112112
)
@@ -123,21 +123,21 @@ class GetMessageFlowSource extends MethodAccess {
123123
}
124124
}
125125

126-
class GetMessageFlowSourceToXssSinkFlowConfig extends TaintTracking::Configuration {
127-
GetMessageFlowSourceToXssSinkFlowConfig() {
128-
this = "StackTraceExposure::GetMessageFlowSourceToXssSinkFlowConfig"
126+
class GetMessageFlowSourceToHttpResponseSinkFlowConfig extends TaintTracking::Configuration {
127+
GetMessageFlowSourceToHttpResponseSinkFlowConfig() {
128+
this = "StackTraceExposure::GetMessageFlowSourceToHttpResponseSinkFlowConfig"
129129
}
130130

131131
override predicate isSource(DataFlow::Node src) { src.asExpr() instanceof GetMessageFlowSource }
132132

133-
override predicate isSink(DataFlow::Node sink) { sink instanceof XssSink }
133+
override predicate isSink(DataFlow::Node sink) { sink instanceof InformationLeakSink }
134134
}
135135

136136
/**
137137
* A call to `getMessage()` that then flows to a servlet response.
138138
*/
139-
predicate getMessageFlowsExternally(XssSink externalExpr, GetMessageFlowSource getMessage) {
140-
any(GetMessageFlowSourceToXssSinkFlowConfig conf)
139+
predicate getMessageFlowsExternally(DataFlow::Node externalExpr, GetMessageFlowSource getMessage) {
140+
any(GetMessageFlowSourceToHttpResponseSinkFlowConfig conf)
141141
.hasFlow(DataFlow::exprNode(getMessage), externalExpr)
142142
}
143143

java/ql/src/semmle/code/java/dataflow/ExternalFlow.qll

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ private module Frameworks {
8080
private import semmle.code.java.frameworks.guava.Guava
8181
private import semmle.code.java.frameworks.jackson.JacksonSerializability
8282
private import semmle.code.java.security.ResponseSplitting
83+
private import semmle.code.java.security.InformationLeak
8384
private import semmle.code.java.security.XSS
8485
private import semmle.code.java.security.LdapInjection
8586
private import semmle.code.java.security.XPath
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
/** Provides classes to reason about System Information Leak vulnerabilities. */
2+
3+
import java
4+
import semmle.code.java.dataflow.DataFlow
5+
import semmle.code.java.dataflow.ExternalFlow
6+
import semmle.code.java.security.XSS
7+
8+
/** CSV sink models representing methods not susceptible to XSS but outputing to an HTTP response body. */
9+
private class DefaultInformationLeakSinkModel extends SinkModelCsv {
10+
override predicate row(string row) {
11+
row =
12+
[
13+
"javax.servlet.http;HttpServletResponse;false;sendError;(int,String);;Argument[1];information-leak"
14+
]
15+
}
16+
}
17+
18+
/** A sink that represent a method that outputs data to an HTTP response. */
19+
abstract class InformationLeakSink extends DataFlow::Node { }
20+
21+
/** A default sink representing methods outputing data to an HTTP response. */
22+
private class DefaultInformationLeakSink extends InformationLeakSink {
23+
DefaultInformationLeakSink() {
24+
sinkNode(this, "information-leak") or
25+
this instanceof XssSink
26+
}
27+
}

java/ql/src/semmle/code/java/security/XSS.qll

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,6 @@ private class DefaultXssSinkModel extends SinkModelCsv {
3434
override predicate row(string row) {
3535
row =
3636
[
37-
"javax.servlet.http;HttpServletResponse;false;sendError;(int,String);;Argument[1];xss",
3837
"android.webkit;WebView;false;loadData;;;Argument[0];xss",
3938
"android.webkit;WebView;false;loadUrl;;;Argument[0];xss",
4039
"android.webkit;WebView;false;loadDataWithBaseURL;;;Argument[1];xss"
Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,15 @@
11
edges
22
| XSS.java:23:21:23:48 | getParameter(...) : String | XSS.java:23:5:23:70 | ... + ... |
3-
| XSS.java:27:21:27:48 | getParameter(...) : String | XSS.java:27:5:27:70 | ... + ... |
43
| XSS.java:38:67:38:87 | getPathInfo(...) : String | XSS.java:38:30:38:87 | ... + ... |
54
| XSS.java:41:36:41:56 | getPathInfo(...) : String | XSS.java:41:36:41:67 | getBytes(...) |
65
nodes
76
| XSS.java:23:5:23:70 | ... + ... | semmle.label | ... + ... |
87
| XSS.java:23:21:23:48 | getParameter(...) : String | semmle.label | getParameter(...) : String |
9-
| XSS.java:27:5:27:70 | ... + ... | semmle.label | ... + ... |
10-
| XSS.java:27:21:27:48 | getParameter(...) : String | semmle.label | getParameter(...) : String |
118
| XSS.java:38:30:38:87 | ... + ... | semmle.label | ... + ... |
129
| XSS.java:38:67:38:87 | getPathInfo(...) : String | semmle.label | getPathInfo(...) : String |
1310
| XSS.java:41:36:41:56 | getPathInfo(...) : String | semmle.label | getPathInfo(...) : String |
1411
| XSS.java:41:36:41:67 | getBytes(...) | semmle.label | getBytes(...) |
1512
#select
1613
| XSS.java:23:5:23:70 | ... + ... | XSS.java:23:21:23:48 | getParameter(...) : String | XSS.java:23:5:23:70 | ... + ... | Cross-site scripting vulnerability due to $@. | XSS.java:23:21:23:48 | getParameter(...) | user-provided value |
17-
| XSS.java:27:5:27:70 | ... + ... | XSS.java:27:21:27:48 | getParameter(...) : String | XSS.java:27:5:27:70 | ... + ... | Cross-site scripting vulnerability due to $@. | XSS.java:27:21:27:48 | getParameter(...) | user-provided value |
1814
| XSS.java:38:30:38:87 | ... + ... | XSS.java:38:67:38:87 | getPathInfo(...) : String | XSS.java:38:30:38:87 | ... + ... | Cross-site scripting vulnerability due to $@. | XSS.java:38:67:38:87 | getPathInfo(...) | user-provided value |
1915
| XSS.java:41:36:41:67 | getBytes(...) | XSS.java:41:36:41:56 | getPathInfo(...) : String | XSS.java:41:36:41:67 | getBytes(...) | Cross-site scripting vulnerability due to $@. | XSS.java:41:36:41:56 | getPathInfo(...) | user-provided value |

java/ql/test/query-tests/security/CWE-079/semmle/tests/XSS.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,15 +22,15 @@ protected void doGet(HttpServletRequest request, HttpServletResponse response)
2222
response.getWriter().print(
2323
"The page \"" + request.getParameter("page") + "\" was not found.");
2424

25-
// BAD: a request parameter is written directly to an error response page
25+
// GOOD: servlet API encodes the error message HTML for the HTML context
2626
response.sendError(HttpServletResponse.SC_NOT_FOUND,
2727
"The page \"" + request.getParameter("page") + "\" was not found.");
2828

2929
// GOOD: escape HTML characters first
3030
response.sendError(HttpServletResponse.SC_NOT_FOUND,
3131
"The page \"" + encodeForHtml(request.getParameter("page")) + "\" was not found.");
3232

33-
// FALSE NEGATIVE: passed through function that is not a secure check
33+
// GOOD: servlet API encodes the error message HTML for the HTML context
3434
response.sendError(HttpServletResponse.SC_NOT_FOUND,
3535
"The page \"" + capitalizeName(request.getParameter("page")) + "\" was not found.");
3636

0 commit comments

Comments
 (0)