mirror of
https://github.com/github/codeql.git
synced 2026-04-27 17:55:19 +02:00
Python: Treat os.exec*, os.spawn*, and os.posix_spawn* as FileSystemAccess
This commit is contained in:
@@ -467,7 +467,8 @@ private module StdlibPrivate {
|
||||
* A call to any of the `os.exec*` functions
|
||||
* See https://docs.python.org/3.8/library/os.html#os.execl
|
||||
*/
|
||||
private class OsExecCall extends SystemCommandExecution::Range, DataFlow::CallCfgNode {
|
||||
private class OsExecCall extends SystemCommandExecution::Range, FileSystemAccess::Range,
|
||||
DataFlow::CallCfgNode {
|
||||
OsExecCall() {
|
||||
exists(string name |
|
||||
name in ["execl", "execle", "execlp", "execlpe", "execv", "execve", "execvp", "execvpe"] and
|
||||
@@ -476,13 +477,16 @@ private module StdlibPrivate {
|
||||
}
|
||||
|
||||
override DataFlow::Node getCommand() { result = this.getArg(0) }
|
||||
|
||||
override DataFlow::Node getAPathArgument() { result = this.getCommand() }
|
||||
}
|
||||
|
||||
/**
|
||||
* A call to any of the `os.spawn*` functions
|
||||
* See https://docs.python.org/3.8/library/os.html#os.spawnl
|
||||
*/
|
||||
private class OsSpawnCall extends SystemCommandExecution::Range, DataFlow::CallCfgNode {
|
||||
private class OsSpawnCall extends SystemCommandExecution::Range, FileSystemAccess::Range,
|
||||
DataFlow::CallCfgNode {
|
||||
OsSpawnCall() {
|
||||
exists(string name |
|
||||
name in [
|
||||
@@ -499,16 +503,21 @@ private module StdlibPrivate {
|
||||
// over-approximation is not hurting anyone, and is easy to implement.
|
||||
result = this.getArgByName("file")
|
||||
}
|
||||
|
||||
override DataFlow::Node getAPathArgument() { result = this.getCommand() }
|
||||
}
|
||||
|
||||
/**
|
||||
* A call to any of the `os.posix_spawn*` functions
|
||||
* See https://docs.python.org/3.8/library/os.html#os.posix_spawn
|
||||
*/
|
||||
private class OsPosixSpawnCall extends SystemCommandExecution::Range, DataFlow::CallCfgNode {
|
||||
private class OsPosixSpawnCall extends SystemCommandExecution::Range, FileSystemAccess::Range,
|
||||
DataFlow::CallCfgNode {
|
||||
OsPosixSpawnCall() { this = os().getMember(["posix_spawn", "posix_spawnp"]).getACall() }
|
||||
|
||||
override DataFlow::Node getCommand() { result in [this.getArg(0), this.getArgByName("path")] }
|
||||
|
||||
override DataFlow::Node getAPathArgument() { result = this.getCommand() }
|
||||
}
|
||||
|
||||
/** An additional taint step for calls to `os.path.join` */
|
||||
|
||||
@@ -44,42 +44,42 @@ def os_members():
|
||||
# doesn't sound safe even if that is restricted to be within a certain directory.
|
||||
if UNKNOWN:
|
||||
env = {"FOO": "foo"}
|
||||
os.execl("path", "<progname>", "arg0") # $ getCommand="path" MISSING: getAPathArgument="path"
|
||||
os.execle("path", "<progname>", "arg0", env) # $ getCommand="path" MISSING: getAPathArgument="path"
|
||||
os.execlp("file", "<progname>", "arg0") # $ getCommand="file" MISSING: getAPathArgument="file"
|
||||
os.execlpe("file", "<progname>", "arg0", env) # $ getCommand="file" MISSING: getAPathArgument="file"
|
||||
os.execv("path", ["<progname>", "arg0"]) # $ getCommand="path" MISSING: getAPathArgument="path"
|
||||
os.execve("path", ["<progname>", "arg0"], env) # $ getCommand="path" MISSING: getAPathArgument="path"
|
||||
os.execvp("file", ["<progname>", "arg0"]) # $ getCommand="file" MISSING: getAPathArgument="file"
|
||||
os.execvpe("file", ["<progname>", "arg0"], env) # $ getCommand="file" MISSING: getAPathArgument="file"
|
||||
os.execl("path", "<progname>", "arg0") # $ getCommand="path" getAPathArgument="path"
|
||||
os.execle("path", "<progname>", "arg0", env) # $ getCommand="path" getAPathArgument="path"
|
||||
os.execlp("file", "<progname>", "arg0") # $ getCommand="file" getAPathArgument="file"
|
||||
os.execlpe("file", "<progname>", "arg0", env) # $ getCommand="file" getAPathArgument="file"
|
||||
os.execv("path", ["<progname>", "arg0"]) # $ getCommand="path" getAPathArgument="path"
|
||||
os.execve("path", ["<progname>", "arg0"], env) # $ getCommand="path" getAPathArgument="path"
|
||||
os.execvp("file", ["<progname>", "arg0"]) # $ getCommand="file" getAPathArgument="file"
|
||||
os.execvpe("file", ["<progname>", "arg0"], env) # $ getCommand="file" getAPathArgument="file"
|
||||
|
||||
|
||||
########################################
|
||||
# https://docs.python.org/3.8/library/os.html#os.spawnl
|
||||
env = {"FOO": "foo"}
|
||||
os.spawnl(os.P_WAIT, "path", "<progname>", "arg0") # $ getCommand="path" MISSING: getAPathArgument="path"
|
||||
os.spawnle(os.P_WAIT, "path", "<progname>", "arg0", env) # $ getCommand="path" MISSING: getAPathArgument="path"
|
||||
os.spawnlp(os.P_WAIT, "file", "<progname>", "arg0") # $ getCommand="file" MISSING: getAPathArgument="file"
|
||||
os.spawnlpe(os.P_WAIT, "file", "<progname>", "arg0", env) # $ getCommand="file" MISSING: getAPathArgument="file"
|
||||
os.spawnv(os.P_WAIT, "path", ["<progname>", "arg0"]) # $ getCommand="path" MISSING: getAPathArgument="path"
|
||||
os.spawnve(os.P_WAIT, "path", ["<progname>", "arg0"], env) # $ getCommand="path" MISSING: getAPathArgument="path"
|
||||
os.spawnvp(os.P_WAIT, "file", ["<progname>", "arg0"]) # $ getCommand="file" MISSING: getAPathArgument="file"
|
||||
os.spawnvpe(os.P_WAIT, "file", ["<progname>", "arg0"], env) # $ getCommand="file" MISSING: getAPathArgument="file"
|
||||
os.spawnl(os.P_WAIT, "path", "<progname>", "arg0") # $ getCommand="path" getAPathArgument="path"
|
||||
os.spawnle(os.P_WAIT, "path", "<progname>", "arg0", env) # $ getCommand="path" getAPathArgument="path"
|
||||
os.spawnlp(os.P_WAIT, "file", "<progname>", "arg0") # $ getCommand="file" getAPathArgument="file"
|
||||
os.spawnlpe(os.P_WAIT, "file", "<progname>", "arg0", env) # $ getCommand="file" getAPathArgument="file"
|
||||
os.spawnv(os.P_WAIT, "path", ["<progname>", "arg0"]) # $ getCommand="path" getAPathArgument="path"
|
||||
os.spawnve(os.P_WAIT, "path", ["<progname>", "arg0"], env) # $ getCommand="path" getAPathArgument="path"
|
||||
os.spawnvp(os.P_WAIT, "file", ["<progname>", "arg0"]) # $ getCommand="file" getAPathArgument="file"
|
||||
os.spawnvpe(os.P_WAIT, "file", ["<progname>", "arg0"], env) # $ getCommand="file" getAPathArgument="file"
|
||||
|
||||
# unlike os.exec*, some os.spawn* functions is usable with keyword arguments. However,
|
||||
# despite the docs using both `file` and `path` as the parameter name, you actually need
|
||||
# to use `file` in all cases.
|
||||
os.spawnv(mode=os.P_WAIT, file="path", args=["<progname>", "arg0"]) # $ getCommand="path" MISSING: getAPathArgument="path"
|
||||
os.spawnve(mode=os.P_WAIT, file="path", args=["<progname>", "arg0"], env=env) # $ getCommand="path" MISSING: getAPathArgument="path"
|
||||
os.spawnvp(mode=os.P_WAIT, file="file", args=["<progname>", "arg0"]) # $ getCommand="file" MISSING: getAPathArgument="file"
|
||||
os.spawnvpe(mode=os.P_WAIT, file="file", args=["<progname>", "arg0"], env=env) # $ getCommand="file" MISSING: getAPathArgument="file"
|
||||
os.spawnv(mode=os.P_WAIT, file="path", args=["<progname>", "arg0"]) # $ getCommand="path" getAPathArgument="path"
|
||||
os.spawnve(mode=os.P_WAIT, file="path", args=["<progname>", "arg0"], env=env) # $ getCommand="path" getAPathArgument="path"
|
||||
os.spawnvp(mode=os.P_WAIT, file="file", args=["<progname>", "arg0"]) # $ getCommand="file" getAPathArgument="file"
|
||||
os.spawnvpe(mode=os.P_WAIT, file="file", args=["<progname>", "arg0"], env=env) # $ getCommand="file" getAPathArgument="file"
|
||||
|
||||
# `posix_spawn` Added in Python 3.8
|
||||
os.posix_spawn("path", ["<progname>", "arg0"], env) # $ getCommand="path" MISSING: getAPathArgument="path"
|
||||
os.posix_spawn(path="path", argv=["<progname>", "arg0"], env=env) # $ getCommand="path" MISSING: getAPathArgument="path"
|
||||
os.posix_spawn("path", ["<progname>", "arg0"], env) # $ getCommand="path" getAPathArgument="path"
|
||||
os.posix_spawn(path="path", argv=["<progname>", "arg0"], env=env) # $ getCommand="path" getAPathArgument="path"
|
||||
|
||||
os.posix_spawnp("path", ["<progname>", "arg0"], env) # $ getCommand="path" MISSING: getAPathArgument="path"
|
||||
os.posix_spawnp(path="path", argv=["<progname>", "arg0"], env=env) # $ getCommand="path" MISSING: getAPathArgument="path"
|
||||
os.posix_spawnp("path", ["<progname>", "arg0"], env) # $ getCommand="path" getAPathArgument="path"
|
||||
os.posix_spawnp(path="path", argv=["<progname>", "arg0"], env=env) # $ getCommand="path" getAPathArgument="path"
|
||||
|
||||
########################################
|
||||
|
||||
@@ -126,9 +126,9 @@ subprocess.Popen(["cmd", "/C", "vuln"]) # $getCommand="cmd" MISSING: getCommand
|
||||
subprocess.Popen(["<progname>", "-c", "vuln"], executable="/bin/bash") # $getCommand="/bin/bash" MISSING: getCommand="vuln"
|
||||
|
||||
if UNKNOWN:
|
||||
os.execl("/bin/sh", "<progname>", "-c", "vuln") # $getCommand="/bin/sh" MISSING: getCommand="vuln"
|
||||
os.execl("/bin/sh", "<progname>", "-c", "vuln") # $getCommand="/bin/sh" getAPathArgument="/bin/sh" MISSING: getCommand="vuln"
|
||||
|
||||
os.spawnl(os.P_WAIT, "/bin/sh", "<progname>", "-c", "vuln") # $getCommand="/bin/sh" MISSING: getCommand="vuln"
|
||||
os.spawnl(os.P_WAIT, "/bin/sh", "<progname>", "-c", "vuln") # $getCommand="/bin/sh" getAPathArgument="/bin/sh" MISSING: getCommand="vuln"
|
||||
|
||||
|
||||
########################################
|
||||
|
||||
Reference in New Issue
Block a user