зеркало из https://github.com/github/codeql.git
Add LDAP Injection query (incomplete)
This commit is contained in:
Родитель
202037e925
Коммит
026d94c457
|
@ -212,8 +212,7 @@ module FileSystemWriteAccess {
|
|||
* Extend this class to refine existing API models. If you want to model new APIs,
|
||||
* extend `FileSystemPermissionModification::Range` instead.
|
||||
*/
|
||||
class FileSystemPermissionModification extends DataFlow::Node instanceof FileSystemPermissionModification::Range
|
||||
{
|
||||
class FileSystemPermissionModification extends DataFlow::Node instanceof FileSystemPermissionModification::Range {
|
||||
/**
|
||||
* Gets an argument to this permission modification that is interpreted as a
|
||||
* set of permissions.
|
||||
|
@ -469,8 +468,7 @@ module Http {
|
|||
}
|
||||
}
|
||||
|
||||
private class RequestInputAccessAsRemoteFlowSource extends RemoteFlowSource::Range instanceof RequestInputAccess
|
||||
{
|
||||
private class RequestInputAccessAsRemoteFlowSource extends RemoteFlowSource::Range instanceof RequestInputAccess {
|
||||
override string getSourceType() { result = this.(RequestInputAccess).getSourceType() }
|
||||
}
|
||||
|
||||
|
@ -959,8 +957,7 @@ module Path {
|
|||
* Extend this class to refine existing API models. If you want to model new APIs,
|
||||
* extend `CookieSecurityConfigurationSetting::Range` instead.
|
||||
*/
|
||||
class CookieSecurityConfigurationSetting extends DataFlow::Node instanceof CookieSecurityConfigurationSetting::Range
|
||||
{
|
||||
class CookieSecurityConfigurationSetting extends DataFlow::Node instanceof CookieSecurityConfigurationSetting::Range {
|
||||
/**
|
||||
* Gets a description of how this cookie setting may weaken application security.
|
||||
* This predicate has no results if the setting is considered to be safe.
|
||||
|
@ -1040,8 +1037,7 @@ module Cryptography {
|
|||
* Extend this class to refine existing API models. If you want to model new APIs,
|
||||
* extend `CryptographicOperation::Range` instead.
|
||||
*/
|
||||
class CryptographicOperation extends SC::CryptographicOperation instanceof CryptographicOperation::Range
|
||||
{
|
||||
class CryptographicOperation extends SC::CryptographicOperation instanceof CryptographicOperation::Range {
|
||||
/** DEPRECATED: Use `getAlgorithm().isWeak() or getBlockMode().isWeak()` instead */
|
||||
deprecated predicate isWeak() { super.isWeak() }
|
||||
}
|
||||
|
@ -1129,3 +1125,69 @@ module TemplateRendering {
|
|||
abstract DataFlow::Node getTemplate();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A data-flow node that constructs a LDAP query.
|
||||
*
|
||||
* Often, it is worthy of an alert if an LDAP query is constructed such that
|
||||
* executing it would be a security risk.
|
||||
*
|
||||
* If it is important that the query is executed, use `LdapExecution`.
|
||||
*
|
||||
* Extend this class to refine existing API models. If you want to model new APIs,
|
||||
* extend `LdapConstruction::Range` instead.
|
||||
*/
|
||||
class LdapConstruction extends DataFlow::Node instanceof LdapConstruction::Range {
|
||||
/** Gets the argument that specifies the query to be constructed. */
|
||||
DataFlow::Node getQuery() { result = super.getQuery() }
|
||||
}
|
||||
|
||||
/** Provides a class for modeling new LDAP query construction APIs. */
|
||||
module LdapConstruction {
|
||||
/**
|
||||
* A data-flow node that constructs a LDAP query.
|
||||
*
|
||||
* Often, it is worthy of an alert if an LDAP query is constructed such that
|
||||
* executing it would be a security risk.
|
||||
*
|
||||
* If it is important that the query is executed, use `LdapExecution`.
|
||||
*
|
||||
* Extend this class to model new APIs. If you want to refine existing API models,
|
||||
* extend `LdapConstruction` instead.
|
||||
*/
|
||||
abstract class Range extends DataFlow::Node {
|
||||
/** Gets the argument that specifies the query to be constructed. */
|
||||
abstract DataFlow::Node getQuery();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A data-flow node that executes LDAP queries.
|
||||
*
|
||||
* If the context of interest is such that merely constructing a LDAP query
|
||||
* would be valuable to report, consider using `LdapConstruction`.
|
||||
*
|
||||
* Extend this class to refine existing API models. If you want to model new APIs,
|
||||
* extend `LdapExecution::Range` instead.
|
||||
*/
|
||||
class LdapExecution extends DataFlow::Node instanceof LdapExecution::Range {
|
||||
/** Gets the argument that specifies the query to be executed. */
|
||||
DataFlow::Node getQuery() { result = super.getQuery() }
|
||||
}
|
||||
|
||||
/** Provides a class for modeling new LDAP query execution APIs. */
|
||||
module LdapExecution {
|
||||
/**
|
||||
* A data-flow node that executes LDAP queries.
|
||||
*
|
||||
* If the context of interest is such that merely constructing a LDAP query
|
||||
* would be valuable to report, consider using `LdapConstruction`.
|
||||
*
|
||||
* Extend this class to model new APIs. If you want to refine existing API models,
|
||||
* extend `LdapExecution` instead.
|
||||
*/
|
||||
abstract class Range extends DataFlow::Node {
|
||||
//** Gets the argument that specifies the query to be executed. */
|
||||
abstract DataFlow::Node getQuery();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -32,3 +32,4 @@ private import codeql.ruby.frameworks.Slim
|
|||
private import codeql.ruby.frameworks.Sinatra
|
||||
private import codeql.ruby.frameworks.Twirp
|
||||
private import codeql.ruby.frameworks.Sqlite3
|
||||
private import codeql.ruby.frameworks.Ldap
|
|
@ -0,0 +1,79 @@
|
|||
/**
|
||||
* Provides modeling for `net-ldap` a ruby library for LDAP.
|
||||
*/
|
||||
|
||||
private import ruby
|
||||
private import codeql.ruby.ApiGraphs
|
||||
private import codeql.ruby.dataflow.FlowSummary
|
||||
private import codeql.ruby.Concepts
|
||||
private import codeql.ruby.CFG
|
||||
private import codeql.ruby.AST
|
||||
private import codeql.ruby.Concepts
|
||||
private import codeql.ruby.controlflow.CfgNodes
|
||||
private import codeql.ruby.DataFlow
|
||||
private import codeql.ruby.dataflow.internal.DataFlowDispatch
|
||||
private import codeql.ruby.dataflow.internal.DataFlowPrivate
|
||||
private import codeql.ruby.ApiGraphs
|
||||
private import codeql.ruby.frameworks.Stdlib
|
||||
private import codeql.ruby.frameworks.Core
|
||||
|
||||
/**
|
||||
* Provides modeling for `net-ldap` a ruby library for LDAP.
|
||||
*/
|
||||
module NetLdap {
|
||||
/**
|
||||
* Flow summary for `Net::LDAP.new`. This method establishes a connection to a LDAP server.
|
||||
*/
|
||||
private class LdapSummary extends SummarizedCallable {
|
||||
LdapSummary() { this = "Net::LDAP.new" }
|
||||
|
||||
override MethodCall getACall() { result = any(LdapConnection l).asExpr().getExpr() }
|
||||
|
||||
override predicate propagatesFlowExt(string input, string output, boolean preservesValue) {
|
||||
input = "Argument[0]" and output = "ReturnValue" and preservesValue = false
|
||||
}
|
||||
}
|
||||
|
||||
private class LdapConnection extends DataFlow::CallNode {
|
||||
LdapConnection() {
|
||||
this = API::getTopLevelMember("Net").getMember("LDAP").getAnInstantiation() or
|
||||
this = API::getTopLevelMember("Net").getMember("LDAP").getAMethodCall(["open"])
|
||||
}
|
||||
}
|
||||
|
||||
/** A call to ` Net::LDAP::Filter.eq`, considered as a LDAP construction. */
|
||||
private class NetLdapConstruction extends LdapConstruction::Range, DataFlow::CallNode {
|
||||
DataFlow::Node query;
|
||||
|
||||
NetLdapConstruction() {
|
||||
this =
|
||||
API::getTopLevelMember("Net").getMember("LDAP").getMember("Filter").getAMethodCall(["eq"]) and
|
||||
query = this.getArgument([0, 1])
|
||||
}
|
||||
|
||||
override DataFlow::Node getQuery() { result = query }
|
||||
}
|
||||
|
||||
/** A call considered as a LDAP execution. */
|
||||
private class NetLdapExecution extends LdapExecution::Range, DataFlow::CallNode {
|
||||
DataFlow::Node query;
|
||||
|
||||
NetLdapExecution() {
|
||||
// detecta cuando la query es una string pej
|
||||
// ldap.search(base: "ou=#{name},dc=example,dc=com"
|
||||
exists(LdapConnection ldapConnection |
|
||||
this = ldapConnection.getAMethodCall("search") and
|
||||
query = this.getKeywordArgument(_)
|
||||
)
|
||||
or
|
||||
// ignora esta parte
|
||||
exists(LdapConnection ldapConnection, NetLdapConstruction ldapConstruction |
|
||||
this = ldapConnection.getAMethodCall("search") and
|
||||
ldapConstruction = this.getKeywordArgument(_) and
|
||||
query = ldapConstruction
|
||||
)
|
||||
}
|
||||
|
||||
override DataFlow::Node getQuery() { result = query }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,64 @@
|
|||
/**
|
||||
* Provides default sources, sinks and sanitizers for detecting
|
||||
* LDAP Injections, as well as extension points for adding your own
|
||||
*/
|
||||
|
||||
private import codeql.ruby.Concepts
|
||||
private import codeql.ruby.DataFlow
|
||||
private import codeql.ruby.dataflow.BarrierGuards
|
||||
private import codeql.ruby.dataflow.RemoteFlowSources
|
||||
private import codeql.ruby.ApiGraphs
|
||||
private import codeql.ruby.dataflow.FlowSummary
|
||||
private import codeql.ruby.CFG
|
||||
|
||||
/**
|
||||
* Provides default sources, sinks and sanitizers for detecting
|
||||
* LDAP Injections, as well as extension points for adding your own
|
||||
*/
|
||||
module LdapInjection {
|
||||
/** A data flow source for LDAP Injection vulnerabilities */
|
||||
abstract class Source extends DataFlow::Node { }
|
||||
|
||||
/** A data flow sink for LDAP Injection vulnerabilities */
|
||||
abstract class Sink extends DataFlow::Node { }
|
||||
|
||||
/** A sanitizer for LDAP Injection vulnerabilities. */
|
||||
abstract class Sanitizer extends DataFlow::Node { }
|
||||
|
||||
/**
|
||||
* Additional taint steps for "LDAP Injection" vulnerabilities.
|
||||
*/
|
||||
predicate isAdditionalTaintStep(DataFlow::Node nodeFrom, DataFlow::Node nodeTo) {
|
||||
exists(API::Node n, API::Node n2 |
|
||||
n = API::getTopLevelMember("Net").getMember("LDAP").getMember("Filter")
|
||||
|
|
||||
n2 = API::getTopLevelMember("Net").getMember("LDAP") and
|
||||
nodeTo = n2.getAMethodCall(["new"]).getAMethodCall(["search"]) and
|
||||
nodeFrom = n.getAMethodCall(["eq"]).getArgument([0, 1])
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* A source of remote user input, considered as a flow source.
|
||||
*/
|
||||
private class RemoteFlowSourceAsSource extends Source, RemoteFlowSource { }
|
||||
|
||||
/**
|
||||
* An LDAP query execution considered as a flow sink.
|
||||
*/
|
||||
private class LdapExecutionAsSink extends Sink {
|
||||
LdapExecutionAsSink() { this = any(LdapExecution l).getQuery() }
|
||||
}
|
||||
|
||||
/**
|
||||
* A comparison with a constant string, considered as a sanitizer-guard.
|
||||
*/
|
||||
private class StringConstCompareAsSanitizerGuard extends Sanitizer, StringConstCompareBarrier { }
|
||||
|
||||
/**
|
||||
* An inclusion check against an array of constant strings, considered as a
|
||||
* sanitizer-guard.
|
||||
*/
|
||||
private class StringConstArrayInclusionCallAsSanitizer extends Sanitizer,
|
||||
StringConstArrayInclusionCallBarrier { }
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
/**
|
||||
* Provides default sources, sinks and sanitizers for detecting
|
||||
* LDAP Injections, as well as extension points for adding your own
|
||||
*/
|
||||
|
||||
private import codeql.ruby.DataFlow
|
||||
private import codeql.ruby.TaintTracking
|
||||
import LdapInjectionCustomizations
|
||||
import LdapInjectionCustomizations::LdapInjection
|
||||
|
||||
/**
|
||||
* A taint-tracking configuration for detecting LDAP Injections vulnerabilities.
|
||||
*/
|
||||
class Configuration extends TaintTracking::Configuration {
|
||||
Configuration() { this = "LdapInjection" }
|
||||
|
||||
override predicate isSource(DataFlow::Node source) { source instanceof Source }
|
||||
|
||||
override predicate isSink(DataFlow::Node source) { source instanceof Sink }
|
||||
|
||||
override predicate isSanitizer(DataFlow::Node node) { node instanceof Sanitizer }
|
||||
|
||||
override predicate isAdditionalTaintStep(DataFlow::Node node1, DataFlow::Node node2) {
|
||||
LdapInjection::isAdditionalTaintStep(node1, node2)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
/**
|
||||
* @name LDAP Injection
|
||||
* @description Building an LDAP query from user-controlled sources is vulnerable to insertion of
|
||||
* malicious LDAP code by the user.
|
||||
* @kind path-problem
|
||||
* @problem.severity error
|
||||
* @security-severity 9.8
|
||||
* @precision high
|
||||
* @id rb/ldap-injection
|
||||
* @tags security
|
||||
* external/cwe/cwe-090
|
||||
*/
|
||||
|
||||
import codeql.ruby.DataFlow
|
||||
import codeql.ruby.security.LdapInjectionQuery
|
||||
import DataFlow::PathGraph
|
||||
|
||||
from Configuration config, DataFlow::PathNode source, DataFlow::PathNode sink
|
||||
where config.hasFlowPath(source, sink)
|
||||
select sink.getNode(), source, sink, "This LDAP query depends on a $@.", source.getNode(),
|
||||
"user-provided value"
|
Загрузка…
Ссылка в новой задаче