Skip to content

Commit 3a08156

Browse files
committed
Allow MaD sanitizers for java/sql-injection, java/concatenated-sql-query and java/ip-address-spoofing
1 parent ad8b766 commit 3a08156

File tree

5 files changed

+38
-16
lines changed

5 files changed

+38
-16
lines changed

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

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,14 @@ import semmle.code.java.frameworks.javaee.Persistence
88
private import semmle.code.java.frameworks.MyBatis
99
private import semmle.code.java.dataflow.ExternalFlow
1010
private import semmle.code.java.dataflow.FlowSinks
11+
private import semmle.code.java.security.Sanitizers
1112

1213
/** A sink for database query language injection vulnerabilities. */
1314
abstract class QueryInjectionSink extends ApiSinkNode { }
1415

16+
/** A sanitizer for query injection vulnerabilities. */
17+
abstract class QueryInjectionSanitizer extends DataFlow::Node { }
18+
1519
/**
1620
* A unit class for adding additional taint steps.
1721
*
@@ -60,6 +64,13 @@ private class MongoDbInjectionSink extends QueryInjectionSink {
6064
}
6165
}
6266

67+
private class SimpleTypeQueryInjectionSanitizer extends QueryInjectionSanitizer instanceof SimpleTypeSanitizer
68+
{ }
69+
70+
private class ExternalQueryInjectionSanitizer extends QueryInjectionSanitizer {
71+
ExternalQueryInjectionSanitizer() { barrierNode(this, "sql-injection") }
72+
}
73+
6374
private class MongoJsonStep extends AdditionalQueryInjectionTaintStep {
6475
override predicate step(DataFlow::Node node1, DataFlow::Node node2) {
6576
exists(MethodCall ma |

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

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ import java
44
private import semmle.code.java.dataflow.TaintTracking
55
private import semmle.code.java.security.SqlConcatenatedLib
66
private import semmle.code.java.security.SqlInjectionQuery
7-
private import semmle.code.java.security.Sanitizers
87

98
private class UncontrolledStringBuilderSource extends DataFlow::ExprNode {
109
UncontrolledStringBuilderSource() {
@@ -23,7 +22,7 @@ module UncontrolledStringBuilderSourceFlowConfig implements DataFlow::ConfigSig
2322

2423
predicate isSink(DataFlow::Node sink) { sink instanceof QueryInjectionSink }
2524

26-
predicate isBarrier(DataFlow::Node node) { node instanceof SimpleTypeSanitizer }
25+
predicate isBarrier(DataFlow::Node node) { node instanceof QueryInjectionSanitizer }
2726

2827
predicate observeDiffInformedIncrementalMode() { any() }
2928

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

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

99
import java
1010
import semmle.code.java.dataflow.FlowSources
11-
private import semmle.code.java.security.Sanitizers
1211
import semmle.code.java.security.QueryInjection
1312

1413
/**
@@ -19,7 +18,7 @@ module QueryInjectionFlowConfig implements DataFlow::ConfigSig {
1918

2019
predicate isSink(DataFlow::Node sink) { sink instanceof QueryInjectionSink }
2120

22-
predicate isBarrier(DataFlow::Node node) { node instanceof SimpleTypeSanitizer }
21+
predicate isBarrier(DataFlow::Node node) { node instanceof QueryInjectionSanitizer }
2322

2423
predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) {
2524
any(AdditionalQueryInjectionTaintStep s).step(node1, node2)

java/ql/src/experimental/Security/CWE/CWE-348/ClientSuppliedIpUsedInSecurityCheck.ql

Lines changed: 1 addition & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@
1414
import java
1515
import semmle.code.java.dataflow.TaintTracking
1616
import semmle.code.java.dataflow.FlowSources
17-
import semmle.code.java.security.Sanitizers
1817
deprecated import ClientSuppliedIpUsedInSecurityCheckLib
1918
deprecated import ClientSuppliedIpUsedInSecurityCheckFlow::PathGraph
2019

@@ -28,18 +27,8 @@ deprecated module ClientSuppliedIpUsedInSecurityCheckConfig implements DataFlow:
2827

2928
predicate isSink(DataFlow::Node sink) { sink instanceof ClientSuppliedIpUsedInSecurityCheckSink }
3029

31-
/**
32-
* Splitting a header value by `,` and taking an entry other than the first is sanitizing, because
33-
* later entries may originate from more-trustworthy intermediate proxies, not the original client.
34-
*/
3530
predicate isBarrier(DataFlow::Node node) {
36-
exists(ArrayAccess aa, MethodCall ma | aa.getArray() = ma |
37-
ma.getQualifier() = node.asExpr() and
38-
ma.getMethod() instanceof SplitMethod and
39-
not aa.getIndexExpr().(CompileTimeConstantExpr).getIntValue() = 0
40-
)
41-
or
42-
node instanceof SimpleTypeSanitizer
31+
node instanceof ClientSuppliedIpUsedInSecurityCheckSanitizer
4332
}
4433
}
4534

