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

Skip to content

Commit a29f615

Browse files
committed
Java: Add additional taint steps through collections.
1 parent bfb8125 commit a29f615

5 files changed

Lines changed: 119 additions & 2 deletions

File tree

change-notes/1.20/analysis-java.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,5 +24,8 @@
2424
`semmle.code.java.dataflow.DataFlow`,
2525
`semmle.code.java.dataflow.TaintTracking`, and
2626
`semmle.code.java.dataflow.FlowSources` since 1.16.
27+
* Taint tracking now includes additional default data-flow steps through
28+
collections, maps, and iterators. This affects all security queries, which
29+
can report more results based on such paths.
2730

2831

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

Lines changed: 62 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ private import DefUse
1212
private import semmle.code.java.security.SecurityTests
1313
private import semmle.code.java.security.Validation
1414
private import semmle.code.java.frameworks.android.Intent
15+
private import semmle.code.java.Maps
1516

1617
module TaintTracking {
1718
/**
@@ -209,6 +210,12 @@ module TaintTracking {
209210
sink = assign.getDest().(ArrayAccess).getArray()
210211
)
211212
or
213+
exists(EnhancedForStmt for, SsaExplicitUpdate v |
214+
for.getExpr() = src and
215+
v.getDefiningExpr() = for.getVariable() and
216+
v.getAFirstUse() = sink
217+
)
218+
or
212219
constructorStep(src, sink)
213220
or
214221
qualifierToMethodStep(src, sink)
@@ -418,8 +425,49 @@ module TaintTracking {
418425
or
419426
m instanceof IntentGetExtraMethod
420427
or
421-
m instanceof CollectionMethod and
422-
m.hasName("toArray")
428+
m
429+
.getDeclaringType()
430+
.getSourceDeclaration()
431+
.getASourceSupertype*()
432+
.hasQualifiedName("java.util", "Map<>$Entry") and
433+
m.hasName("getValue")
434+
or
435+
m
436+
.getDeclaringType()
437+
.getSourceDeclaration()
438+
.getASourceSupertype*()
439+
.hasQualifiedName("java.lang", "Iterable") and
440+
m.hasName("iterator")
441+
or
442+
m
443+
.getDeclaringType()
444+
.getSourceDeclaration()
445+
.getASourceSupertype*()
446+
.hasQualifiedName("java.util", "Iterator") and
447+
m.hasName("next")
448+
or
449+
m.getDeclaringType().getSourceDeclaration().hasQualifiedName("java.util", "Enumeration") and
450+
m.hasName("nextElement")
451+
or
452+
m.(MapMethod).hasName("entrySet")
453+
or
454+
m.(MapMethod).hasName("get")
455+
or
456+
m.(MapMethod).hasName("remove")
457+
or
458+
m.(MapMethod).hasName("values")
459+
or
460+
m.(CollectionMethod).hasName("toArray")
461+
or
462+
m.(CollectionMethod).hasName("get")
463+
or
464+
m.(CollectionMethod).hasName("remove") and m.getParameterType(0).(PrimitiveType).hasName("int")
465+
or
466+
m.(CollectionMethod).hasName("subList")
467+
or
468+
m.(CollectionMethod).hasName("firstElement")
469+
or
470+
m.(CollectionMethod).hasName("lastElement")
423471
or
424472
m.getDeclaringType().hasQualifiedName("java.nio", "ByteBuffer") and
425473
m.hasName("get")
@@ -596,6 +644,18 @@ module TaintTracking {
596644
method.getDeclaringType().hasQualifiedName("java.io", "ByteArrayOutputStream") and
597645
method.hasName("write") and
598646
arg = 0
647+
or
648+
method.(MapMethod).hasName("put") and arg = 1
649+
or
650+
method.(MapMethod).hasName("putAll") and arg = 0
651+
or
652+
method.(CollectionMethod).hasName("add") and arg = method.getNumberOfParameters() - 1
653+
or
654+
method.(CollectionMethod).hasName("addAll") and arg = method.getNumberOfParameters() - 1
655+
or
656+
method.(CollectionMethod).hasName("addElement") and arg = 0
657+
or
658+
method.(CollectionMethod).hasName("set") and arg = 1
599659
}
600660

601661
/** A comparison or equality test with a constant. */
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import java.util.*;
2+
3+
public class Test {
4+
static String tainted;
5+
6+
void sink(Object o) { }
7+
8+
public void run() {
9+
HashMap<String, String> m = new HashMap<>();
10+
String x1 = m.get("key");
11+
sink(x1); // No flow
12+
13+
m.put("key", tainted);
14+
String x2 = m.get("key");
15+
sink(x2); // Flow
16+
17+
String x3 = m.values().toArray(new String[1])[0];
18+
sink(x3); // Flow
19+
20+
for(Map.Entry<String, String> e : m.entrySet()) {
21+
String x4 = e.getValue();
22+
sink(x4); // Flow
23+
}
24+
25+
Iterator<String> it = m.values().iterator();
26+
String x5 = it.next();
27+
sink(x5); // Flow
28+
}
29+
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
| Test.java:13:18:13:24 | tainted | Test.java:15:10:15:11 | x2 |
2+
| Test.java:13:18:13:24 | tainted | Test.java:18:10:18:11 | x3 |
3+
| Test.java:13:18:13:24 | tainted | Test.java:22:12:22:13 | x4 |
4+
| Test.java:13:18:13:24 | tainted | Test.java:27:10:27:11 | x5 |
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import java
2+
import semmle.code.java.dataflow.TaintTracking
3+
4+
class Conf extends TaintTracking::Configuration {
5+
Conf() { this = "conf" }
6+
7+
override predicate isSource(DataFlow::Node src) {
8+
src.asExpr().(VarAccess).getVariable().hasName("tainted")
9+
}
10+
11+
override predicate isSink(DataFlow::Node sink) {
12+
exists(MethodAccess ma |
13+
sink.asExpr() = ma.getAnArgument() and
14+
ma.getMethod().hasName("sink")
15+
)
16+
}
17+
}
18+
19+
from Conf c, DataFlow::Node src, DataFlow::Node sink
20+
where c.hasFlow(src, sink)
21+
select src, sink

0 commit comments

Comments
 (0)