@@ -19,6 +19,20 @@ private module LDAP {
1919 * See https://www.python-ldap.org/en/python-ldap-3.3.0/index.html
2020 */
2121 private module LDAP2 {
22+ /** Gets a reference to the `ldap` module. */
23+ API:: Node ldap ( ) { result = API:: moduleImport ( "ldap" ) }
24+
25+ /** Returns a `ldap` module instance */
26+ API:: Node ldapInitialize ( ) { result = ldap ( ) .getMember ( "initialize" ) }
27+
28+ /** Gets a reference to a `ldap` operation. */
29+ private DataFlow:: TypeTrackingNode ldapOperation ( DataFlow:: TypeTracker t ) {
30+ t .start ( ) and
31+ result .( DataFlow:: AttrRead ) .getObject ( ) .getALocalSource ( ) = ldapInitialize ( ) .getACall ( )
32+ or
33+ exists ( DataFlow:: TypeTracker t2 | result = ldapOperation ( t2 ) .track ( t2 , t ) )
34+ }
35+
2236 /**
2337 * List of `ldap` methods used to execute a query.
2438 *
@@ -30,32 +44,61 @@ private module LDAP {
3044 }
3145 }
3246
47+ /** Gets a reference to a `ldap` operation. */
48+ private DataFlow:: Node ldapOperation ( ) {
49+ ldapOperation ( DataFlow:: TypeTracker:: end ( ) ) .flowsTo ( result )
50+ }
51+
52+ /** Gets a reference to a `ldap` query. */
53+ private DataFlow:: Node ldapQuery ( ) {
54+ result = ldapOperation ( ) and
55+ result .( DataFlow:: AttrRead ) .getAttributeName ( ) instanceof LDAP2QueryMethods
56+ }
57+
3358 /**
3459 * A class to find `ldap` methods executing a query.
3560 *
3661 * See `LDAP2QueryMethods`
3762 */
3863 private class LDAP2Query extends DataFlow:: CallCfgNode , LDAPQuery:: Range {
39- DataFlow:: Node ldapQuery ;
40-
41- LDAP2Query ( ) {
42- exists ( DataFlow:: AttrRead searchMethod |
43- this .getFunction ( ) = searchMethod and
44- API:: moduleImport ( "ldap" ) .getMember ( "initialize" ) .getACall ( ) =
45- searchMethod .getObject ( ) .getALocalSource ( ) and
46- searchMethod .getAttributeName ( ) instanceof LDAP2QueryMethods and
47- (
48- ldapQuery = this .getArg ( 0 )
49- or
50- (
51- ldapQuery = this .getArg ( 2 ) or
52- ldapQuery = this .getArgByName ( "filterstr" )
53- )
54- )
55- )
64+ LDAP2Query ( ) { this .getFunction ( ) = ldapQuery ( ) }
65+
66+ override DataFlow:: Node getQuery ( ) {
67+ result in [ this .getArg ( 0 ) , this .getArg ( 2 ) , this .getArgByName ( "filterstr" ) ]
68+ }
69+ }
70+
71+ /**
72+ * List of `ldap` methods used for binding.
73+ *
74+ * See https://www.python-ldap.org/en/python-ldap-3.3.0/reference/ldap.html#functions
75+ */
76+ private class LDAP2BindMethods extends string {
77+ LDAP2BindMethods ( ) {
78+ this in [
79+ "bind" , "bind_s" , "simple_bind" , "simple_bind_s" , "sasl_interactive_bind_s" ,
80+ "sasl_non_interactive_bind_s" , "sasl_external_bind_s" , "sasl_gssapi_bind_s"
81+ ]
5682 }
83+ }
5784
58- override DataFlow:: Node getQuery ( ) { result = ldapQuery }
85+ /** Gets a reference to a `ldap` bind. */
86+ private DataFlow:: Node ldapBind ( ) {
87+ result = ldapOperation ( ) and
88+ result .( DataFlow:: AttrRead ) .getAttributeName ( ) instanceof LDAP2BindMethods
89+ }
90+
91+ /**
92+ * A class to find `ldap` methods binding a connection.
93+ *
94+ * See `LDAP2BindMethods`
95+ */
96+ private class LDAP2Bind extends DataFlow:: CallCfgNode , LDAPBind:: Range {
97+ LDAP2Bind ( ) { this .getFunction ( ) = ldapBind ( ) }
98+
99+ override DataFlow:: Node getPassword ( ) {
100+ result in [ this .getArg ( 1 ) , this .getArgByName ( "cred" ) ]
101+ }
59102 }
60103
61104 /**
@@ -64,9 +107,7 @@ private module LDAP {
64107 * See https://github.com/python-ldap/python-ldap/blob/7ce471e238cdd9a4dd8d17baccd1c9e05e6f894a/Lib/ldap/dn.py#L17
65108 */
66109 private class LDAP2EscapeDNCall extends DataFlow:: CallCfgNode , LDAPEscape:: Range {
67- LDAP2EscapeDNCall ( ) {
68- this = API:: moduleImport ( "ldap" ) .getMember ( "dn" ) .getMember ( "escape_dn_chars" ) .getACall ( )
69- }
110+ LDAP2EscapeDNCall ( ) { this = ldap ( ) .getMember ( "dn" ) .getMember ( "escape_dn_chars" ) .getACall ( ) }
70111
71112 override DataFlow:: Node getAnInput ( ) { result = this .getArg ( 0 ) }
72113 }
@@ -78,8 +119,7 @@ private module LDAP {
78119 */
79120 private class LDAP2EscapeFilterCall extends DataFlow:: CallCfgNode , LDAPEscape:: Range {
80121 LDAP2EscapeFilterCall ( ) {
81- this =
82- API:: moduleImport ( "ldap" ) .getMember ( "filter" ) .getMember ( "escape_filter_chars" ) .getACall ( )
122+ this = ldap ( ) .getMember ( "filter" ) .getMember ( "escape_filter_chars" ) .getACall ( )
83123 }
84124
85125 override DataFlow:: Node getAnInput ( ) { result = this .getArg ( 0 ) }
@@ -92,26 +132,40 @@ private module LDAP {
92132 * See https://pypi.org/project/ldap3/
93133 */
94134 private module LDAP3 {
135+ /** Gets a reference to the `ldap3` module. */
136+ API:: Node ldap3 ( ) { result = API:: moduleImport ( "ldap3" ) }
137+
138+ /** Gets a reference to the `ldap3` `utils` module. */
139+ API:: Node ldap3Utils ( ) { result = ldap3 ( ) .getMember ( "utils" ) }
140+
141+ /** Returns a `ldap3` module `Server` instance */
142+ API:: Node ldap3Server ( ) { result = ldap3 ( ) .getMember ( "Server" ) }
143+
144+ /** Returns a `ldap3` module `Connection` instance */
145+ API:: Node ldap3Connection ( ) { result = ldap3 ( ) .getMember ( "Connection" ) }
146+
95147 /**
96148 * A class to find `ldap3` methods executing a query.
97149 */
98150 private class LDAP3Query extends DataFlow:: CallCfgNode , LDAPQuery:: Range {
99- DataFlow:: Node ldapQuery ;
100-
101151 LDAP3Query ( ) {
102- exists ( DataFlow:: AttrRead searchMethod |
103- this .getFunction ( ) = searchMethod and
104- API:: moduleImport ( "ldap3" ) .getMember ( "Connection" ) .getACall ( ) =
105- searchMethod .getObject ( ) .getALocalSource ( ) and
106- searchMethod .getAttributeName ( ) = "search" and
107- (
108- ldapQuery = this .getArg ( 0 ) or
109- ldapQuery = this .getArg ( 1 )
110- )
111- )
152+ this .getFunction ( ) .( DataFlow:: AttrRead ) .getObject ( ) .getALocalSource ( ) =
153+ ldap3Connection ( ) .getACall ( ) and
154+ this .getFunction ( ) .( DataFlow:: AttrRead ) .getAttributeName ( ) = "search"
112155 }
113156
114- override DataFlow:: Node getQuery ( ) { result = ldapQuery }
157+ override DataFlow:: Node getQuery ( ) { result in [ this .getArg ( 0 ) , this .getArg ( 1 ) ] }
158+ }
159+
160+ /**
161+ * A class to find `ldap3` methods binding a connection.
162+ */
163+ class LDAP3Bind extends DataFlow:: CallCfgNode , LDAPBind:: Range {
164+ LDAP3Bind ( ) { this = ldap3Connection ( ) .getACall ( ) }
165+
166+ override DataFlow:: Node getPassword ( ) {
167+ result in [ this .getArg ( 2 ) , this .getArgByName ( "password" ) ]
168+ }
115169 }
116170
117171 /**
@@ -120,14 +174,7 @@ private module LDAP {
120174 * See https://github.com/cannatag/ldap3/blob/4d33166f0869b929f59c6e6825a1b9505eb99967/ldap3/utils/dn.py#L390
121175 */
122176 private class LDAP3EscapeDNCall extends DataFlow:: CallCfgNode , LDAPEscape:: Range {
123- LDAP3EscapeDNCall ( ) {
124- this =
125- API:: moduleImport ( "ldap3" )
126- .getMember ( "utils" )
127- .getMember ( "dn" )
128- .getMember ( "escape_rdn" )
129- .getACall ( )
130- }
177+ LDAP3EscapeDNCall ( ) { this = ldap3Utils ( ) .getMember ( "dn" ) .getMember ( "escape_rdn" ) .getACall ( ) }
131178
132179 override DataFlow:: Node getAnInput ( ) { result = this .getArg ( 0 ) }
133180 }
@@ -139,12 +186,7 @@ private module LDAP {
139186 */
140187 private class LDAP3EscapeFilterCall extends DataFlow:: CallCfgNode , LDAPEscape:: Range {
141188 LDAP3EscapeFilterCall ( ) {
142- this =
143- API:: moduleImport ( "ldap3" )
144- .getMember ( "utils" )
145- .getMember ( "conv" )
146- .getMember ( "escape_filter_chars" )
147- .getACall ( )
189+ this = ldap3Utils ( ) .getMember ( "conv" ) .getMember ( "escape_filter_chars" ) .getACall ( )
148190 }
149191
150192 override DataFlow:: Node getAnInput ( ) { result = this .getArg ( 0 ) }
0 commit comments