java/ql/src/experimental/Security/CWE/CWE-348/ClientSuppliedIpUsedInSecurityCheckLib.qll

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import java
44
import DataFlow
55
import semmle.code.java.frameworks.Networking
66
import semmle.code.java.security.QueryInjection
7+
import semmle.code.java.security.Sanitizers
78

89
/**
910
* A data flow source of the client ip obtained according to the remote endpoint identifier specified
@@ -28,6 +29,9 @@ class ClientSuppliedIpUsedInSecurityCheck extends DataFlow::Node {
2829
/** A data flow sink for ip address forgery vulnerabilities. */
2930
abstract class ClientSuppliedIpUsedInSecurityCheckSink extends DataFlow::Node { }
3031

32+
/** A data flow sanitizer for ip address forgery vulnerabilities. */
33+
abstract class ClientSuppliedIpUsedInSecurityCheckSanitizer extends DataFlow::Node { }
34+
3135
/**
3236
* A data flow sink for remote client ip comparison.
3337
*
@@ -98,3 +102,23 @@ string getIpAddressRegex() {
98102
result =
99103
"^((10\\.((1\\d{2})?|(2[0-4]\\d)?|(25[0-5])?|([1-9]\\d|[0-9])?)(\\.)?)|(192\\.168\\.)|172\\.(1[6789]|2[0-9]|3[01])\\.)((1\\d{2})?|(2[0-4]\\d)?|(25[0-5])?|([1-9]\\d|[0-9])?)(\\.)?((1\\d{2})?|(2[0-4]\\d)?|(25[0-5])?|([1-9]\\d|[0-9])?)$"
100104
}
105+
106+
/**
107+
* Splitting a header value by `,` and taking an entry other than the first is sanitizing, because
108+
* later entries may originate from more-trustworthy intermediate proxies, not the original client.
109+
*/
110+
private class EntryAfterFirstSanitizer extends ClientSuppliedIpUsedInSecurityCheckSanitizer {
111+
EntryAfterFirstSanitizer() {
112+
exists(ArrayAccess aa, MethodCall ma | aa.getArray() = ma |
113+
ma.getQualifier() = this.asExpr() and
114+
ma.getMethod() instanceof SplitMethod and
115+
not aa.getIndexExpr().(CompileTimeConstantExpr).getIntValue() = 0
116+
)
117+
}
118+
}
119+
120+
private class SimpleTypeAddressSpoofingSanitizer extends ClientSuppliedIpUsedInSecurityCheckSanitizer instanceof SimpleTypeSanitizer
121+
{ }
122+
123+
private class SqlOperationSanitizer extends ClientSuppliedIpUsedInSecurityCheckSanitizer instanceof QueryInjectionSanitizer
124+
{ }

0 commit comments

Comments
 (0)