|
11 | 11 |
|
12 | 12 | // Determine precision above |
13 | 13 | import python |
14 | | -import semmle.python.dataflow.new.RemoteFlowSources |
15 | | -import semmle.python.dataflow.new.DataFlow |
16 | | -import semmle.python.dataflow.new.TaintTracking |
17 | | -import semmle.python.dataflow.new.internal.TaintTrackingPublic |
| 14 | +import experimental.semmle.python.security.injection.LDAPInjection |
18 | 15 | import DataFlow::PathGraph |
19 | 16 |
|
20 | | -class InitializeSink extends DataFlow::Node { |
21 | | - InitializeSink() { |
22 | | - exists(SsaVariable initVar, CallNode searchCall | |
23 | | - // get variable whose value equals a call to ldap.initialize |
24 | | - initVar.getDefinition().getImmediateDominator() = Value::named("ldap.initialize").getACall() and |
25 | | - // get the Call in which the previous variable is used |
26 | | - initVar.getAUse().getNode() = searchCall.getNode().getFunc().(Attribute).getObject() and |
27 | | - // restrict that call's attribute (something.this) to match %search% |
28 | | - searchCall.getNode().getFunc().(Attribute).getName().matches("%search%") and |
29 | | - // set the third argument (search_filter) as sink |
30 | | - this.asExpr() = searchCall.getArg(2).getNode() |
31 | | - // set the first argument (DN) as sink |
32 | | - // or this.asExpr() = searchCall.getArg(0) // Should this be set? |
33 | | - ) |
34 | | - } |
35 | | -} |
36 | | - |
37 | | -class ConnectionSink extends DataFlow::Node { |
38 | | - ConnectionSink() { |
39 | | - exists(SsaVariable connVar, CallNode searchCall | |
40 | | - // get variable whose value equals a call to ldap.initialize |
41 | | - connVar.getDefinition().getImmediateDominator() = Value::named("ldap3.Connection").getACall() and |
42 | | - // get the Call in which the previous variable is used |
43 | | - connVar.getAUse().getNode() = searchCall.getNode().getFunc().(Attribute).getObject() and |
44 | | - // restrict that call's attribute (something.this) to match %search% |
45 | | - searchCall.getNode().getFunc().(Attribute).getName().matches("%search%") and |
46 | | - // set the second argument (search_filter) as sink |
47 | | - this.asExpr() = searchCall.getArg(1).getNode() |
48 | | - // set the first argument (DN) as sink |
49 | | - // or this.asExpr() = searchCall.getArg(0) // Should this be set? |
50 | | - ) |
51 | | - } |
52 | | -} |
53 | | - |
54 | | -class EscapeSanitizer extends DataFlow::Node { |
55 | | - EscapeSanitizer() { |
56 | | - exists(Call c | |
57 | | - ( |
58 | | - // avoid flow through any %escape% function |
59 | | - c.getFunc().(Attribute).getName().matches("%escape%") or // something.%escape%() |
60 | | - c.getFunc().(Name).getId().matches("%escape%") // %escape%() |
61 | | - ) and |
62 | | - this.asExpr() = c |
63 | | - ) |
64 | | - } |
65 | | -} |
66 | | - |
67 | | -class LDAPInjectionSink extends DataFlow::Node { |
68 | | - LDAPInjectionSink() { |
69 | | - this instanceof InitializeSink or |
70 | | - this instanceof ConnectionSink |
71 | | - } |
72 | | -} |
73 | | - |
74 | | -class LDAPInjectionFlowConfig extends TaintTracking::Configuration { |
75 | | - LDAPInjectionFlowConfig() { this = "LDAPInjectionFlowConfig" } |
76 | | - |
77 | | - override predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource } |
78 | | - |
79 | | - override predicate isSink(DataFlow::Node sink) { sink instanceof LDAPInjectionSink } |
80 | | - |
81 | | - override predicate isSanitizer(DataFlow::Node sanitizer) { sanitizer instanceof EscapeSanitizer } |
82 | | -} |
83 | | - |
84 | | -from LDAPInjectionFlowConfig config, DataFlow::PathNode source, DataFlow::PathNode sink |
85 | | -where config.hasFlowPath(source, sink) |
86 | | -select sink.getNode(), source, sink, "$@ LDAP query executes $@.", sink.getNode(), "This", |
87 | | - source.getNode(), "a user-provided value" |
| 17 | +from |
| 18 | + LDAPInjectionFlowConfig config, DataFlow::PathNode source, DataFlow::PathNode sink, |
| 19 | + LDAPQuery castedSink |
| 20 | +where |
| 21 | + config.hasFlowPath(source, sink) and |
| 22 | + castedSink = sink.getNode() |
| 23 | +select sink.getNode(), source, sink, "$@ LDAP query executes $@ as a $@ probably leaking $@.", |
| 24 | + sink.getNode(), "This", source.getNode(), "a user-provided value", castedSink.getLDAPNode(), |
| 25 | + castedSink.getLDAPPart(), castedSink.getAttrList(), "this attribute(s)" |
0 commit comments