add ssh client libraries, add SecondaryServerCmdInjectionCustomizations

This commit is contained in:
amammad
2024-02-25 12:50:12 +04:00
parent 385c3ba7ff
commit 95c9a3fc9a
7 changed files with 280 additions and 34 deletions

View File

@@ -0,0 +1,38 @@
/**
* Provides classes modeling security-relevant aspects of the `asyncssh` PyPI package.
* See https://pypi.org/project/asyncssh/.
*/
private import python
private import semmle.python.dataflow.new.DataFlow
private import semmle.python.dataflow.new.RemoteFlowSources
private import semmle.python.Concepts
private import semmle.python.ApiGraphs
import experimental.semmle.python.security.SecondaryServerCmdInjectionCustomizations
/**
* Provides models for the `asyncssh` PyPI package.
* See https://pypi.org/project/asyncssh/.
*/
private module Asyncssh {
/**
* Gets `asyncssh` package.
*/
private API::Node asyncssh() { result = API::moduleImport("asyncssh") }
/**
* A `run` method responsible for executing commands on remote secondary servers.
*/
class AsyncsshRun extends SecondaryCommandInjection::Sink {
AsyncsshRun() {
this =
asyncssh()
.getMember("connect")
.getReturn()
.getMember("run")
.getACall()
.getParameter(0, "command")
.asSink()
}
}
}

View File

@@ -0,0 +1,50 @@
/**
* Provides classes modeling security-relevant aspects of the `netmiko` PyPI package.
* See https://pypi.org/project/netmiko/.
*/
private import python
private import semmle.python.dataflow.new.DataFlow
private import semmle.python.dataflow.new.RemoteFlowSources
private import semmle.python.Concepts
private import semmle.python.ApiGraphs
import experimental.semmle.python.security.SecondaryServerCmdInjectionCustomizations
/**
* Provides models for the `netmiko` PyPI package.
* See https://pypi.org/project/netmiko/.
*/
private module Netmiko {
/**
* Gets `netmiko` package.
*/
private API::Node netmiko() { result = API::moduleImport("netmiko") }
/**
* Gets `netmiko.ConnectHandler` return value.
*/
private API::Node netmikoConnectHandler() {
result = netmiko().getMember("ConnectHandler").getReturn()
}
/**
* The `send_*` methods responsible for executing commands on remote secondary servers.
*/
class NetmikoSendCommand extends SecondaryCommandInjection::Sink {
NetmikoSendCommand() {
this =
netmikoConnectHandler()
.getMember(["send_command", "send_command_expect", "send_command_timing"])
.getACall()
.getParameter(0, "command_string")
.asSink()
or
this =
netmikoConnectHandler()
.getMember(["send_multiline", "send_multiline_timing"])
.getACall()
.getParameter(0, "commands")
.asSink()
}
}
}

View File

@@ -0,0 +1,37 @@
/**
* Provides classes modeling security-relevant aspects of the `paramiko` PyPI package.
* See https://pypi.org/project/paramiko/.
*/
private import python
private import semmle.python.dataflow.new.DataFlow
private import semmle.python.dataflow.new.RemoteFlowSources
private import semmle.python.Concepts
private import semmle.python.ApiGraphs
import experimental.semmle.python.security.SecondaryServerCmdInjectionCustomizations
/**
* Provides models for the `paramiko` PyPI package.
* See https://pypi.org/project/paramiko/.
*/
private module Paramiko {
/**
* Gets `paramiko` package.
*/
private API::Node paramiko() { result = API::moduleImport("paramiko") }
/**
* Gets `paramiko.SSHClient` return value.
*/
private API::Node paramikoClient() { result = paramiko().getMember("SSHClient").getReturn() }
/**
* The `exec_command` of `paramiko.SSHClient` class execute command on ssh target server
*/
class ParamikoExecCommand extends SecondaryCommandInjection::Sink {
ParamikoExecCommand() {
this =
paramikoClient().getMember("exec_command").getACall().getParameter(0, "command").asSink()
}
}
}

View File

