Skip to content

Commit f056ea6

Browse files
committed
Add example for TaintAnalysis
1 parent 612ea90 commit f056ea6

17 files changed

+454
-84
lines changed

examples/TaintAnalysis/.gitignore

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
target/
2+
!.mvn/wrapper/maven-wrapper.jar
3+
!**/src/main/**/target/
4+
!**/src/test/**/target/
5+
6+
### IntelliJ IDEA ###
7+
.idea/modules.xml
8+
.idea/jarRepositories.xml
9+
.idea/compiler.xml
10+
.idea/libraries/
11+
*.iws
12+
*.iml
13+
*.ipr
14+
15+
### Eclipse ###
16+
.apt_generated
17+
.classpath
18+
.factorypath
19+
.project
20+
.settings
21+
.springBeans
22+
.sts4-cache
23+
24+
### NetBeans ###
25+
/nbproject/private/
26+
/nbbuild/
27+
/dist/
28+
/nbdist/
29+
/.nb-gradle/
30+
build/
31+
!**/src/main/**/build/
32+
!**/src/test/**/build/
33+
34+
### VS Code ###
35+
.vscode/
36+
37+
### Mac OS ###
38+
.DS_Store

examples/TaintAnalysis/pom.xml

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<project xmlns="http://maven.apache.org/POM/4.0.0"
3+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
5+
<modelVersion>4.0.0</modelVersion>
6+
7+
<groupId>org.example</groupId>
8+
<artifactId>TaintAnalysis</artifactId>
9+
<version>1.0.0</version>
10+
11+
<properties>
12+
<maven.compiler.source>11</maven.compiler.source>
13+
<maven.compiler.target>11</maven.compiler.target>
14+
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
15+
16+
<boomerang.version>4.3.2</boomerang.version>
17+
<license.dir>../license_header.txt</license.dir>
18+
</properties>
19+
20+
<dependencies>
21+
<dependency>
22+
<groupId>de.fraunhofer.iem</groupId>
23+
<artifactId>boomerangPDS</artifactId>
24+
<version>${boomerang.version}</version>
25+
</dependency>
26+
<dependency>
27+
<groupId>de.fraunhofer.iem</groupId>
28+
<artifactId>boomerangScope-SootUp</artifactId>
29+
<version>${boomerang.version}</version>
30+
</dependency>
31+
</dependencies>
32+
</project>
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
package boomerang.example;
2+
3+
import boomerang.example.analysis.TaintAnalysis;
4+
import boomerang.example.analysis.TaintDataFlowScope;
5+
import boomerang.scope.DataFlowScope;
6+
import boomerang.scope.FrameworkScope;
7+
import boomerang.scope.sootup.BoomerangPreInterceptor;
8+
import boomerang.scope.sootup.SootUpFrameworkScope;
9+
import boomerang.utils.MethodWrapper;
10+
import sootup.callgraph.CallGraph;
11+
import sootup.callgraph.CallGraphAlgorithm;
12+
import sootup.callgraph.RapidTypeAnalysisAlgorithm;
13+
import sootup.core.inputlocation.AnalysisInputLocation;
14+
import sootup.core.model.SourceType;
15+
import sootup.core.signatures.MethodSignature;
16+
import sootup.core.transform.BodyInterceptor;
17+
import sootup.java.bytecode.frontend.inputlocation.JavaClassPathAnalysisInputLocation;
18+
import sootup.java.core.JavaSootMethod;
19+
import sootup.java.core.views.JavaView;
20+
21+
import java.util.Collection;
22+
import java.util.HashSet;
23+
import java.util.List;
24+
import java.util.Optional;
25+
import java.util.Set;
26+
27+
public class Main {
28+
29+
private static final String appToAnalyze = "./targets/BranchingSingleExample.jar";
30+
31+
private static final Collection<MethodWrapper> sources =
32+
Set.of(new MethodWrapper("taints.SourceClass", "source", "java.lang.String"));
33+
34+
private static final Collection<MethodWrapper> sinks =
35+
Set.of(new MethodWrapper("taints.SinkClass", "sink", "void", List.of("java.lang.String")));
36+
37+
public static void main(String[] args) {
38+
List<BodyInterceptor> interceptors = List.of(new BoomerangPreInterceptor());
39+
AnalysisInputLocation inputLocation =
40+
new JavaClassPathAnalysisInputLocation(appToAnalyze, SourceType.Application, interceptors);
41+
JavaView view = new JavaView(inputLocation);
42+
43+
CallGraphAlgorithm cgAlgorithm = new RapidTypeAnalysisAlgorithm(view);
44+
CallGraph callGraph = cgAlgorithm.initialize();
45+
46+
Collection<JavaSootMethod> entryPoints = new HashSet<>();
47+
for (MethodSignature signature : callGraph.getEntryMethods()) {
48+
Optional<JavaSootMethod> method = view.getMethod(signature);
49+
50+
method.ifPresent(entryPoints::add);
51+
}
52+
53+
DataFlowScope dataFlowScope = new TaintDataFlowScope(sources, sinks);
54+
FrameworkScope frameworkScope =
55+
new SootUpFrameworkScope(view, callGraph, entryPoints, dataFlowScope);
56+
57+
TaintAnalysis taintAnalysis = new TaintAnalysis(frameworkScope, sources, sinks);
58+
taintAnalysis.run();
59+
}
60+
}
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
package boomerang.example.analysis;
2+
3+
import boomerang.options.IAllocationSite;
4+
import boomerang.scope.AllocVal;
5+
import boomerang.scope.DeclaredMethod;
6+
import boomerang.scope.Method;
7+
import boomerang.scope.Statement;
8+
import boomerang.scope.Val;
9+
import boomerang.utils.MethodWrapper;
10+
11+
import java.util.Collection;
12+
import java.util.Optional;
13+
14+
public class TaintAllocationSite implements IAllocationSite {
15+
16+
private final Collection<MethodWrapper> sources;
17+
18+
public TaintAllocationSite(Collection<MethodWrapper> sources) {
19+
this.sources = sources;
20+
}
21+
22+
@Override
23+
public Optional<AllocVal> getAllocationSite(Method method, Statement statement, Val val) {
24+
if (!statement.isAssignStmt()) {
25+
return Optional.empty();
26+
}
27+
28+
Val leftOp = statement.getLeftOp();
29+
Val rightOp = statement.getRightOp();
30+
31+
if (!leftOp.equals(val)) {
32+
return Optional.empty();
33+
}
34+
35+
if (statement.containsInvokeExpr()) {
36+
DeclaredMethod declaredMethod = statement.getInvokeExpr().getDeclaredMethod();
37+
38+
if (sources.contains(declaredMethod.toMethodWrapper())) {
39+
AllocVal allocVal = new AllocVal(leftOp, statement, rightOp);
40+
41+
return Optional.of(allocVal);
42+
}
43+
}
44+
45+
return Optional.empty();
46+
}
47+
}
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
package boomerang.example.analysis;
2+
3+
import boomerang.BackwardQuery;
4+
import boomerang.Boomerang;
5+
import boomerang.ForwardQuery;
6+
import boomerang.Query;
7+
import boomerang.options.BoomerangOptions;
8+
import boomerang.results.BackwardBoomerangResults;
9+
import boomerang.scope.AllocVal;
10+
import boomerang.scope.FrameworkScope;
11+
import boomerang.utils.MethodWrapper;
12+
import org.slf4j.Logger;
13+
import org.slf4j.LoggerFactory;
14+
import wpds.impl.NoWeight;
15+
16+
import java.util.Collection;
17+
import java.util.HashSet;
18+
19+
public class TaintAnalysis {
20+
21+
private static final Logger logger = LoggerFactory.getLogger(TaintAnalysis.class.getSimpleName());
22+
23+
private final FrameworkScope frameworkScope;
24+
private final Collection<MethodWrapper> sources;
25+
private final Collection<MethodWrapper> sinks;
26+
27+
public TaintAnalysis(
28+
FrameworkScope frameworkScope,
29+
Collection<MethodWrapper> sources,
30+
Collection<MethodWrapper> sinks) {
31+
this.frameworkScope = frameworkScope;
32+
this.sources = sources;
33+
this.sinks = sinks;
34+
}
35+
36+
public void run() {
37+
TaintAnalysisScope scope = new TaintAnalysisScope(frameworkScope, sinks);
38+
Collection<Query> queries = scope.computeSeeds();
39+
40+
logger.info("Found " + queries.size() + " sink(s)");
41+
42+
for (Query query : queries) {
43+
if (!(query instanceof BackwardQuery)) {
44+
continue;
45+
}
46+
47+
Collection<AllocVal> allocSites = solveQuery((BackwardQuery) query);
48+
logger.info(
49+
"Found {} leaks for variable {} @ {}:",
50+
allocSites.size(),
51+
query.var().getVariableName(),
52+
query.cfgEdge().getTarget());
53+
54+
for (AllocVal allocVal : allocSites) {
55+
logger.info(
56+
"\tSource: "
57+
+ allocVal.getAllocVal()
58+
+ " @ "
59+
+ allocVal.getAllocStatement()
60+
+ " @ line "
61+
+ allocVal.getAllocStatement().getLineNumber());
62+
}
63+
}
64+
65+
if (queries.isEmpty()) {
66+
logger.info("Did not find any leaks!");
67+
}
68+
}
69+
70+
public Collection<AllocVal> solveQuery(BackwardQuery query) {
71+
TaintAllocationSite allocationSite = new TaintAllocationSite(sources);
72+
BoomerangOptions options =
73+
BoomerangOptions.builder().withAllocationSite(allocationSite).build();
74+
75+
Boomerang boomerang = new Boomerang(frameworkScope, options);
76+
BackwardBoomerangResults<NoWeight> results = boomerang.solve(query);
77+
78+
Collection<AllocVal> allocSites = new HashSet<>();
79+
for (ForwardQuery result : results.getAllocationSites().keySet()) {
80+
allocSites.add(result.getAllocVal());
81+
}
82+
83+
return allocSites;
84+
}
85+
}
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
package boomerang.example.analysis;
2+
3+
import boomerang.BackwardQuery;
4+
import boomerang.Query;
5+
import boomerang.scope.AnalysisScope;
6+
import boomerang.scope.ControlFlowGraph;
7+
import boomerang.scope.DeclaredMethod;
8+
import boomerang.scope.FrameworkScope;
9+
import boomerang.scope.InvokeExpr;
10+
import boomerang.scope.Statement;
11+
import boomerang.scope.Val;
12+
import boomerang.utils.MethodWrapper;
13+
14+
import java.util.Collection;
15+
import java.util.Collections;
16+
17+
public class TaintAnalysisScope extends AnalysisScope {
18+
19+
private final Collection<MethodWrapper> sinks;
20+
21+
public TaintAnalysisScope(FrameworkScope frameworkScope, Collection<MethodWrapper> sinks) {
22+
super(frameworkScope);
23+
24+
this.sinks = sinks;
25+
}
26+
27+
@Override
28+
protected Collection<? extends Query> generate(ControlFlowGraph.Edge edge) {
29+
Statement statement = edge.getTarget();
30+
31+
if (statement.containsInvokeExpr()) {
32+
InvokeExpr invokeExpr = statement.getInvokeExpr();
33+
DeclaredMethod declaredMethod = invokeExpr.getDeclaredMethod();
34+
35+
if (sinks.contains(declaredMethod.toMethodWrapper())) {
36+
Val arg = invokeExpr.getArg(0);
37+
38+
BackwardQuery query = BackwardQuery.make(edge, arg);
39+
return Collections.singleton(query);
40+
}
41+
}
42+
43+
return Collections.emptySet();
44+
}
45+
}
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
package boomerang.example.analysis;
2+
3+
import boomerang.scope.DataFlowScope;
4+
import boomerang.scope.DeclaredMethod;
5+
import boomerang.scope.Method;
6+
import boomerang.scope.WrappedClass;
7+
import boomerang.utils.MethodWrapper;
8+
9+
import java.util.Collection;
10+
11+
public class TaintDataFlowScope implements DataFlowScope {
12+
13+
private final Collection<MethodWrapper> sources;
14+
private final Collection<MethodWrapper> sinks;
15+
16+
public TaintDataFlowScope(Collection<MethodWrapper> sources, Collection<MethodWrapper> sinks) {
17+
this.sources = sources;
18+
this.sinks = sinks;
19+
}
20+
21+
@Override
22+
public boolean isExcluded(DeclaredMethod declaredMethod) {
23+
WrappedClass declaringClass = declaredMethod.getDeclaringClass();
24+
25+
if (declaringClass.isPhantom()) {
26+
return true;
27+
}
28+
29+
return isClassSourceOrSink(declaringClass);
30+
}
31+
32+
@Override
33+
public boolean isExcluded(Method method) {
34+
WrappedClass declaringClass = method.getDeclaringClass();
35+
36+
if (declaringClass.isPhantom()) {
37+
return true;
38+
}
39+
40+
return isClassSourceOrSink(declaringClass);
41+
}
42+
43+
private boolean isClassSourceOrSink(WrappedClass declaringClass) {
44+
for (MethodWrapper wrapper : sources) {
45+
if (wrapper.getDeclaringClass().equals(declaringClass.getFullyQualifiedName())) {
46+
return true;
47+
}
48+
}
49+
50+
for (MethodWrapper wrapper : sinks) {
51+
if (wrapper.getDeclaringClass().equals(declaringClass.getFullyQualifiedName())) {
52+
return true;
53+
}
54+
}
55+
56+
return false;
57+
}
58+
}
928 Bytes
Binary file not shown.
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import taints.SinkClass;
2+
import taints.SourceClass;
3+
4+
/**
5+
* Simple example for a branched dataflow where there are multiple branches that taint the variable.
6+
* Hence, Boomerang reports both positions for the taint.
7+
*/
8+
public class BranchingMultipleExample {
9+
10+
private static boolean staticallyUnknown() {
11+
return Math.random() > 0.5;
12+
}
13+
14+
public static void main(String[] args) {
15+
// Taint position 1
16+
String s = SourceClass.source();
17+
18+
if (staticallyUnknown()) {
19+
// Taint position 2
20+
s = SourceClass.source();
21+
}
22+
23+
SinkClass.sink(s);
24+
}
25+
}
935 Bytes
Binary file not shown.

0 commit comments

Comments
 (0)