Skip to content

Commit 555a202

Browse files
committed
Allow MaD sanitizers for java/http-response-splitting
1 parent 3a08156 commit 555a202

File tree

2 files changed

+28
-16
lines changed

2 files changed

+28
-16
lines changed

java/ql/lib/semmle/code/java/security/ResponseSplitting.qll

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import semmle.code.java.dataflow.FlowSources
88
import semmle.code.java.frameworks.Servlets
99
import semmle.code.java.frameworks.JaxWS
1010
private import semmle.code.java.dataflow.ExternalFlow
11+
private import semmle.code.java.security.Sanitizers
1112

1213
/** A sink that is vulnerable to an HTTP header splitting attack. */
1314
abstract class HeaderSplittingSink extends DataFlow::Node { }
@@ -16,6 +17,32 @@ private class DefaultHeaderSplittingSink extends HeaderSplittingSink {
1617
DefaultHeaderSplittingSink() { sinkNode(this, "response-splitting") }
1718
}
1819

20+
/** A sanitizer for an HTTP header splitting attack. */
21+
abstract class HeaderSplittingSanitizer extends DataFlow::Node { }
22+
23+
private class SimpleTypeHeaderSplittingSanitizer extends HeaderSplittingSanitizer instanceof SimpleTypeSanitizer
24+
{ }
25+
26+
private class ExternalHeaderSplittingSanitizer extends HeaderSplittingSanitizer {
27+
ExternalHeaderSplittingSanitizer() { barrierNode(this, "response-splitting") }
28+
}
29+
30+
private class NewlineRemovalHeaderSplittingSanitizer extends HeaderSplittingSanitizer {
31+
NewlineRemovalHeaderSplittingSanitizer() {
32+
exists(MethodCall ma, string methodName, CompileTimeConstantExpr target |
33+
this.asExpr() = ma and
34+
ma.getMethod().hasQualifiedName("java.lang", "String", methodName) and
35+
target = ma.getArgument(0) and
36+
(
37+
methodName = "replace" and target.getIntValue() = [10, 13] // 10 == "\n", 13 == "\r"
38+
or
39+
methodName = "replaceAll" and
40+
target.getStringValue().regexpMatch(".*([\n\r]|\\[\\^[^\\]\r\n]*\\]).*")
41+
)
42+
)
43+
}
44+
}
45+
1946
/** A source that introduces data considered safe to use by a header splitting source. */
2047
abstract class SafeHeaderSplittingSource extends DataFlow::Node instanceof RemoteFlowSource { }
2148

java/ql/lib/semmle/code/java/security/ResponseSplittingQuery.qll

Lines changed: 1 addition & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22

33
import java
44
private import semmle.code.java.dataflow.FlowSources
5-
private import semmle.code.java.security.Sanitizers
65
import semmle.code.java.security.ResponseSplitting
76

87
/**
@@ -16,21 +15,7 @@ module ResponseSplittingConfig implements DataFlow::ConfigSig {
1615

1716
predicate isSink(DataFlow::Node sink) { sink instanceof HeaderSplittingSink }
1817

19-
predicate isBarrier(DataFlow::Node node) {
20-
node instanceof SimpleTypeSanitizer
21-
or
22-
exists(MethodCall ma, string methodName, CompileTimeConstantExpr target |
23-
node.asExpr() = ma and
24-
ma.getMethod().hasQualifiedName("java.lang", "String", methodName) and
25-
target = ma.getArgument(0) and
26-
(
27-
methodName = "replace" and target.getIntValue() = [10, 13] // 10 == "\n", 13 == "\r"
28-
or
29-
methodName = "replaceAll" and
30-
target.getStringValue().regexpMatch(".*([\n\r]|\\[\\^[^\\]\r\n]*\\]).*")
31-
)
32-
)
33-
}
18+
predicate isBarrier(DataFlow::Node node) { node instanceof HeaderSplittingSanitizer }
3419

3520
predicate observeDiffInformedIncrementalMode() { any() }
3621
}

0 commit comments

Comments
 (0)