@@ -0,0 +1,70 @@
/**
* Provides classes modeling security-relevant aspects of the `scrapli` PyPI package.
* See https://pypi.org/project/scrapli/.
*/
private import python
private import semmle.python.dataflow.new.DataFlow
private import semmle.python.dataflow.new.RemoteFlowSources
private import semmle.python.Concepts
private import semmle.python.ApiGraphs
import experimental.semmle.python.security.SecondaryServerCmdInjectionCustomizations
/**
* Provides models for the `scrapli` PyPI package.
* See https://pypi.org/project/scrapli/.
*/
private module Scrapli {
/**
* Gets `scrapli` package.
*/
private API::Node scrapli() { result = API::moduleImport("scrapli") }
/**
* Gets `scrapli.driver` package.
*/
private API::Node scrapliDriver() { result = scrapli().getMember("driver") }
/**
* Gets `scrapli.driver.core` package.
*/
private API::Node scrapliCore() { result = scrapliDriver().getMember("core") }
/**
* A `send_command` method responsible for executing commands on remote secondary servers.
*/
class ScrapliSendCommand extends SecondaryCommandInjection::Sink {
ScrapliSendCommand() {
this =
scrapliCore()
.getMember([
"AsyncNXOSDriver", "AsyncJunosDriver", "AsyncEOSDriver", "AsyncIOSXEDriver",
"AsyncIOSXRDriver", "NXOSDriver", "JunosDriver", "EOSDriver", "IOSXEDriver",
"IOSXRDriver"
])
.getReturn()
.getMember("send_command")
.getACall()
.getParameter(0, "command")
.asSink()
or
this =
scrapli()
.getMember("Scrapli")
.getReturn()
.getMember("send_command")
.getACall()
.getParameter(0, "command")
.asSink()
or
this =
scrapliDriver()
.getMember("GenericDriver")
.getReturn()
.getMember("send_command")
.getACall()
.getParameter(0, "command")
.asSink()
}
}
}

View File

@@ -0,0 +1,48 @@
/**
* Provides classes modeling security-relevant aspects of the `ssh2-python` PyPI package.
* See https://pypi.org/project/ssh2-python/.
*/
private import python
private import semmle.python.dataflow.new.DataFlow
private import semmle.python.dataflow.new.RemoteFlowSources
private import semmle.python.Concepts
private import semmle.python.ApiGraphs
import experimental.semmle.python.security.SecondaryServerCmdInjectionCustomizations
/**
* Provides models for the `ssh2-python` PyPI package.
* See https://pypi.org/project/ssh2-python/.
*/
private module Ssh2 {
/**
* Gets `ssh2` package.
*/
private API::Node ssh2() { result = API::moduleImport("ssh2") }
/**
* Gets `ssh2.session` package.
*/
private API::Node ssh2Session() { result = API::moduleImport("ssh2").getMember("session") }
/**
* Gets `ssh2.session.Session` return value.
*/
private API::Node ssh2Session() { result = ssh2Session().getMember("Session").getReturn() }
/**
* A `execute` method responsible for executing commands on remote secondary servers.
*/
class Ssh2Execute extends SecondaryCommandInjection::Sink {
Ssh2Execute() {
this =
ssh2Session()
.getMember("open_session")
.getReturn()
.getMember("execute")
.getACall()
.getParameter(0, "command")
.asSink()
}
}
}

View File

@@ -4,42 +4,10 @@ import semmle.python.dataflow.new.RemoteFlowSources
import semmle.python.ApiGraphs
import semmle.python.dataflow.new.internal.DataFlowPublic
import codeql.util.Unit
/**
* Provides sinks and additional taint steps for the secondary command injection configuration
*/
module SecondaryCommandInjection {
/**
* The additional taint steps that need for creating taint tracking or dataflow.
*/
class AdditionalTaintStep extends Unit {
/**
* Holds if there is a additional taint step between pred and succ.
*/
abstract predicate isAdditionalTaintStep(DataFlow::Node pred, DataFlow::Node succ);
}
/**
* A abstract class responsible for extending new decompression sinks
*/
abstract class Sink extends DataFlow::Node { }
}
/**
* The exec_command of `paramiko.SSHClient` class execute command on ssh target server
*/
class ParamikoExecCommand extends SecondaryCommandInjection::Sink {
ParamikoExecCommand() {
this = paramikoClient().getMember("exec_command").getACall().getParameter(0, "command").asSink()
}
}
private API::Node paramikoClient() {
result = API::moduleImport("paramiko").getMember("SSHClient").getReturn()
}
import SecondaryServerCmdInjectionCustomizations
module SecondaryCommandInjectionConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource }
predicate isSource(DataFlow::Node source) { source instanceof SecondaryCommandInjection::Source }
predicate isSink(DataFlow::Node sink) { sink instanceof SecondaryCommandInjection::Sink }
}

View File

@@ -0,0 +1,35 @@
import python
import semmle.python.dataflow.new.TaintTracking
import semmle.python.dataflow.new.RemoteFlowSources
import semmle.python.ApiGraphs
import semmle.python.dataflow.new.internal.DataFlowPublic
import codeql.util.Unit
/**
* Provides sinks and additional taint steps for the secondary command injection configuration
*/
module SecondaryCommandInjection {
/**
* The additional taint steps that need for creating taint tracking or dataflow.
*/
class AdditionalTaintStep extends Unit {
/**
* Holds if there is a additional taint step between pred and succ.
*/
abstract predicate isAdditionalTaintStep(DataFlow::Node pred, DataFlow::Node succ);
}
/**
* A abstract class responsible for extending secondary command injection dataflow sinks.
*/
abstract class Sink extends DataFlow::Node { }
/**
* A data flow source for secondary command injection data flow queries.
*/
abstract class Source extends DataFlow::Node { }
class RemoteSources extends Source {
RemoteSources() { this instanceof RemoteFlowSource }
}
}