C#: Add Dapper support to SQL injection queries

This commit is contained in:
Tamas Vajk
2021-04-06 15:42:24 +02:00
parent 98001c494f
commit ffcb345916
4 changed files with 117 additions and 0 deletions

View File

@@ -0,0 +1,42 @@
/**
* Classes for modelling Dapper.
*/
import csharp
private import semmle.code.csharp.frameworks.system.Data
/** Definitions relating to the `Dapper` package. */
module Dapper {
/** The namespace `Dapper`. */
class DapperNamespace extends Namespace {
DapperNamespace() { this.hasQualifiedName("Dapper") }
}
/** A class in `Dapper`. */
class DapperClass extends Class {
DapperClass() { this.getParent() instanceof DapperNamespace }
}
/** A struct in `Dapper`. */
class DapperStruct extends Struct {
DapperStruct() { this.getParent() instanceof DapperNamespace }
}
/** The `Dapper.SqlMapper` class. */
class SqlMapperClass extends DapperClass {
SqlMapperClass() { this.hasName("SqlMapper") }
/** Gets a DB query method. */
ExtensionMethod getAQueryMethod() {
result = this.getAMethod() and
result.getName().regexpMatch("Query.*|Execute.*") and
result.getExtendedType() instanceof SystemDataIDbConnectionInterface and
result.isPublic()
}
}
/** The `Dapper.CommandDefinition` struct. */
class CommandDefinitionStruct extends DapperStruct {
CommandDefinitionStruct() { this.hasName("CommandDefinition") }
}
}

View File

@@ -5,6 +5,8 @@ private import semmle.code.csharp.frameworks.system.Data
private import semmle.code.csharp.frameworks.system.data.SqlClient
private import semmle.code.csharp.frameworks.EntityFramework
private import semmle.code.csharp.frameworks.NHibernate
private import semmle.code.csharp.frameworks.Dapper
private import semmle.code.csharp.dataflow.DataFlow3
/** An expression containing a SQL command. */
abstract class SqlExpr extends Expr {
@@ -83,3 +85,37 @@ class MicrosoftSqlHelperMethodCallSqlExpr extends SqlExpr, MethodCall {
)
}
}
/** A `Dapper.SqlMapper` method that is taking a SQL string argument. */
class DapperSqlMethodCallSqlExpr extends SqlExpr, MethodCall {
DapperSqlMethodCallSqlExpr() {
this.getTarget() = any(Dapper::SqlMapperClass c).getAQueryMethod()
}
override Expr getSql() { result = this.getArgumentForName("sql") }
}
/** A `Dapper.CommandDefinition` creation that is taking a SQL string argument and is passed to a `Dapper.SqlMapper` method. */
class DapperCommandDefinitionMethodCallSqlExpr extends SqlExpr, ObjectCreation {
DapperCommandDefinitionMethodCallSqlExpr() {
this.getObjectType() instanceof Dapper::CommandDefinitionStruct and
exists(Conf c | c.hasFlow(DataFlow::exprNode(this), _))
}
override Expr getSql() { result = this.getArgumentForName("commandText") }
}
private class Conf extends DataFlow3::Configuration {
Conf() { this = "DapperCommandDefinitionFlowConfig" }
override predicate isSource(DataFlow::Node node) {
node.asExpr().(ObjectCreation).getObjectType() instanceof Dapper::CommandDefinitionStruct
}
override predicate isSink(DataFlow::Node node) {
exists(MethodCall mc |
mc.getTarget() = any(Dapper::SqlMapperClass c).getAQueryMethod() and
node.asExpr() = mc.getArgumentForName("command")
)
}
}