File tree Expand file tree Collapse file tree 16 files changed +215
-63
lines changed
src/experimental/semmle/python
test/experimental/query-tests/Security/CWE-074-SecondaryServerCmdInjection Expand file tree Collapse file tree 16 files changed +215
-63
lines changed Original file line number Diff line number Diff line change @@ -15,6 +15,13 @@ private import semmle.python.dataflow.new.TaintTracking
1515private import experimental.semmle.python.Frameworks
1616private import semmle.python.Concepts
1717
18+ /**
19+ * A data-flow node that responsible for a command that can be executed on a secondary remote system,
20+ *
21+ * Extend this class to model new APIs.
22+ */
23+ abstract class SecondaryCommandInjection extends DataFlow:: Node { }
24+
1825/** Provides classes for modeling copying file related APIs. */
1926module CopyFile {
2027 /**
Original file line number Diff line number Diff line change 22 * Helper file that imports all framework modeling.
33 */
44
5+ private import experimental.semmle.python.frameworks.AsyncSsh
56private import experimental.semmle.python.frameworks.Stdlib
67private import experimental.semmle.python.frameworks.Flask
78private import experimental.semmle.python.frameworks.Django
89private import experimental.semmle.python.frameworks.Werkzeug
910private import experimental.semmle.python.frameworks.LDAP
11+ private import experimental.semmle.python.frameworks.Netmiko
12+ private import experimental.semmle.python.frameworks.Paramiko
13+ private import experimental.semmle.python.frameworks.Scrapli
1014private import experimental.semmle.python.frameworks.JWT
1115private import experimental.semmle.python.frameworks.Csv
1216private import experimental.semmle.python.libraries.PyJWT
@@ -15,5 +19,6 @@ private import experimental.semmle.python.libraries.Authlib
1519private import experimental.semmle.python.libraries.PythonJose
1620private import experimental.semmle.python.frameworks.CopyFile
1721private import experimental.semmle.python.frameworks.Sendgrid
22+ private import experimental.semmle.python.frameworks.Ssh2
1823private import experimental.semmle.python.libraries.FlaskMail
1924private import experimental.semmle.python.libraries.SmtpLib
Original file line number Diff line number Diff line change @@ -8,7 +8,7 @@ private import semmle.python.dataflow.new.DataFlow
88private import semmle.python.dataflow.new.RemoteFlowSources
99private import semmle.python.Concepts
1010private import semmle.python.ApiGraphs
11- import experimental.semmle.python.security.SecondaryServerCmdInjectionCustomizations
11+ import experimental.semmle.python.Concepts
1212
1313/**
1414 * Provides models for the `asyncssh` PyPI package.
@@ -23,7 +23,7 @@ private module Asyncssh {
2323 /**
2424 * A `run` method responsible for executing commands on remote secondary servers.
2525 */
26- class AsyncsshRun extends SecondaryCommandInjection:: Sink {
26+ class AsyncsshRun extends SecondaryCommandInjection {
2727 AsyncsshRun ( ) {
2828 this =
2929 asyncssh ( )
Original file line number Diff line number Diff line change @@ -8,7 +8,7 @@ private import semmle.python.dataflow.new.DataFlow
88private import semmle.python.dataflow.new.RemoteFlowSources
99private import semmle.python.Concepts
1010private import semmle.python.ApiGraphs
11- import experimental.semmle.python.security.SecondaryServerCmdInjectionCustomizations
11+ import experimental.semmle.python.Concepts
1212
1313/**
1414 * Provides models for the `netmiko` PyPI package.
@@ -30,7 +30,7 @@ private module Netmiko {
3030 /**
3131 * The `send_*` methods responsible for executing commands on remote secondary servers.
3232 */
33- class NetmikoSendCommand extends SecondaryCommandInjection:: Sink {
33+ class NetmikoSendCommand extends SecondaryCommandInjection {
3434 NetmikoSendCommand ( ) {
3535 this =
3636 netmikoConnectHandler ( )
Original file line number Diff line number Diff line change @@ -8,7 +8,7 @@ private import semmle.python.dataflow.new.DataFlow
88private import semmle.python.dataflow.new.RemoteFlowSources
99private import semmle.python.Concepts
1010private import semmle.python.ApiGraphs
11- import experimental.semmle.python.security.SecondaryServerCmdInjectionCustomizations
11+ import experimental.semmle.python.Concepts
1212
1313/**
1414 * Provides models for the `paramiko` PyPI package.
@@ -28,7 +28,7 @@ private module Paramiko {
2828 /**
2929 * The `exec_command` of `paramiko.SSHClient` class execute command on ssh target server
3030 */
31- class ParamikoExecCommand extends SecondaryCommandInjection:: Sink {
31+ class ParamikoExecCommand extends SecondaryCommandInjection {
3232 ParamikoExecCommand ( ) {
3333 this =
3434 paramikoClient ( ) .getMember ( "exec_command" ) .getACall ( ) .getParameter ( 0 , "command" ) .asSink ( )
Original file line number Diff line number Diff line change @@ -8,7 +8,7 @@ private import semmle.python.dataflow.new.DataFlow
88private import semmle.python.dataflow.new.RemoteFlowSources
99private import semmle.python.Concepts
1010private import semmle.python.ApiGraphs
11- import experimental.semmle.python.security.SecondaryServerCmdInjectionCustomizations
11+ import experimental.semmle.python.Concepts
1212
1313/**
1414 * Provides models for the `scrapli` PyPI package.
@@ -33,7 +33,7 @@ private module Scrapli {
3333 /**
3434 * A `send_command` method responsible for executing commands on remote secondary servers.
3535 */
36- class ScrapliSendCommand extends SecondaryCommandInjection:: Sink {
36+ class ScrapliSendCommand extends SecondaryCommandInjection {
3737 ScrapliSendCommand ( ) {
3838 this =
3939 scrapliCore ( )
Original file line number Diff line number Diff line change @@ -8,7 +8,7 @@ private import semmle.python.dataflow.new.DataFlow
88private import semmle.python.dataflow.new.RemoteFlowSources
99private import semmle.python.Concepts
1010private import semmle.python.ApiGraphs
11- import experimental.semmle.python.security.SecondaryServerCmdInjectionCustomizations
11+ import experimental.semmle.python.Concepts
1212
1313/**
1414 * Provides models for the `ssh2-python` PyPI package.
@@ -20,20 +20,17 @@ private module Ssh2 {
2020 */
2121 private API:: Node ssh2 ( ) { result = API:: moduleImport ( "ssh2" ) }
2222
23- /**
24- * Gets `ssh2.session` package.
25- */
26- private API::Node ssh2Session() { result = API::moduleImport("ssh2").getMember("session") }
27-
2823 /**
2924 * Gets `ssh2.session.Session` return value.
3025 */
31- private API::Node ssh2Session() { result = ssh2Session().getMember("Session").getReturn() }
26+ private API:: Node ssh2Session ( ) {
27+ result = ssh2 ( ) .getMember ( "session" ) .getMember ( "Session" ) .getReturn ( )
28+ }
3229
3330 /**
3431 * A `execute` method responsible for executing commands on remote secondary servers.
3532 */
36- class Ssh2Execute extends SecondaryCommandInjection::Sink {
33+ class Ssh2Execute extends SecondaryCommandInjection {
3734 Ssh2Execute ( ) {
3835 this =
3936 ssh2Session ( )
Original file line number Diff line number Diff line change @@ -4,12 +4,12 @@ import semmle.python.dataflow.new.RemoteFlowSources
44import semmle.python.ApiGraphs
55import semmle.python.dataflow.new.internal.DataFlowPublic
66import codeql.util.Unit
7- import SecondaryServerCmdInjectionCustomizations
7+ import experimental.semmle.python.Concepts
88
99module SecondaryCommandInjectionConfig implements DataFlow:: ConfigSig {
10- predicate isSource ( DataFlow:: Node source ) { source instanceof SecondaryCommandInjection :: Source }
10+ predicate isSource ( DataFlow:: Node source ) { source instanceof RemoteFlowSource }
1111
12- predicate isSink ( DataFlow:: Node sink ) { sink instanceof SecondaryCommandInjection:: Sink }
12+ predicate isSink ( DataFlow:: Node sink ) { sink instanceof SecondaryCommandInjection }
1313}
1414
1515/** Global taint-tracking for detecting "paramiko command injection" vulnerabilities. */
Load Diff This file was deleted.
Original file line number Diff line number Diff line change 1+ #!/usr/bin/env python
2+
3+ from fastapi import FastAPI
4+ import asyncssh
5+
6+
7+ app = FastAPI ()
8+ sock = socket .socket (socket .AF_INET , socket .SOCK_STREAM )
9+ sock .connect (("host" , "port" ))
10+ session = Session ()
11+ session .handshake (sock )
12+ session .userauth_password ("user" , "password" )
13+
14+ @app .get ("/bad1" )
15+ async def bad1 (cmd : str ):
16+ async with asyncssh .connect ('localhost' ) as conn :
17+ result = await conn .run (cmd , check = True ) # $ result=BAD getSecondaryCommand=cmd
18+ print (result .stdout , end = '' )
19+ return {"success" : "Dangerous" }
You can’t perform that action at this time.
0 commit comments