Rework LDAP framework modeling

This commit is contained in:
jorgectf
2021-06-17 17:44:08 +02:00
parent 13cfcec968
commit 5704ac36db

View File

@@ -19,6 +19,20 @@ private module LDAP {
* See https://www.python-ldap.org/en/python-ldap-3.3.0/index.html
*/
private module LDAP2 {
/** Gets a reference to the `ldap` module. */
API::Node ldap() { result = API::moduleImport("ldap") }
/** Returns a `ldap` module instance */
API::Node ldapInitialize() { result = ldap().getMember("initialize") }
/** Gets a reference to a `ldap` operation. */
private DataFlow::LocalSourceNode ldapOperation(DataFlow::TypeTracker t) {
t.start() and
result.(DataFlow::AttrRead).getObject().getALocalSource() = ldapInitialize().getACall()
or
exists(DataFlow::TypeTracker t2 | result = ldapOperation(t2).track(t2, t))
}
/**
* List of `ldap` methods used to execute a query.
*
@@ -30,32 +44,45 @@ private module LDAP {
}
}
/** Gets a reference to a `ldap` operation. */
private DataFlow::Node ldapOperation() {
ldapOperation(DataFlow::TypeTracker::end()).flowsTo(result)
}
/** Gets a reference to a `ldap` query. */
private DataFlow::Node ldapQuery() {
result = ldapOperation() and
result.(DataFlow::AttrRead).getAttributeName() instanceof LDAP2QueryMethods
}
/**
* A class to find `ldap` methods executing a query.
*
* See `LDAP2QueryMethods`
*/
private class LDAP2Query extends DataFlow::CallCfgNode, LDAPQuery::Range {
DataFlow::Node ldapQuery;
LDAP2Query() { this.getFunction() = ldapQuery() }
LDAP2Query() {
exists(DataFlow::AttrRead searchMethod |
this.getFunction() = searchMethod and
API::moduleImport("ldap").getMember("initialize").getACall() =
searchMethod.getObject().getALocalSource() and
searchMethod.getAttributeName() instanceof LDAP2QueryMethods and
(
ldapQuery = this.getArg(0)
or
(
ldapQuery = this.getArg(2) or
ldapQuery = this.getArgByName("filterstr")
)
)
)
override DataFlow::Node getQuery() {
result in [this.getArg(0), [this.getArg(2), this.getArgByName("filterstr")]]
}
}
override DataFlow::Node getQuery() { result = ldapQuery }
/** Gets a reference to a `ldap` bind. */
private DataFlow::Node ldapBind() {
result = ldapOperation() and
result.(DataFlow::AttrRead).getAttributeName().matches("%bind%")
}
/**
* A class to find `ldap` methods binding a connection.
*
* See `LDAP2QueryMethods`
*/
private class LDAP2Bind extends DataFlow::CallCfgNode, LDAPBind::Range {
LDAP2Bind() { this.getFunction() = ldapBind() }
override DataFlow::Node getPassword() { result = this.getArg(1) }
}
/**
@@ -64,9 +91,7 @@ private module LDAP {
* See https://github.com/python-ldap/python-ldap/blob/7ce471e238cdd9a4dd8d17baccd1c9e05e6f894a/Lib/ldap/dn.py#L17
*/
private class LDAP2EscapeDNCall extends DataFlow::CallCfgNode, LDAPEscape::Range {
LDAP2EscapeDNCall() {
this = API::moduleImport("ldap").getMember("dn").getMember("escape_dn_chars").getACall()
}
LDAP2EscapeDNCall() { this = ldap().getMember("dn").getMember("escape_dn_chars").getACall() }
override DataFlow::Node getAnInput() { result = this.getArg(0) }
}
@@ -78,8 +103,7 @@ private module LDAP {
*/
private class LDAP2EscapeFilterCall extends DataFlow::CallCfgNode, LDAPEscape::Range {
LDAP2EscapeFilterCall() {
this =
API::moduleImport("ldap").getMember("filter").getMember("escape_filter_chars").getACall()
this = ldap().getMember("filter").getMember("escape_filter_chars").getACall()
}
override DataFlow::Node getAnInput() { result = this.getArg(0) }
@@ -92,26 +116,38 @@ private module LDAP {
* See https://pypi.org/project/ldap3/
*/
private module LDAP3 {
/** Gets a reference to the `ldap3` module. */
API::Node ldap3() { result = API::moduleImport("ldap3") }
/** Gets a reference to the `ldap3` `utils` module. */
API::Node ldap3Utils() { result = ldap3().getMember("utils") }
/** Returns a `ldap3` module `Server` instance */
API::Node ldap3Server() { result = ldap3().getMember("Server") }
/** Returns a `ldap3` module `Connection` instance */
API::Node ldap3Connection() { result = ldap3().getMember("Connection") }
/**
* A class to find `ldap3` methods executing a query.
*/
private class LDAP3Query extends DataFlow::CallCfgNode, LDAPQuery::Range {
DataFlow::Node ldapQuery;
LDAP3Query() {
exists(DataFlow::AttrRead searchMethod |
this.getFunction() = searchMethod and
API::moduleImport("ldap3").getMember("Connection").getACall() =
searchMethod.getObject().getALocalSource() and
searchMethod.getAttributeName() = "search" and
(
ldapQuery = this.getArg(0) or
ldapQuery = this.getArg(1)
)
)
this.getFunction().(DataFlow::AttrRead).getObject().getALocalSource() =
ldap3Connection().getACall() and
this.getFunction().(DataFlow::AttrRead).getAttributeName() = "search"
}
override DataFlow::Node getQuery() { result = ldapQuery }
override DataFlow::Node getQuery() { result in [this.getArg(0), this.getArg(1)] }
}
/**
* A class to find `ldap3` methods binding a connection.
*/
class LDAP3Bind extends DataFlow::CallCfgNode, LDAPBind::Range {
LDAP3Bind() { this = ldap3Connection().getACall() }
override DataFlow::Node getPassword() { result = this.getArgByName("password") }
}
/**
@@ -120,14 +156,7 @@ private module LDAP {
* See https://github.com/cannatag/ldap3/blob/4d33166f0869b929f59c6e6825a1b9505eb99967/ldap3/utils/dn.py#L390
*/
private class LDAP3EscapeDNCall extends DataFlow::CallCfgNode, LDAPEscape::Range {
LDAP3EscapeDNCall() {
this =
API::moduleImport("ldap3")
.getMember("utils")
.getMember("dn")
.getMember("escape_rdn")
.getACall()
}
LDAP3EscapeDNCall() { this = ldap3Utils().getMember("dn").getMember("escape_rdn").getACall() }
override DataFlow::Node getAnInput() { result = this.getArg(0) }
}
@@ -139,12 +168,7 @@ private module LDAP {
*/
private class LDAP3EscapeFilterCall extends DataFlow::CallCfgNode, LDAPEscape::Range {
LDAP3EscapeFilterCall() {
this =
API::moduleImport("ldap3")
.getMember("utils")
.getMember("conv")
.getMember("escape_filter_chars")
.getACall()
this = ldap3Utils().getMember("conv").getMember("escape_filter_chars").getACall()
}
override DataFlow::Node getAnInput() { result = this.getArg(0) }