Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/add cpg tests #1009

Merged
merged 8 commits into from
Aug 13, 2024
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
175 changes: 175 additions & 0 deletions docs/codepropertygraphs.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,175 @@
Code Property Graphs (CPGs) are a representation of program code that combines different code representations into a
single graph. This unified representation includes abstract syntax trees (ASTs), control flow graphs (CFGs), control
dependence graphs (CDGs), and data dependence graphs (DDGs). CPGs enable comprehensive analysis, which makes them a
powerful tool for detecting vulnerabilities and understanding code structure. For further details, refer to
this [thesis](#).

## Usage Example

In this example, we will demonstrate how to create a CPG for a vulnerable Java method and use it to identify a potential
vulnerability.

### Vulnerable Java Code

Let's assume we have the following vulnerable Java code in a file named `VulnerableClass.java`:

=== "Java"

```java
public class VulnerableClass {
public void vulnerableMethod(String userInput) {
if (userInput.equals("admin")) {
System.out.println("Welcome, admin!");
}
}
}
```

### Step 1: Obtain a SootMethod

First, we assume we have a `SootMethod` for the `vulnerableMethod`. For instructions on how to obtain a `SootMethod`,
refer to [Retrieving a Method](getting-started.md#retrieving-a-method).

### Step 2: Create the CPG

We can create the CPG subgraphs using the creators.

=== "AST"

```java
public class AstExample {

public static void main(String[] args) {
// Assuming `sootMethod` is obtained from the setup step
SootMethod vulnerableMethod = getVulnerableMethod();

// Create the AST subgraph
AstCreator astCreator = new AstCreator();
PropertyGraph astGraph = astCreator.createGraph(vulnerableMethod);

// Print the DOT representation of the AST
System.out.println(astGraph.toDotGraph());
}
}
```

=== "CFG"

```java
public class CfgExample {

public static void main(String[] args) {
// Assuming `sootMethod` is obtained from the setup step
SootMethod vulnerableMethod = getVulnerableMethod();

// Create the CFG subgraph
CfgCreator cfgCreator = new CfgCreator();
PropertyGraph cfgGraph = cfgCreator.createGraph(vulnerableMethod);

// Print the DOT representation of the CFG
System.out.println(cfgGraph.toDotGraph());
}
}
```

=== "CDG"

```java
public class CdgExample {

public static void main(String[] args) {
// Assuming `sootMethod` is obtained from the setup step
SootMethod vulnerableMethod = getVulnerableMethod();

// Create the CDG subgraph
CdgCreator cdgCreator = new CdgCreator();
PropertyGraph cdgGraph = cdgCreator.createGraph(vulnerableMethod);

// Print the DOT representation of the CDG
System.out.println(cdgGraph.toDotGraph());
}
}
```

=== "DDG"

```java
public class DdgExample {

public static void main(String[] args) {
// Assuming `sootMethod` is obtained from the setup step
SootMethod vulnerableMethod = getVulnerableMethod();

// Create the DDG subgraph
DdgCreator ddgCreator = new DdgCreator();
PropertyGraph ddgGraph = ddgCreator.createGraph(vulnerableMethod);

// Print the DOT representation of the DDG
System.out.println(ddgGraph.toDotGraph());
}
}
```

We can create the combined CPG graph using the `CpgCreator`.

=== "CPG"

```java
public class CpgExample {

public static void main(String[] args) {
// Assuming `sootMethod` is obtained from the setup step
SootMethod vulnerableMethod = getVulnerableMethod();

AstCreator astCreator = new AstCreator();
CfgCreator cfgCreator = new CfgCreator();
CdgCreator cdgCreator = new CdgCreator();
DdgCreator ddgCreator = new DdgCreator();

// Create the combined CPG
CpgCreator cpgCreator = new CpgCreator(astCreator, cfgCreator, cdgCreator, ddgCreator);
PropertyGraph cpg = cpgCreator.createCpg(vulnerableMethod);

// Print the DOT representation of the CPG
System.out.println(cpg.toDotGraph());
}
}
```

### Step 3: Analyzing the CPG

With the CPG created, you can now analyze it for vulnerabilities. For example, you can check for potential injection
vulnerabilities by analyzing data flow dependencies.

=== "SootUp"

```java
public class VulnerabilityAnalysis {

public static void main(String[] args) {
// Assuming `cpg` is the PropertyGraph created in the previous step
for (DdgEdge edge : cpg.getEdges(DdgEdge.class)) {
StmtGraphNode source = (StmtGraphNode) edge.getSource();
StmtGraphNode destination = (StmtGraphNode) edge.getDestination();

if (isPotentiallyVulnerable(source, destination)) {
System.out.println("Potential vulnerability found between: ");
System.out.println("Source: " + source.getStmt());
System.out.println("Destination: " + destination.getStmt());
}
}
}

private static boolean isPotentiallyVulnerable(StmtGraphNode source, StmtGraphNode destination) {
// Implement your vulnerability detection logic here
return source.getStmt().toString().contains("userInput") &&
destination.getStmt() instanceof JInvokeStmt &&
destination.getStmt().toString().contains("println");
}
}
```

In this example, we check for data flow dependencies between the `userInput` variable and any `println`
calls, which could indicate a potential injection vulnerability.

Similarly, we can define our own queries to detect specific patterns that identify common vulnerabilities.
6 changes: 6 additions & 0 deletions docs/installation.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,11 @@ Add the following dependencies to your ```pom.xml``` / ```build.gradle```.
<artifactId>sootup.qilin</artifactId>
<version>{{ git_latest_release }}</version>
</dependency>
<dependency>
<groupId>org.soot-oss</groupId>
<artifactId>sootup.codepropertygraph</artifactId>
<version>{{ git_latest_release }}</version>
</dependency>
</dependencies>
```

Expand All @@ -73,6 +78,7 @@ Add the following dependencies to your ```pom.xml``` / ```build.gradle```.
compile "org.soot-oss:sootup.callgraph:{{ git_latest_release }}"
compile "org.soot-oss:sootup.analysis:{{ git_latest_release }}"
compile "org.soot-oss:sootup.qilin:{{ git_latest_release }}"
compile "org.soot-oss:sootup.codepropertygraph:{{ git_latest_release }}"
```

## Build from Source
Expand Down
1 change: 1 addition & 0 deletions mkdocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ nav:
- TypeHierarchy: typehierarchy.md
- Callgraphs: callgraphs.md
- BuiltIn Analyses: builtin-analyses.md
- Code Property Graphs: codepropertygraphs.md

- How to..:
- Write a Dataflow analysis: write_analyses.md
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
import sootup.codepropertygraph.propertygraph.edges.*;
import sootup.codepropertygraph.propertygraph.nodes.*;
import sootup.core.jimple.basic.Immediate;
import sootup.core.jimple.basic.Value;
import sootup.core.jimple.common.expr.AbstractConditionExpr;
import sootup.core.jimple.common.expr.AbstractInvokeExpr;
import sootup.core.jimple.common.expr.Expr;
Expand Down Expand Up @@ -72,7 +73,7 @@ public void caseAssignStmt(@Nonnull JAssignStmt stmt) {
* @param operand the operand
* @return the property graph node
*/
private PropertyGraphNode createOperandNode(Object operand) {
private PropertyGraphNode createOperandNode(Value operand) {
if (operand instanceof Immediate) {
return new ImmediateGraphNode((Immediate) operand);
} else if (operand instanceof Ref) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,12 +64,12 @@ public static String convert(PropertyGraph graph) {
String.format("\t\"%s\" [label=\"%s\", fillcolor=\"%s\"];\n", nodeId, label, color));
}

// Sort edges by a consistent property
// Sort edges by the IDs of the source and destination nodes
List<PropertyGraphEdge> sortedEdges =
graph.getEdges().stream()
.sorted(
Comparator.comparing((PropertyGraphEdge edge) -> edge.getSource().toString())
.thenComparing(edge -> edge.getDestination().toString())
Comparator.comparing((PropertyGraphEdge edge) -> nodeIds.get(edge.getSource()))
.thenComparing(edge -> nodeIds.get(edge.getDestination()))
.thenComparing(PropertyGraphEdge::getLabel))
.collect(Collectors.toList());

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,13 +49,7 @@ protected Optional<? extends SootMethod> getMinimalTestSuiteMethod(
return minimalTsView.getMethod(methodSignature);
}

protected Optional<? extends SootMethod> getTestResourcesMethod(
String className, String methodName) {
ClassType appClass = testResourcesView.getIdentifierFactory().getClassType(className);
MethodSignature methodSignature =
testResourcesView
.getIdentifierFactory()
.getMethodSignature(appClass, methodName, "void", Collections.emptyList());
protected Optional<? extends SootMethod> getTestResourcesMethod(MethodSignature methodSignature) {
return testResourcesView.getMethod(methodSignature);
}
}
Loading
Loading