Skip to content

Commit cc61e61

Browse files
authored
Merge pull request #3542 from porcupineyhairs/mongoJava
Java : add MongoDB injection sinks
2 parents 311e62f + 4418259 commit cc61e61

15 files changed

Lines changed: 206 additions & 0 deletions

File tree

java/ql/src/Security/CWE/CWE-089/SqlInjectionLib.qll

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,22 @@ import java
44
import semmle.code.java.dataflow.FlowSources
55
import semmle.code.java.security.QueryInjection
66

7+
/** A sink for MongoDB injection vulnerabilities. */
8+
class MongoDbInjectionSink extends QueryInjectionSink {
9+
MongoDbInjectionSink() {
10+
exists(MethodAccess call |
11+
call.getMethod().getDeclaringType().hasQualifiedName("com.mongodb", "BasicDBObject") and
12+
call.getMethod().hasName("parse") and
13+
this.asExpr() = call.getArgument(0)
14+
)
15+
or
16+
exists(CastExpr c |
17+
c.getExpr() = this.asExpr() and
18+
c.getTypeExpr().getType().(RefType).hasQualifiedName("com.mongodb", "DBObject")
19+
)
20+
}
21+
}
22+
723
private class QueryInjectionFlowConfig extends TaintTracking::Configuration {
824
QueryInjectionFlowConfig() { this = "SqlInjectionLib::QueryInjectionFlowConfig" }
925

@@ -16,6 +32,10 @@ private class QueryInjectionFlowConfig extends TaintTracking::Configuration {
1632
node.getType() instanceof BoxedType or
1733
node.getType() instanceof NumberType
1834
}
35+
36+
override predicate isAdditionalTaintStep(DataFlow::Node node1, DataFlow::Node node2) {
37+
mongoJsonStep(node1, node2)
38+
}
1939
}
2040

