@@ -18,49 +18,34 @@ import semmle.python.dataflow.new.RemoteFlowSources
18
18
import semmle.python.ApiGraphs
19
19
import DataFlow:: PathGraph
20
20
21
+ private API:: Node paramikoClient ( ) {
22
+ result = API:: moduleImport ( "paramiko" ) .getMember ( "SSHClient" ) .getReturn ( )
23
+ }
24
+
21
25
class ParamikoCMDInjectionConfiguration extends TaintTracking:: Configuration {
22
26
ParamikoCMDInjectionConfiguration ( ) { this = "ParamikoCMDInjectionConfiguration" }
23
27
24
28
override predicate isSource ( DataFlow:: Node source ) { source instanceof RemoteFlowSource }
25
29
30
+ /**
31
+ * exec_command of `paramiko.SSHClient` class execute command on ssh target server
32
+ * the `paramiko.ProxyCommand` is equivalent of `ssh -o ProxyCommand="CMD"`
33
+ * and it run CMD on current system that running the ssh command
34
+ * the Sink related to proxy command is the `connect` method of `paramiko.SSHClient` class
35
+ */
26
36
override predicate isSink ( DataFlow:: Node sink ) {
27
- sink =
28
- [
29
- API:: moduleImport ( "paramiko" )
30
- .getMember ( "SSHClient" )
31
- .getReturn ( )
32
- .getMember ( "exec_command" )
33
- .getACall ( )
34
- .getArgByName ( "command" ) ,
35
- API:: moduleImport ( "paramiko" )
36
- .getMember ( "SSHClient" )
37
- .getReturn ( )
38
- .getMember ( "exec_command" )
39
- .getACall ( )
40
- .getArg ( 0 )
41
- ]
37
+ sink = paramikoClient ( ) .getMember ( "exec_command" ) .getACall ( ) .getParameter ( 0 , "command" ) .asSink ( )
42
38
or
43
- sink =
44
- [
45
- API:: moduleImport ( "paramiko" )
46
- .getMember ( "SSHClient" )
47
- .getReturn ( )
48
- .getMember ( "connect" )
49
- .getACall ( )
50
- .getArgByName ( "sock" ) ,
51
- API:: moduleImport ( "paramiko" )
52
- .getMember ( "SSHClient" )
53
- .getReturn ( )
54
- .getMember ( "connect" )
55
- .getACall ( )
56
- .getArg ( 11 )
57
- ]
39
+ sink = paramikoClient ( ) .getMember ( "connect" ) .getACall ( ) .getParameter ( 11 , "sock" ) .asSink ( )
58
40
}
59
41
42
+ /**
43
+ * this additional taint step help taint tracking to find the vulnerable `connect` method of `paramiko.SSHClient` class
44
+ */
60
45
override predicate isAdditionalTaintStep ( DataFlow:: Node nodeFrom , DataFlow:: Node nodeTo ) {
61
46
exists ( API:: CallNode call |
62
47
call = API:: moduleImport ( "paramiko" ) .getMember ( "ProxyCommand" ) .getACall ( ) and
63
- nodeFrom = [ call .getArg ( 0 ) , call . getArgByName ( "command_line" ) ] and
48
+ nodeFrom = call .getParameter ( 0 , "command_line" ) . asSink ( ) and
64
49
nodeTo = call
65
50
)
66
51
}
0 commit comments