mirror of
https://github.com/github/codeql.git
synced 2025-12-22 11:46:32 +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.dataflow.FlowSources
|
||||||
import semmle.code.java.security.QueryInjection
|
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 {
|
private class QueryInjectionFlowConfig extends TaintTracking::Configuration {
|
||||||
QueryInjectionFlowConfig() { this = "SqlInjectionLib::QueryInjectionFlowConfig" }
|
QueryInjectionFlowConfig() { this = "SqlInjectionLib::QueryInjectionFlowConfig" }
|
||||||
|
|
||||||
@@ -16,6 +32,10 @@ private class QueryInjectionFlowConfig extends TaintTracking::Configuration {
|
|||||||
node.getType() instanceof BoxedType or
|
node.getType() instanceof BoxedType or
|
||||||
node.getType() instanceof NumberType
|
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)
|
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) {
|
override predicate isSanitizer(DataFlow::Node node) {
|
||||||
node.getType() instanceof PrimitiveType or node.getType() instanceof BoxedType
|
node.getType() instanceof PrimitiveType or node.getType() instanceof BoxedType
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override predicate isAdditionalTaintStep(DataFlow::Node node1, DataFlow::Node node2) {
|
||||||
|
mongoJsonStep(node1, node2)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
from
|
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
|
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: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:42:57:42:62 | query2 |
|
||||||
| Test.java:29:30:29:42 | args : String[] | Test.java:50:62:50:67 | query3 |
|
| 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: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[] |
|
| Test.java:218:14:218:17 | args : String[] | Test.java:183:33:183:45 | args : String[] |
|
||||||
nodes
|
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:29:30:29:42 | args : String[] | semmle.label | args : String[] |
|
||||||
| Test.java:36:47:36:52 | query1 | semmle.label | query1 |
|
| Test.java:36:47:36:52 | query1 | semmle.label | query1 |
|
||||||
| Test.java:42:57:42:62 | query2 | semmle.label | query2 |
|
| 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:214:11:214:14 | args : String[] | semmle.label | args : String[] |
|
||||||
| Test.java:218:14:218:17 | args : String[] | semmle.label | args : String[] |
|
| Test.java:218:14:218:17 | args : String[] | semmle.label | args : String[] |
|
||||||
#select
|
#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: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: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 |
|
| 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