2141
/**
@@ -27,3 +47,12 @@ predicate queryTaintedBy(
2747
) {
2848
exists(QueryInjectionFlowConfig conf | conf.hasFlowPath(source, sink) and sink.getNode() = query)
2949
}
50+
51+
predicate mongoJsonStep(DataFlow::Node node1, DataFlow::Node node2) {
52+
exists(MethodAccess ma |
53+
ma.getMethod().getDeclaringType().hasQualifiedName("com.mongodb.util", "JSON") and
54+
ma.getMethod().hasName("parse") and
55+
ma.getArgument(0) = node1.asExpr() and
56+
ma = node2.asExpr()
57+
)
58+
}

java/ql/src/Security/CWE/CWE-089/SqlTaintedLocal.ql

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,10 @@ class LocalUserInputToQueryInjectionFlowConfig extends TaintTracking::Configurat
2525
override predicate isSanitizer(DataFlow::Node node) {
2626
node.getType() instanceof PrimitiveType or node.getType() instanceof BoxedType
2727
}
28+
29+
override predicate isAdditionalTaintStep(DataFlow::Node node1, DataFlow::Node node2) {
30+
mongoJsonStep(node1, node2)
31+
}
2832
}
2933

3034
from
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import com.mongodb.MongoClient;
2+
import com.mongodb.DBObject;
3+
import com.mongodb.util.*;
4+
import com.mongodb.ServerAddress;
5+
import com.mongodb.DBCollection;
6+
import com.mongodb.DBCursor;
7+
import com.mongodb.*;
8+
9+
public class Mongo {
10+
public static void main(String[] args) {
11+
MongoClient mongoClient = new MongoClient(new ServerAddress("localhost", 27017));
12+
DB db = mongoClient.getDB("mydb");
13+
DBCollection collection = db.getCollection("test");
14+
15+
String name = args[1];
16+
String stringQuery = "{ 'name' : '" + name + "'}";
17+
DBObject databaseQuery = (DBObject) JSON.parse(stringQuery);
18+
DBCursor result = collection.find(databaseQuery);
19+
20+
String json = args[1];
21+
BasicDBObject bdb = BasicDBObject.parse(json);
22+
DBCursor result2 = collection.find(bdb);
23+
24+
}
25+
}

java/ql/test/query-tests/security/CWE-089/semmle/examples/SqlTaintedLocal.expected

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
edges
2+
| Mongo.java:10:29:10:41 | args : String[] | Mongo.java:17:45:17:67 | parse(...) |
3+
| Mongo.java:10:29:10:41 | args : String[] | Mongo.java:21:49:21:52 | json |
24
| Test.java:29:30:29:42 | args : String[] | Test.java:36:47:36:52 | query1 |
35
| Test.java:29:30:29:42 | args : String[] | Test.java:42:57:42:62 | query2 |
46
| Test.java:29:30:29:42 | args : String[] | Test.java:50:62:50:67 | query3 |
@@ -11,6 +13,9 @@ edges
1113
| Test.java:214:11:214:14 | args : String[] | Test.java:29:30:29:42 | args : String[] |
1214
| Test.java:218:14:218:17 | args : String[] | Test.java:183:33:183:45 | args : String[] |
1315
nodes
16+
| Mongo.java:10:29:10:41 | args : String[] | semmle.label | args : String[] |
17+
| Mongo.java:17:45:17:67 | parse(...) | semmle.label | parse(...) |
18+
| Mongo.java:21:49:21:52 | json | semmle.label | json |
1419
| Test.java:29:30:29:42 | args : String[] | semmle.label | args : String[] |
1520
| Test.java:36:47:36:52 | query1 | semmle.label | query1 |
1621
| Test.java:42:57:42:62 | query2 | semmle.label | query2 |
@@ -24,6 +29,8 @@ nodes
2429
| Test.java:214:11:214:14 | args : String[] | semmle.label | args : String[] |
2530
| Test.java:218:14:218:17 | args : String[] | semmle.label | args : String[] |
2631
#select
32+
| Mongo.java:17:45:17:67 | parse(...) | Mongo.java:10:29:10:41 | args : String[] | Mongo.java:17:45:17:67 | parse(...) | Query might include code from $@. | Mongo.java:10:29:10:41 | args | this user input |
33+
| Mongo.java:21:49:21:52 | json | Mongo.java:10:29:10:41 | args : String[] | Mongo.java:21:49:21:52 | json | Query might include code from $@. | Mongo.java:10:29:10:41 | args | this user input |
2734
| Test.java:36:47:36:52 | query1 | Test.java:213:26:213:38 | args : String[] | Test.java:36:47:36:52 | query1 | Query might include code from $@. | Test.java:213:26:213:38 | args | this user input |
2835
| Test.java:42:57:42:62 | query2 | Test.java:213:26:213:38 | args : String[] | Test.java:42:57:42:62 | query2 | Query might include code from $@. | Test.java:213:26:213:38 | args | this user input |
2936
| Test.java:50:62:50:67 | query3 | Test.java:213:26:213:38 | args : String[] | Test.java:50:62:50:67 | query3 | Query might include code from $@. | Test.java:213:26:213:38 | args | this user input |
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
//semmle-extractor-options: --javac-args -cp ${testdir}/../../../../../stubs/mongodbClient
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
package com.mongodb;
2+
3+
public class BasicDBObject implements com.mongodb.DBObject {
4+
public static com.mongodb.BasicDBObject parse(java.lang.String json) {
5+
return null;
6+
}
7+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
package com.mongodb;
2+
3+
public class DB {
4+
5+
public com.mongodb.DBCollection getCollection(java.lang.String name) {
6+
return null;
7+
}
8+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
package com.mongodb;
2+
3+
public class DBCollection {
4+
public com.mongodb.DBCursor find(com.mongodb.DBObject query) {
5+
return null;
6+
}
7+
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
package com.mongodb;
2+
3+
public class DBCursor {
4+
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
package com.mongodb;
2+
3+
public abstract interface DBObject {
4+
}

0 commit comments

Comments
 (0)