mirror of
https://github.com/github/codeql.git
synced 2025-12-24 04:36:35 +01:00
Merge pull request #3542 from porcupineyhairs/mongoJava
Java : add MongoDB injection sinks
This commit is contained in:
@@ -4,6 +4,22 @@ import java
|
||||
import semmle.code.java.dataflow.FlowSources
|
||||
import semmle.code.java.security.QueryInjection
|
||||
|
||||
/** A sink for MongoDB injection vulnerabilities. */
|
||||
class MongoDbInjectionSink extends QueryInjectionSink {
|
||||
MongoDbInjectionSink() {
|
||||
exists(MethodAccess call |
|
||||
call.getMethod().getDeclaringType().hasQualifiedName("com.mongodb", "BasicDBObject") and
|
||||
call.getMethod().hasName("parse") and
|
||||
this.asExpr() = call.getArgument(0)
|
||||
)
|
||||
or
|
||||
exists(CastExpr c |
|
||||
c.getExpr() = this.asExpr() and
|
||||
c.getTypeExpr().getType().(RefType).hasQualifiedName("com.mongodb", "DBObject")
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private class QueryInjectionFlowConfig extends TaintTracking::Configuration {
|
||||
QueryInjectionFlowConfig() { this = "SqlInjectionLib::QueryInjectionFlowConfig" }
|
||||
|
||||
@@ -16,6 +32,10 @@ private class QueryInjectionFlowConfig extends TaintTracking::Configuration {
|
||||
node.getType() instanceof BoxedType or
|
||||
node.getType() instanceof NumberType
|
||||
}
|
||||
|
||||
override predicate isAdditionalTaintStep(DataFlow::Node node1, DataFlow::Node node2) {
|
||||
mongoJsonStep(node1, node2)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -27,3 +47,12 @@ predicate queryTaintedBy(
|
||||
) {
|
||||
exists(QueryInjectionFlowConfig conf | conf.hasFlowPath(source, sink) and sink.getNode() = query)
|
||||
}
|
||||
|
||||
predicate mongoJsonStep(DataFlow::Node node1, DataFlow::Node node2) {
|
||||
exists(MethodAccess ma |
|
||||
ma.getMethod().getDeclaringType().hasQualifiedName("com.mongodb.util", "JSON") and
|
||||
ma.getMethod().hasName("parse") and
|
||||
ma.getArgument(0) = node1.asExpr() and
|
||||
ma = node2.asExpr()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -25,6 +25,10 @@ class LocalUserInputToQueryInjectionFlowConfig extends TaintTracking::Configurat
|
||||
override predicate isSanitizer(DataFlow::Node node) {
|
||||
node.getType() instanceof PrimitiveType or node.getType() instanceof BoxedType
|
||||
}
|
||||
|
||||
override predicate isAdditionalTaintStep(DataFlow::Node node1, DataFlow::Node node2) {
|
||||
mongoJsonStep(node1, node2)
|
||||
}
|
||||
}
|
||||
|
||||
from
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
import com.mongodb.MongoClient;
|
||||
import com.mongodb.DBObject;
|
||||
import com.mongodb.util.*;
|
||||
import com.mongodb.ServerAddress;
|
||||
import com.mongodb.DBCollection;
|
||||
import com.mongodb.DBCursor;
|
||||
import com.mongodb.*;
|
||||
|
||||
public class Mongo {
|
||||
public static void main(String[] args) {
|
||||
MongoClient mongoClient = new MongoClient(new ServerAddress("localhost", 27017));
|
||||
DB db = mongoClient.getDB("mydb");
|
||||
DBCollection collection = db.getCollection("test");
|
||||
|
||||
String name = args[1];
|
||||
String stringQuery = "{ 'name' : '" + name + "'}";
|
||||
DBObject databaseQuery = (DBObject) JSON.parse(stringQuery);
|
||||
DBCursor result = collection.find(databaseQuery);
|
||||
|
||||
String json = args[1];
|
||||
BasicDBObject bdb = BasicDBObject.parse(json);
|
||||
DBCursor result2 = collection.find(bdb);
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,6 @@
|
||||
edges
|
||||
| Mongo.java:10:29:10:41 | args : String[] | Mongo.java:17:45:17:67 | parse(...) |
|
||||
| Mongo.java:10:29:10:41 | args : String[] | Mongo.java:21:49:21:52 | json |
|
||||
| Test.java:29:30:29:42 | args : String[] | Test.java:36:47:36:52 | query1 |
|
||||
| Test.java:29:30:29:42 | args : String[] | Test.java:42:57:42:62 | query2 |
|
||||
| Test.java:29:30:29:42 | args : String[] | Test.java:50:62:50:67 | query3 |
|
||||
@@ -11,6 +13,9 @@ edges
|
||||
| Test.java:214:11:214:14 | args : String[] | Test.java:29:30:29:42 | args : String[] |
|
||||
| Test.java:218:14:218:17 | args : String[] | Test.java:183:33:183:45 | args : String[] |
|
||||
nodes
|
||||
| Mongo.java:10:29:10:41 | args : String[] | semmle.label | args : String[] |
|
||||
| Mongo.java:17:45:17:67 | parse(...) | semmle.label | parse(...) |
|
||||
| Mongo.java:21:49:21:52 | json | semmle.label | json |
|
||||
| Test.java:29:30:29:42 | args : String[] | semmle.label | args : String[] |
|
||||
| Test.java:36:47:36:52 | query1 | semmle.label | query1 |
|
||||
| Test.java:42:57:42:62 | query2 | semmle.label | query2 |
|
||||
@@ -24,6 +29,8 @@ nodes
|
||||
| Test.java:214:11:214:14 | args : String[] | semmle.label | args : String[] |
|
||||
| Test.java:218:14:218:17 | args : String[] | semmle.label | args : String[] |
|
||||
#select
|
||||
| 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 |
|
||||
| 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 |
|
||||
| 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 |
|
||||
| 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 |
|
||||
| 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 |
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
//semmle-extractor-options: --javac-args -cp ${testdir}/../../../../../stubs/mongodbClient
|
||||
@@ -0,0 +1,7 @@
|
||||
package com.mongodb;
|
||||
|
||||
public class BasicDBObject implements com.mongodb.DBObject {
|
||||
public static com.mongodb.BasicDBObject parse(java.lang.String json) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
8
java/ql/test/stubs/mongodbClient/com/mongodb/DB.java
Normal file
8
java/ql/test/stubs/mongodbClient/com/mongodb/DB.java
Normal file
@@ -0,0 +1,8 @@
|
||||
package com.mongodb;
|
||||
|
||||
public class DB {
|
||||
|
||||
public com.mongodb.DBCollection getCollection(java.lang.String name) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package com.mongodb;
|
||||
|
||||
public class DBCollection {
|
||||
public com.mongodb.DBCursor find(com.mongodb.DBObject query) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
package com.mongodb;
|
||||
|
||||
public class DBCursor {
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
package com.mongodb;
|
||||
|
||||
public abstract interface DBObject {
|
||||
}
|
||||
10
java/ql/test/stubs/mongodbClient/com/mongodb/Mongo.java
Normal file
10
java/ql/test/stubs/mongodbClient/com/mongodb/Mongo.java
Normal file
@@ -0,0 +1,10 @@
|
||||
|
||||
package com.mongodb;
|
||||
|
||||
public class Mongo {
|
||||
|
||||
public com.mongodb.DB getDB(java.lang.String dbName) {
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
package com.mongodb;
|
||||
|
||||
public class MongoClient extends com.mongodb.Mongo {
|
||||
public MongoClient(com.mongodb.ServerAddress addr) {
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
// Failed to get sources. Instead, stub sources have been generated by the disassembler.
|
||||
// Implementation of methods is unavailable.
|
||||
package com.mongodb;
|
||||
|
||||
public class ServerAddress implements java.io.Serializable {
|
||||
|
||||
public ServerAddress() {
|
||||
}
|
||||
|
||||
public ServerAddress(java.lang.String host) {
|
||||
}
|
||||
|
||||
public ServerAddress(java.net.InetAddress inetAddress) {
|
||||
}
|
||||
|
||||
public ServerAddress(java.net.InetAddress inetAddress, int port) {
|
||||
}
|
||||
|
||||
public ServerAddress(java.net.InetSocketAddress inetSocketAddress) {
|
||||
}
|
||||
|
||||
public ServerAddress(java.lang.String host, int port) {
|
||||
}
|
||||
|
||||
public boolean equals(java.lang.Object o) {
|
||||
return false;
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public java.lang.String getHost() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public int getPort() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public java.net.InetSocketAddress getSocketAddress() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public java.util.List<java.net.InetSocketAddress> getSocketAddresses() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public java.lang.String toString() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public static java.lang.String defaultHost() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public static int defaultPort() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public boolean sameHost(java.lang.String hostName) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
package com.mongodb.util;
|
||||
|
||||
public class JSON {
|
||||
|
||||
public static java.lang.Object parse(java.lang.String jsonString) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
22
java/ql/test/stubs/mongodbClient/org/bson/BSONObject.java
Normal file
22
java/ql/test/stubs/mongodbClient/org/bson/BSONObject.java
Normal file
@@ -0,0 +1,22 @@
|
||||
package org.bson;
|
||||
|
||||
public abstract interface BSONObject {
|
||||
|
||||
public abstract java.lang.Object put(java.lang.String arg0, java.lang.Object arg1);
|
||||
|
||||
public abstract void putAll(org.bson.BSONObject arg0);
|
||||
|
||||
public abstract void putAll(java.util.Map arg0);
|
||||
|
||||
public abstract java.lang.Object get(java.lang.String arg0);
|
||||
|
||||
public abstract java.util.Map toMap();
|
||||
|
||||
public abstract java.lang.Object removeField(java.lang.String arg0);
|
||||
|
||||
public abstract boolean containsKey(java.lang.String arg0);
|
||||
|
||||
public abstract boolean containsField(java.lang.String arg0);
|
||||
|
||||
public abstract java.util.Set<java.lang.String> keySet();
|
||||
}
|
||||
Reference in New Issue
Block a user