mirror of
https://github.com/github/codeql.git
synced 2026-05-01 19:55:15 +02:00
refactoring and renamings in the ldap model
This commit is contained in:
@@ -99,7 +99,7 @@ import semmle.javascript.frameworks.History
|
||||
import semmle.javascript.frameworks.Immutable
|
||||
import semmle.javascript.frameworks.Knex
|
||||
import semmle.javascript.frameworks.LazyCache
|
||||
import semmle.javascript.frameworks.Ldapjs
|
||||
import semmle.javascript.frameworks.LDAPjs
|
||||
import semmle.javascript.frameworks.LodashUnderscore
|
||||
import semmle.javascript.frameworks.Logging
|
||||
import semmle.javascript.frameworks.HttpFrameworks
|
||||
|
||||
67
javascript/ql/lib/semmle/javascript/frameworks/LDAPjs.qll
Normal file
67
javascript/ql/lib/semmle/javascript/frameworks/LDAPjs.qll
Normal file
@@ -0,0 +1,67 @@
|
||||
/**
|
||||
* Provides classes for working with [LDAPjs](https://www.npmjs.com/package/ldapjs)
|
||||
*/
|
||||
|
||||
import javascript
|
||||
|
||||
module LDAPjs {
|
||||
/** Gets a reference to the ldapjs library. */
|
||||
API::Node ldapjs() { result = API::moduleImport("ldapjs") }
|
||||
|
||||
/** Gets an LDAPjs client. */
|
||||
private API::Node ldapClient() { result = ldapjs().getMember("createClient").getReturn() }
|
||||
|
||||
/** A call to a LDAPjs Client API method. */
|
||||
class ClientCall extends API::CallNode {
|
||||
string methodName;
|
||||
|
||||
ClientCall() {
|
||||
methodName = ["add", "bind", "compare", "del", "modify", "modifyDN", "search"] and
|
||||
this = ldapClient().getMember(methodName).getACall()
|
||||
}
|
||||
|
||||
string getMethodName() { result = methodName }
|
||||
}
|
||||
|
||||
/** A reference to a LDAPjs client `search` options. */
|
||||
class SearchOptions extends API::Node {
|
||||
ClientCall call;
|
||||
|
||||
SearchOptions() { call.getMethodName() = "search" and this = call.getParameter(1) }
|
||||
}
|
||||
|
||||
/** A creation of an LDAPjs filter, or object containing a filter, that doesn't sanitizes the input. */
|
||||
abstract class LDAPFilterStep extends DataFlow::Node {
|
||||
/** The input that creates (part of) an LDAPjs filter. */
|
||||
abstract DataFlow::Node getInput();
|
||||
|
||||
/** The resulting LDAPjs filter. */
|
||||
abstract DataFlow::Node getOutput();
|
||||
}
|
||||
|
||||
/** A call to the ldap utility method "parseFilter". */
|
||||
private class ParseFilter extends LDAPFilterStep, API::CallNode {
|
||||
ParseFilter() { this = ldapjs().getMember("parseFilter").getACall() }
|
||||
|
||||
override DataFlow::Node getInput() { result = this.getArgument(0) }
|
||||
|
||||
override DataFlow::Node getOutput() { result = this }
|
||||
}
|
||||
|
||||
/**
|
||||
* A filter used in call to "search" on an LDAPjs client.
|
||||
* We model that as a step from the ".filter" write to the options object itself.
|
||||
*/
|
||||
private class SearchFilter extends LDAPFilterStep {
|
||||
SearchOptions options;
|
||||
|
||||
SearchFilter() {
|
||||
options = ldapClient().getMember("search").getACall().getParameter(1) and
|
||||
this = options.getARhs()
|
||||
}
|
||||
|
||||
override DataFlow::Node getInput() { result = options.getMember("filter").getARhs() }
|
||||
|
||||
override DataFlow::Node getOutput() { result = this }
|
||||
}
|
||||
}
|
||||
@@ -1,105 +0,0 @@
|
||||
/**
|
||||
* Provides classes for working with [ldapjs](https://github.com/ldapjs/node-ldapjs) (Client only)
|
||||
*/
|
||||
|
||||
import javascript
|
||||
|
||||
module Ldapjs {
|
||||
/**
|
||||
* Gets a data flow source node for the ldapjs library.
|
||||
*/
|
||||
private API::Node ldapjs() { result = API::moduleImport("ldapjs") } // TODO: createServer, parseDN.
|
||||
|
||||
/**
|
||||
* Gets an LDAP client.
|
||||
*/
|
||||
private API::Node ldapClient() { result = ldapjs().getMember("createClient").getReturn() }
|
||||
|
||||
/**
|
||||
* A call to the ldapjs Client API methods.
|
||||
*/
|
||||
class LdapjsClientAPICall extends API::CallNode {
|
||||
string methodName;
|
||||
|
||||
LdapjsClientAPICall() {
|
||||
methodName = ["add", "bind", "compare", "del", "modify", "modifyDN", "search"] and
|
||||
this = ldapClient().getMember(methodName).getACall()
|
||||
}
|
||||
|
||||
string getMethodName() { result = methodName }
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a data flow node for the client `search` options.
|
||||
*/
|
||||
class LdapjsSearchOptions extends API::Node {
|
||||
LdapjsClientAPICall queryCall;
|
||||
|
||||
LdapjsSearchOptions() {
|
||||
queryCall.getMethodName() = "search" and
|
||||
this = queryCall.getParameter(1)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the LDAP query call that these options are used in.
|
||||
*/
|
||||
API::CallNode getQueryCall() { result = queryCall }
|
||||
}
|
||||
|
||||
/**
|
||||
* A distinguished name (DN) used in a Client API call against the LDAP server.
|
||||
*/
|
||||
class LdapjsDNArgument extends DataFlow::Node {
|
||||
LdapjsClientAPICall queryCall;
|
||||
|
||||
LdapjsDNArgument() { this = queryCall.getArgument(0) }
|
||||
|
||||
/**
|
||||
* Gets the LDAP query call that this DN is used in.
|
||||
*/
|
||||
API::CallNode getQueryCall() { result = queryCall }
|
||||
}
|
||||
|
||||
/**
|
||||
* A creation of an Ldap filter that doesn't sanitizes the input.
|
||||
*/
|
||||
abstract class LdapFilter extends DataFlow::Node {
|
||||
/**
|
||||
* The input that creates (part of) an Ldap filter.
|
||||
*/
|
||||
abstract DataFlow::Node getInput();
|
||||
|
||||
/**
|
||||
* The resulting Ldap filter.
|
||||
*/
|
||||
abstract DataFlow::Node getOutput();
|
||||
}
|
||||
|
||||
/**
|
||||
* Ldapjs parseFilter method call.
|
||||
*/
|
||||
private class LdapjsParseFilter extends LdapFilter, API::CallNode {
|
||||
LdapjsParseFilter() { this = ldapjs().getMember("parseFilter").getACall() }
|
||||
|
||||
override DataFlow::Node getInput() { result = this.getArgument(0) }
|
||||
|
||||
override DataFlow::Node getOutput() { result = this }
|
||||
}
|
||||
|
||||
/**
|
||||
* A filter used in call to "search" on an LDAP client.
|
||||
* We model that as a step from the ".filter" write to the options object itself.
|
||||
*/
|
||||
class LdapjsSearchFilter extends LdapFilter {
|
||||
LdapjsSearchOptions options;
|
||||
|
||||
LdapjsSearchFilter() {
|
||||
options = ldapClient().getMember("search").getACall().getParameter(1) and
|
||||
this = options.getARhs()
|
||||
}
|
||||
|
||||
override DataFlow::Node getInput() { result = options.getMember("filter").getARhs() }
|
||||
|
||||
override DataFlow::Node getOutput() { result = this }
|
||||
}
|
||||
}
|
||||
@@ -47,9 +47,11 @@ module SqlInjection {
|
||||
*/
|
||||
class LdapJSSink extends Sink {
|
||||
LdapJSSink() {
|
||||
this instanceof Ldapjs::LdapjsDNArgument
|
||||
// A distinguished name (DN) used in a call to the client API.
|
||||
this = any(LDAPjs::ClientCall call).getArgument(0)
|
||||
or
|
||||
this = any(Ldapjs::LdapjsSearchOptions opt).getARhs()
|
||||
// A search options object, which contains a filter and a baseDN.
|
||||
this = any(LDAPjs::SearchOptions opt).getARhs()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@ class Configuration extends TaintTracking::Configuration {
|
||||
}
|
||||
|
||||
override predicate isAdditionalTaintStep(DataFlow::Node pred, DataFlow::Node succ) {
|
||||
exists(Ldapjs::LdapFilter filter |
|
||||
exists(LDAPjs::LDAPFilterStep filter |
|
||||
pred = filter.getInput() and
|
||||
succ = filter.getOutput()
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user