refactoring and renamings in the ldap model

This commit is contained in:
Erik Krogh Kristensen
2021-09-30 13:56:41 +02:00
parent bcf4626fd0
commit d4de5e3248
5 changed files with 73 additions and 109 deletions

View File

@@ -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

View 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 }
}
}

View File

@@ -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 }
}
}

View File

@@ -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()
}
}

View File

@@ -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()
)