@@ -8,6 +8,7 @@ import semmle.code.java.dataflow.FlowSources
88import semmle.code.java.frameworks.Servlets
99import semmle.code.java.frameworks.JaxWS
1010private 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. */
1314abstract 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. */
2047abstract class SafeHeaderSplittingSource extends DataFlow:: Node instanceof RemoteFlowSource { }
2148
0 commit comments