зеркало из https://github.com/github/codeql.git
Merge pull request #7259 from RasmusWL/even-more-path-injection-sinks
Python: Add more path-injection sinks from `os` and `tempfile` modules
This commit is contained in:
Коммит
8e11c2c476
|
@ -1,2 +0,0 @@
|
|||
lgtm,codescanning
|
||||
* Added modeling of `os.stat`, `os.lstat`, `os.statvfs`, `os.fstat`, and `os.fstatvfs`, which are new sinks for the _Uncontrolled data used in path expression_ (`py/path-injection`) query.
|
|
@ -0,0 +1,2 @@
|
|||
lgtm,codescanning
|
||||
* Added modeling of many functions from the `os` module that uses file system paths, such as `os.stat`, `os.chdir`, `os.mkdir`, and so on. All of these are new sinks for the _Uncontrolled data used in path expression_ (`py/path-injection`) query.
|
|
@ -0,0 +1,2 @@
|
|||
lgtm,codescanning
|
||||
* Added modeling of the `tempfile` module for creating temporary files and directories, such as the functions `tempfile.NamedTemporaryFile` and `tempfile.TemporaryDirectory`. The `suffix`, `prefix`, and `dir` arguments are all vulnerable to path-injection, and these are new sinks for the _Uncontrolled data used in path expression_ (`py/path-injection`) query.
|
|
@ -276,25 +276,589 @@ private module StdlibPrivate {
|
|||
}
|
||||
|
||||
/**
|
||||
* The `os` module has multiple methods for getting the status of a file, like
|
||||
* a stat() system call.
|
||||
*
|
||||
* Note: `os.fstat` and `os.fstatvfs` operate on file-descriptors.
|
||||
*
|
||||
* See:
|
||||
* - https://docs.python.org/3.10/library/os.html#os.stat
|
||||
* - https://docs.python.org/3.10/library/os.html#os.lstat
|
||||
* - https://docs.python.org/3.10/library/os.html#os.statvfs
|
||||
* - https://docs.python.org/3.10/library/os.html#os.fstat
|
||||
* - https://docs.python.org/3.10/library/os.html#os.fstatvfs
|
||||
* Modeling of path related functions in the `os` module.
|
||||
* Wrapped in QL module to make it easy to fold/unfold.
|
||||
*/
|
||||
private class OsProbingCall extends FileSystemAccess::Range, DataFlow::CallCfgNode {
|
||||
OsProbingCall() {
|
||||
this = os().getMember(["stat", "lstat", "statvfs", "fstat", "fstatvfs"]).getACall()
|
||||
private module OsFileSystemAccessModeling {
|
||||
/**
|
||||
* A call to the `os.fsencode` function.
|
||||
*
|
||||
* See https://docs.python.org/3/library/os.html#os.fsencode
|
||||
*/
|
||||
private class OsFsencodeCall extends Encoding::Range, DataFlow::CallCfgNode {
|
||||
OsFsencodeCall() { this = os().getMember("fsencode").getACall() }
|
||||
|
||||
override DataFlow::Node getAnInput() {
|
||||
result in [this.getArg(0), this.getArgByName("filename")]
|
||||
}
|
||||
|
||||
override DataFlow::Node getOutput() { result = this }
|
||||
|
||||
override string getFormat() { result = "filesystem" }
|
||||
}
|
||||
|
||||
override DataFlow::Node getAPathArgument() {
|
||||
result in [this.getArg(0), this.getArgByName("path")]
|
||||
/**
|
||||
* A call to the `os.fsdecode` function.
|
||||
*
|
||||
* See https://docs.python.org/3/library/os.html#os.fsdecode
|
||||
*/
|
||||
private class OsFsdecodeCall extends Decoding::Range, DataFlow::CallCfgNode {
|
||||
OsFsdecodeCall() { this = os().getMember("fsdecode").getACall() }
|
||||
|
||||
override DataFlow::Node getAnInput() {
|
||||
result in [this.getArg(0), this.getArgByName("filename")]
|
||||
}
|
||||
|
||||
override DataFlow::Node getOutput() { result = this }
|
||||
|
||||
override string getFormat() { result = "filesystem" }
|
||||
|
||||
override predicate mayExecuteInput() { none() }
|
||||
}
|
||||
|
||||
/**
|
||||
* Additional taint step from a call to the `os.fspath` function.
|
||||
*
|
||||
* See https://docs.python.org/3/library/os.html#os.fspath
|
||||
*/
|
||||
private class OsFspathCallAdditionalTaintStep extends TaintTracking::AdditionalTaintStep {
|
||||
override predicate step(DataFlow::Node nodeFrom, DataFlow::Node nodeTo) {
|
||||
exists(DataFlow::CallCfgNode call |
|
||||
call = os().getMember("fspath").getACall() and
|
||||
nodeFrom in [call.getArg(0), call.getArgByName("path")] and
|
||||
nodeTo = call
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A call to the `os.open` function.
|
||||
*
|
||||
* See https://docs.python.org/3/library/os.html#os.open
|
||||
*/
|
||||
private class OsOpenCall extends FileSystemAccess::Range, DataFlow::CallCfgNode {
|
||||
OsOpenCall() { this = os().getMember("open").getACall() }
|
||||
|
||||
override DataFlow::Node getAPathArgument() {
|
||||
result in [this.getArg(0), this.getArgByName("path")]
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A call to the `os.access` function.
|
||||
*
|
||||
* See https://docs.python.org/3/library/os.html#os.access
|
||||
*/
|
||||
private class OsAccessCall extends FileSystemAccess::Range, DataFlow::CallCfgNode {
|
||||
OsAccessCall() { this = os().getMember("access").getACall() }
|
||||
|
||||
override DataFlow::Node getAPathArgument() {
|
||||
result in [this.getArg(0), this.getArgByName("path")]
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A call to the `os.chdir` function.
|
||||
*
|
||||
* See https://docs.python.org/3/library/os.html#os.chdir
|
||||
*/
|
||||
private class OsChdirCall extends FileSystemAccess::Range, DataFlow::CallCfgNode {
|
||||
OsChdirCall() { this = os().getMember("chdir").getACall() }
|
||||
|
||||
override DataFlow::Node getAPathArgument() {
|
||||
result in [this.getArg(0), this.getArgByName("path")]
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A call to the `os.chflags` function.
|
||||
*
|
||||
* See https://docs.python.org/3/library/os.html#os.chflags
|
||||
*/
|
||||
private class OsChflagsCall extends FileSystemAccess::Range, DataFlow::CallCfgNode {
|
||||
OsChflagsCall() { this = os().getMember("chflags").getACall() }
|
||||
|
||||
override DataFlow::Node getAPathArgument() {
|
||||
result in [this.getArg(0), this.getArgByName("path")]
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A call to the `os.chmod` function.
|
||||
*
|
||||
* See https://docs.python.org/3/library/os.html#os.chmod
|
||||
*/
|
||||
private class OsChmodCall extends FileSystemAccess::Range, DataFlow::CallCfgNode {
|
||||
OsChmodCall() { this = os().getMember("chmod").getACall() }
|
||||
|
||||
override DataFlow::Node getAPathArgument() {
|
||||
result in [this.getArg(0), this.getArgByName("path")]
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A call to the `os.chown` function.
|
||||
*
|
||||
* See https://docs.python.org/3/library/os.html#os.chown
|
||||
*/
|
||||
private class OsChownCall extends FileSystemAccess::Range, DataFlow::CallCfgNode {
|
||||
OsChownCall() { this = os().getMember("chown").getACall() }
|
||||
|
||||
override DataFlow::Node getAPathArgument() {
|
||||
result in [this.getArg(0), this.getArgByName("path")]
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A call to the `os.chroot` function.
|
||||
*
|
||||
* See https://docs.python.org/3/library/os.html#os.chroot
|
||||
*/
|
||||
private class OsChrootCall extends FileSystemAccess::Range, DataFlow::CallCfgNode {
|
||||
OsChrootCall() { this = os().getMember("chroot").getACall() }
|
||||
|
||||
override DataFlow::Node getAPathArgument() {
|
||||
result in [this.getArg(0), this.getArgByName("path")]
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A call to the `os.lchflags` function.
|
||||
*
|
||||
* See https://docs.python.org/3/library/os.html#os.lchflags
|
||||
*/
|
||||
private class OsLchflagsCall extends FileSystemAccess::Range, DataFlow::CallCfgNode {
|
||||
OsLchflagsCall() { this = os().getMember("lchflags").getACall() }
|
||||
|
||||
override DataFlow::Node getAPathArgument() {
|
||||
result in [this.getArg(0), this.getArgByName("path")]
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A call to the `os.lchmod` function.
|
||||
*
|
||||
* See https://docs.python.org/3/library/os.html#os.lchmod
|
||||
*/
|
||||
private class OsLchmodCall extends FileSystemAccess::Range, DataFlow::CallCfgNode {
|
||||
OsLchmodCall() { this = os().getMember("lchmod").getACall() }
|
||||
|
||||
override DataFlow::Node getAPathArgument() {
|
||||
result in [this.getArg(0), this.getArgByName("path")]
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A call to the `os.lchown` function.
|
||||
*
|
||||
* See https://docs.python.org/3/library/os.html#os.lchown
|
||||
*/
|
||||
private class OsLchownCall extends FileSystemAccess::Range, DataFlow::CallCfgNode {
|
||||
OsLchownCall() { this = os().getMember("lchown").getACall() }
|
||||
|
||||
override DataFlow::Node getAPathArgument() {
|
||||
result in [this.getArg(0), this.getArgByName("path")]
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A call to the `os.link` function.
|
||||
*
|
||||
* See https://docs.python.org/3/library/os.html#os.link
|
||||
*/
|
||||
private class OsLinkCall extends FileSystemAccess::Range, DataFlow::CallCfgNode {
|
||||
OsLinkCall() { this = os().getMember("link").getACall() }
|
||||
|
||||
override DataFlow::Node getAPathArgument() {
|
||||
result in [
|
||||
this.getArg(0), this.getArgByName("src"), this.getArg(1), this.getArgByName("dst")
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A call to the `os.listdir` function.
|
||||
*
|
||||
* See https://docs.python.org/3/library/os.html#os.listdir
|
||||
*/
|
||||
private class OsListdirCall extends FileSystemAccess::Range, DataFlow::CallCfgNode {
|
||||
OsListdirCall() { this = os().getMember("listdir").getACall() }
|
||||
|
||||
override DataFlow::Node getAPathArgument() {
|
||||
result in [this.getArg(0), this.getArgByName("path")]
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A call to the `os.lstat` function.
|
||||
*
|
||||
* See https://docs.python.org/3/library/os.html#os.lstat
|
||||
*/
|
||||
private class OsLstatCall extends FileSystemAccess::Range, DataFlow::CallCfgNode {
|
||||
OsLstatCall() { this = os().getMember("lstat").getACall() }
|
||||
|
||||
override DataFlow::Node getAPathArgument() {
|
||||
result in [this.getArg(0), this.getArgByName("path")]
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A call to the `os.mkdir` function.
|
||||
*
|
||||
* See https://docs.python.org/3/library/os.html#os.mkdir
|
||||
*/
|
||||
private class OsMkdirCall extends FileSystemAccess::Range, DataFlow::CallCfgNode {
|
||||
OsMkdirCall() { this = os().getMember("mkdir").getACall() }
|
||||
|
||||
override DataFlow::Node getAPathArgument() {
|
||||
result in [this.getArg(0), this.getArgByName("path")]
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A call to the `os.makedirs` function.
|
||||
*
|
||||
* See https://docs.python.org/3/library/os.html#os.makedirs
|
||||
*/
|
||||
private class OsMakedirsCall extends FileSystemAccess::Range, DataFlow::CallCfgNode {
|
||||
OsMakedirsCall() { this = os().getMember("makedirs").getACall() }
|
||||
|
||||
override DataFlow::Node getAPathArgument() {
|
||||
result in [this.getArg(0), this.getArgByName("name")]
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A call to the `os.mkfifo` function.
|
||||
*
|
||||
* See https://docs.python.org/3/library/os.html#os.mkfifo
|
||||
*/
|
||||
private class OsMkfifoCall extends FileSystemAccess::Range, DataFlow::CallCfgNode {
|
||||
OsMkfifoCall() { this = os().getMember("mkfifo").getACall() }
|
||||
|
||||
override DataFlow::Node getAPathArgument() {
|
||||
result in [this.getArg(0), this.getArgByName("path")]
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A call to the `os.mknod` function.
|
||||
*
|
||||
* See https://docs.python.org/3/library/os.html#os.mknod
|
||||
*/
|
||||
private class OsMknodCall extends FileSystemAccess::Range, DataFlow::CallCfgNode {
|
||||
OsMknodCall() { this = os().getMember("mknod").getACall() }
|
||||
|
||||
override DataFlow::Node getAPathArgument() {
|
||||
result in [this.getArg(0), this.getArgByName("path")]
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A call to the `os.pathconf` function.
|
||||
*
|
||||
* See https://docs.python.org/3/library/os.html#os.pathconf
|
||||
*/
|
||||
private class OsPathconfCall extends FileSystemAccess::Range, DataFlow::CallCfgNode {
|
||||
OsPathconfCall() { this = os().getMember("pathconf").getACall() }
|
||||
|
||||
override DataFlow::Node getAPathArgument() {
|
||||
result in [this.getArg(0), this.getArgByName("path")]
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A call to the `os.readlink` function.
|
||||
*
|
||||
* See https://docs.python.org/3/library/os.html#os.readlink
|
||||
*/
|
||||
private class OsReadlinkCall extends FileSystemAccess::Range, DataFlow::CallCfgNode {
|
||||
OsReadlinkCall() { this = os().getMember("readlink").getACall() }
|
||||
|
||||
override DataFlow::Node getAPathArgument() {
|
||||
result in [this.getArg(0), this.getArgByName("path")]
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A call to the `os.remove` function.
|
||||
*
|
||||
* See https://docs.python.org/3/library/os.html#os.remove
|
||||
*/
|
||||
private class OsRemoveCall extends FileSystemAccess::Range, DataFlow::CallCfgNode {
|
||||
OsRemoveCall() { this = os().getMember("remove").getACall() }
|
||||
|
||||
override DataFlow::Node getAPathArgument() {
|
||||
result in [this.getArg(0), this.getArgByName("path")]
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A call to the `os.removedirs` function.
|
||||
*
|
||||
* See https://docs.python.org/3/library/os.html#os.removedirs
|
||||
*/
|
||||
private class OsRemovedirsCall extends FileSystemAccess::Range, DataFlow::CallCfgNode {
|
||||
OsRemovedirsCall() { this = os().getMember("removedirs").getACall() }
|
||||
|
||||
override DataFlow::Node getAPathArgument() {
|
||||
result in [this.getArg(0), this.getArgByName("name")]
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A call to the `os.rename` function.
|
||||
*
|
||||
* See https://docs.python.org/3/library/os.html#os.rename
|
||||
*/
|
||||
private class OsRenameCall extends FileSystemAccess::Range, DataFlow::CallCfgNode {
|
||||
OsRenameCall() { this = os().getMember("rename").getACall() }
|
||||
|
||||
override DataFlow::Node getAPathArgument() {
|
||||
result in [
|
||||
this.getArg(0), this.getArgByName("src"), this.getArg(1), this.getArgByName("dst")
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A call to the `os.renames` function.
|
||||
*
|
||||
* See https://docs.python.org/3/library/os.html#os.renames
|
||||
*/
|
||||
private class OsRenamesCall extends FileSystemAccess::Range, DataFlow::CallCfgNode {
|
||||
OsRenamesCall() { this = os().getMember("renames").getACall() }
|
||||
|
||||
override DataFlow::Node getAPathArgument() {
|
||||
result in [
|
||||
this.getArg(0), this.getArgByName("old"), this.getArg(1), this.getArgByName("new")
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A call to the `os.replace` function.
|
||||
*
|
||||
* See https://docs.python.org/3/library/os.html#os.replace
|
||||
*/
|
||||
private class OsReplaceCall extends FileSystemAccess::Range, DataFlow::CallCfgNode {
|
||||
OsReplaceCall() { this = os().getMember("replace").getACall() }
|
||||
|
||||
override DataFlow::Node getAPathArgument() {
|
||||
result in [
|
||||
this.getArg(0), this.getArgByName("src"), this.getArg(1), this.getArgByName("dst")
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A call to the `os.rmdir` function.
|
||||
*
|
||||
* See https://docs.python.org/3/library/os.html#os.rmdir
|
||||
*/
|
||||
private class OsRmdirCall extends FileSystemAccess::Range, DataFlow::CallCfgNode {
|
||||
OsRmdirCall() { this = os().getMember("rmdir").getACall() }
|
||||
|
||||
override DataFlow::Node getAPathArgument() {
|
||||
result in [this.getArg(0), this.getArgByName("path")]
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A call to the `os.scandir` function.
|
||||
*
|
||||
* See https://docs.python.org/3/library/os.html#os.scandir
|
||||
*/
|
||||
private class OsScandirCall extends FileSystemAccess::Range, DataFlow::CallCfgNode {
|
||||
OsScandirCall() { this = os().getMember("scandir").getACall() }
|
||||
|
||||
override DataFlow::Node getAPathArgument() {
|
||||
result in [this.getArg(0), this.getArgByName("path")]
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A call to the `os.stat` function.
|
||||
*
|
||||
* See https://docs.python.org/3/library/os.html#os.stat
|
||||
*/
|
||||
private class OsStatCall extends FileSystemAccess::Range, DataFlow::CallCfgNode {
|
||||
OsStatCall() { this = os().getMember("stat").getACall() }
|
||||
|
||||
override DataFlow::Node getAPathArgument() {
|
||||
result in [this.getArg(0), this.getArgByName("path")]
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A call to the `os.statvfs` function.
|
||||
*
|
||||
* See https://docs.python.org/3/library/os.html#os.statvfs
|
||||
*/
|
||||
private class OsStatvfsCall extends FileSystemAccess::Range, DataFlow::CallCfgNode {
|
||||
OsStatvfsCall() { this = os().getMember("statvfs").getACall() }
|
||||
|
||||
override DataFlow::Node getAPathArgument() {
|
||||
result in [this.getArg(0), this.getArgByName("path")]
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A call to the `os.symlink` function.
|
||||
*
|
||||
* See https://docs.python.org/3/library/os.html#os.symlink
|
||||
*/
|
||||
private class OsSymlinkCall extends FileSystemAccess::Range, DataFlow::CallCfgNode {
|
||||
OsSymlinkCall() { this = os().getMember("symlink").getACall() }
|
||||
|
||||
override DataFlow::Node getAPathArgument() {
|
||||
result in [
|
||||
this.getArg(0), this.getArgByName("src"), this.getArg(1), this.getArgByName("dst")
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A call to the `os.truncate` function.
|
||||
*
|
||||
* See https://docs.python.org/3/library/os.html#os.truncate
|
||||
*/
|
||||
private class OsTruncateCall extends FileSystemAccess::Range, DataFlow::CallCfgNode {
|
||||
OsTruncateCall() { this = os().getMember("truncate").getACall() }
|
||||
|
||||
override DataFlow::Node getAPathArgument() {
|
||||
result in [this.getArg(0), this.getArgByName("path")]
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A call to the `os.unlink` function.
|
||||
*
|
||||
* See https://docs.python.org/3/library/os.html#os.unlink
|
||||
*/
|
||||
private class OsUnlinkCall extends FileSystemAccess::Range, DataFlow::CallCfgNode {
|
||||
OsUnlinkCall() { this = os().getMember("unlink").getACall() }
|
||||
|
||||
override DataFlow::Node getAPathArgument() {
|
||||
result in [this.getArg(0), this.getArgByName("path")]
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A call to the `os.utime` function.
|
||||
*
|
||||
* See https://docs.python.org/3/library/os.html#os.utime
|
||||
*/
|
||||
private class OsUtimeCall extends FileSystemAccess::Range, DataFlow::CallCfgNode {
|
||||
OsUtimeCall() { this = os().getMember("utime").getACall() }
|
||||
|
||||
override DataFlow::Node getAPathArgument() {
|
||||
result in [this.getArg(0), this.getArgByName("path")]
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A call to the `os.walk` function.
|
||||
*
|
||||
* See https://docs.python.org/3/library/os.html#os.walk
|
||||
*/
|
||||
private class OsWalkCall extends FileSystemAccess::Range, DataFlow::CallCfgNode {
|
||||
OsWalkCall() { this = os().getMember("walk").getACall() }
|
||||
|
||||
override DataFlow::Node getAPathArgument() {
|
||||
result in [this.getArg(0), this.getArgByName("top")]
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A call to the `os.fwalk` function.
|
||||
*
|
||||
* See https://docs.python.org/3/library/os.html#os.fwalk
|
||||
*/
|
||||
private class OsFwalkCall extends FileSystemAccess::Range, DataFlow::CallCfgNode {
|
||||
OsFwalkCall() { this = os().getMember("fwalk").getACall() }
|
||||
|
||||
override DataFlow::Node getAPathArgument() {
|
||||
result in [this.getArg(0), this.getArgByName("top")]
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A call to the `os.getxattr` function.
|
||||
*
|
||||
* See https://docs.python.org/3/library/os.html#os.getxattr
|
||||
*/
|
||||
private class OsGetxattrCall extends FileSystemAccess::Range, DataFlow::CallCfgNode {
|
||||
OsGetxattrCall() { this = os().getMember("getxattr").getACall() }
|
||||
|
||||
override DataFlow::Node getAPathArgument() {
|
||||
result in [this.getArg(0), this.getArgByName("path")]
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A call to the `os.listxattr` function.
|
||||
*
|
||||
* See https://docs.python.org/3/library/os.html#os.listxattr
|
||||
*/
|
||||
private class OsListxattrCall extends FileSystemAccess::Range, DataFlow::CallCfgNode {
|
||||
OsListxattrCall() { this = os().getMember("listxattr").getACall() }
|
||||
|
||||
override DataFlow::Node getAPathArgument() {
|
||||
result in [this.getArg(0), this.getArgByName("path")]
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A call to the `os.removexattr` function.
|
||||
*
|
||||
* See https://docs.python.org/3/library/os.html#os.removexattr
|
||||
*/
|
||||
private class OsRemovexattrCall extends FileSystemAccess::Range, DataFlow::CallCfgNode {
|
||||
OsRemovexattrCall() { this = os().getMember("removexattr").getACall() }
|
||||
|
||||
override DataFlow::Node getAPathArgument() {
|
||||
result in [this.getArg(0), this.getArgByName("path")]
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A call to the `os.setxattr` function.
|
||||
*
|
||||
* See https://docs.python.org/3/library/os.html#os.setxattr
|
||||
*/
|
||||
private class OsSetxattrCall extends FileSystemAccess::Range, DataFlow::CallCfgNode {
|
||||
OsSetxattrCall() { this = os().getMember("setxattr").getACall() }
|
||||
|
||||
override DataFlow::Node getAPathArgument() {
|
||||
result in [this.getArg(0), this.getArgByName("path")]
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A call to the `os.add_dll_directory` function.
|
||||
*
|
||||
* See https://docs.python.org/3/library/os.html#os.add_dll_directory
|
||||
*/
|
||||
private class OsAdd_dll_directoryCall extends FileSystemAccess::Range, DataFlow::CallCfgNode {
|
||||
OsAdd_dll_directoryCall() { this = os().getMember("add_dll_directory").getACall() }
|
||||
|
||||
override DataFlow::Node getAPathArgument() {
|
||||
result in [this.getArg(0), this.getArgByName("path")]
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A call to the `os.startfile` function.
|
||||
*
|
||||
* See https://docs.python.org/3/library/os.html#os.startfile
|
||||
*/
|
||||
private class OsStartfileCall extends FileSystemAccess::Range, DataFlow::CallCfgNode {
|
||||
OsStartfileCall() { this = os().getMember("startfile").getACall() }
|
||||
|
||||
override DataFlow::Node getAPathArgument() {
|
||||
result in [this.getArg(0), this.getArgByName("path")]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -318,20 +882,26 @@ private module StdlibPrivate {
|
|||
* - https://docs.python.org/3/library/os.path.html#os.path.realpath
|
||||
*/
|
||||
private class OsPathProbingCall extends FileSystemAccess::Range, DataFlow::CallCfgNode {
|
||||
string name;
|
||||
|
||||
OsPathProbingCall() {
|
||||
this =
|
||||
os::path()
|
||||
.getMember([
|
||||
// these check if the file exists
|
||||
"exists", "lexists", "isfile", "isdir", "islink", "ismount",
|
||||
// these raise errors if the file does not exist
|
||||
"getatime", "getmtime", "getctime", "getsize"
|
||||
])
|
||||
.getACall()
|
||||
name in [
|
||||
// these check if the file exists
|
||||
"exists", "lexists", "isfile", "isdir", "islink", "ismount",
|
||||
// these raise errors if the file does not exist
|
||||
"getatime", "getmtime", "getctime", "getsize"
|
||||
] and
|
||||
this = os::path().getMember(name).getACall()
|
||||
}
|
||||
|
||||
override DataFlow::Node getAPathArgument() {
|
||||
not name = "isdir" and
|
||||
result in [this.getArg(0), this.getArgByName("path")]
|
||||
or
|
||||
// although the Python docs say the parameter is called `path`, the implementation
|
||||
// actually uses `s`.
|
||||
name = "isdir" and
|
||||
result in [this.getArg(0), this.getArgByName("s")]
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -461,7 +1031,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
|
||||
|
@ -470,13 +1041,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 [
|
||||
|
@ -486,17 +1060,28 @@ private module StdlibPrivate {
|
|||
)
|
||||
}
|
||||
|
||||
override DataFlow::Node getCommand() { result = this.getArg(1) }
|
||||
override DataFlow::Node getCommand() {
|
||||
result = this.getArg(1)
|
||||
or
|
||||
// `file` keyword argument only valid for the `v` variants, but this
|
||||
// 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 = this.getArg(0) }
|
||||
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` */
|
||||
|
@ -2052,6 +2637,116 @@ private module StdlibPrivate {
|
|||
nodeTo.(UrllibParseUrlsplitCall).getUrl() = nodeFrom
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// tempfile
|
||||
// ---------------------------------------------------------------------------
|
||||
/**
|
||||
* A call to `tempfile.mkstemp`.
|
||||
*
|
||||
* See https://docs.python.org/3/library/tempfile.html#tempfile.mkstemp
|
||||
*/
|
||||
private class TempfileMkstempCall extends FileSystemAccess::Range, DataFlow::CallCfgNode {
|
||||
TempfileMkstempCall() { this = API::moduleImport("tempfile").getMember("mkstemp").getACall() }
|
||||
|
||||
override DataFlow::Node getAPathArgument() {
|
||||
result in [
|
||||
this.getArg(0), this.getArgByName("suffix"), this.getArg(1), this.getArgByName("prefix"),
|
||||
this.getArg(2), this.getArgByName("dir")
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A call to `tempfile.NamedTemporaryFile`.
|
||||
*
|
||||
* See https://docs.python.org/3/library/tempfile.html#tempfile.NamedTemporaryFile
|
||||
*/
|
||||
private class TempfileNamedTemporaryFileCall extends FileSystemAccess::Range,
|
||||
DataFlow::CallCfgNode {
|
||||
TempfileNamedTemporaryFileCall() {
|
||||
this = API::moduleImport("tempfile").getMember("NamedTemporaryFile").getACall()
|
||||
}
|
||||
|
||||
override DataFlow::Node getAPathArgument() {
|
||||
result in [
|
||||
this.getArg(4), this.getArgByName("suffix"), this.getArg(5), this.getArgByName("prefix"),
|
||||
this.getArg(6), this.getArgByName("dir")
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A call to `tempfile.TemporaryFile`.
|
||||
*
|
||||
* See https://docs.python.org/3/library/tempfile.html#tempfile.TemporaryFile
|
||||
*/
|
||||
private class TempfileTemporaryFileCall extends FileSystemAccess::Range, DataFlow::CallCfgNode {
|
||||
TempfileTemporaryFileCall() {
|
||||
this = API::moduleImport("tempfile").getMember("TemporaryFile").getACall()
|
||||
}
|
||||
|
||||
override DataFlow::Node getAPathArgument() {
|
||||
result in [
|
||||
this.getArg(4), this.getArgByName("suffix"), this.getArg(5), this.getArgByName("prefix"),
|
||||
this.getArg(6), this.getArgByName("dir")
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A call to `tempfile.SpooledTemporaryFile`.
|
||||
*
|
||||
* See https://docs.python.org/3/library/tempfile.html#tempfile.SpooledTemporaryFile
|
||||
*/
|
||||
private class TempfileSpooledTemporaryFileCall extends FileSystemAccess::Range,
|
||||
DataFlow::CallCfgNode {
|
||||
TempfileSpooledTemporaryFileCall() {
|
||||
this = API::moduleImport("tempfile").getMember("SpooledTemporaryFile").getACall()
|
||||
}
|
||||
|
||||
override DataFlow::Node getAPathArgument() {
|
||||
result in [
|
||||
this.getArg(5), this.getArgByName("suffix"), this.getArg(6), this.getArgByName("prefix"),
|
||||
this.getArg(7), this.getArgByName("dir")
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A call to `tempfile.mkdtemp`.
|
||||
*
|
||||
* See https://docs.python.org/3/library/tempfile.html#tempfile.mkdtemp
|
||||
*/
|
||||
private class TempfileMkdtempCall extends FileSystemAccess::Range, DataFlow::CallCfgNode {
|
||||
TempfileMkdtempCall() { this = API::moduleImport("tempfile").getMember("mkdtemp").getACall() }
|
||||
|
||||
override DataFlow::Node getAPathArgument() {
|
||||
result in [
|
||||
this.getArg(0), this.getArgByName("suffix"), this.getArg(1), this.getArgByName("prefix"),
|
||||
this.getArg(2), this.getArgByName("dir")
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A call to `tempfile.TemporaryDirectory`.
|
||||
*
|
||||
* See https://docs.python.org/3/library/tempfile.html#tempfile.TemporaryDirectory
|
||||
*/
|
||||
private class TempfileTemporaryDirectoryCall extends FileSystemAccess::Range,
|
||||
DataFlow::CallCfgNode {
|
||||
TempfileTemporaryDirectoryCall() {
|
||||
this = API::moduleImport("tempfile").getMember("TemporaryDirectory").getACall()
|
||||
}
|
||||
|
||||
override DataFlow::Node getAPathArgument() {
|
||||
result in [
|
||||
this.getArg(0), this.getArgByName("suffix"), this.getArg(1), this.getArgByName("prefix"),
|
||||
this.getArg(2), this.getArgByName("dir")
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
|
|
@ -1,21 +1,24 @@
|
|||
import builtins
|
||||
import io
|
||||
import os
|
||||
import stat
|
||||
import tempfile
|
||||
|
||||
open("filepath") # $ getAPathArgument="filepath"
|
||||
open(file="filepath") # $ getAPathArgument="filepath"
|
||||
open("file") # $ getAPathArgument="file"
|
||||
open(file="file") # $ getAPathArgument="file"
|
||||
|
||||
o = open
|
||||
|
||||
o("filepath") # $ getAPathArgument="filepath"
|
||||
o(file="filepath") # $ getAPathArgument="filepath"
|
||||
o("file") # $ getAPathArgument="file"
|
||||
o(file="file") # $ getAPathArgument="file"
|
||||
|
||||
|
||||
builtins.open("filepath") # $ getAPathArgument="filepath"
|
||||
builtins.open(file="filepath") # $ getAPathArgument="filepath"
|
||||
builtins.open("file") # $ getAPathArgument="file"
|
||||
builtins.open(file="file") # $ getAPathArgument="file"
|
||||
|
||||
|
||||
io.open("filepath") # $ getAPathArgument="filepath"
|
||||
io.open(file="filepath") # $ getAPathArgument="filepath"
|
||||
io.open("file") # $ getAPathArgument="file"
|
||||
io.open(file="file") # $ getAPathArgument="file"
|
||||
|
||||
f = open("path") # $ getAPathArgument="path"
|
||||
f.write("foo") # $ getAPathArgument="path" fileWriteData="foo"
|
||||
|
@ -28,22 +31,210 @@ def through_function(open_file):
|
|||
|
||||
through_function(f)
|
||||
|
||||
from os import path
|
||||
path.exists("filepath") # $ getAPathArgument="filepath"
|
||||
path.isfile("filepath") # $ getAPathArgument="filepath"
|
||||
path.isdir("filepath") # $ getAPathArgument="filepath"
|
||||
path.islink("filepath") # $ getAPathArgument="filepath"
|
||||
path.ismount("filepath") # $ getAPathArgument="filepath"
|
||||
# os.path
|
||||
os.path.exists("path") # $ getAPathArgument="path"
|
||||
os.path.exists(path="path") # $ getAPathArgument="path"
|
||||
|
||||
os.path.isfile("path") # $ getAPathArgument="path"
|
||||
os.path.isfile(path="path") # $ getAPathArgument="path"
|
||||
|
||||
os.path.isdir("s") # $ getAPathArgument="s"
|
||||
os.path.isdir(s="s") # $ getAPathArgument="s"
|
||||
|
||||
os.path.islink("path") # $ getAPathArgument="path"
|
||||
os.path.islink(path="path") # $ getAPathArgument="path"
|
||||
|
||||
os.path.ismount("path") # $ getAPathArgument="path"
|
||||
os.path.ismount(path="path") # $ getAPathArgument="path"
|
||||
|
||||
# actual os.path implementations
|
||||
import posixpath
|
||||
import ntpath
|
||||
import genericpath
|
||||
|
||||
posixpath.exists("filepath") # $ getAPathArgument="filepath"
|
||||
ntpath.exists("filepath") # $ getAPathArgument="filepath"
|
||||
genericpath.exists("filepath") # $ getAPathArgument="filepath"
|
||||
posixpath.exists("path") # $ getAPathArgument="path"
|
||||
posixpath.exists(path="path") # $ getAPathArgument="path"
|
||||
|
||||
import os
|
||||
ntpath.exists("path") # $ getAPathArgument="path"
|
||||
ntpath.exists(path="path") # $ getAPathArgument="path"
|
||||
|
||||
os.stat("filepath") # $ getAPathArgument="filepath"
|
||||
os.stat(path="filepath") # $ getAPathArgument="filepath"
|
||||
genericpath.exists("path") # $ getAPathArgument="path"
|
||||
genericpath.exists(path="path") # $ getAPathArgument="path"
|
||||
|
||||
# os
|
||||
|
||||
def test_fsencode_fsdecode():
|
||||
# notice that this does not make a file system access, but performs encoding/decoding.
|
||||
os.fsencode("filename") # $ encodeInput="filename" encodeOutput=os.fsencode(..) encodeFormat=filesystem
|
||||
os.fsencode(filename="filename") # $ encodeInput="filename" encodeOutput=os.fsencode(..) encodeFormat=filesystem
|
||||
|
||||
os.fsdecode("filename") # $ decodeInput="filename" decodeOutput=os.fsdecode(..) decodeFormat=filesystem
|
||||
os.fsdecode(filename="filename") # $ decodeInput="filename" decodeOutput=os.fsdecode(..) decodeFormat=filesystem
|
||||
|
||||
def test_fspath():
|
||||
# notice that this does not make a file system access, but returns the path
|
||||
# representation of a path-like object.
|
||||
|
||||
ensure_tainted(
|
||||
TAINTED_STRING, # $ tainted
|
||||
os.fspath(TAINTED_STRING), # $ tainted
|
||||
os.fspath(path=TAINTED_STRING), # $ tainted
|
||||
)
|
||||
|
||||
os.open("path", os.O_RDONLY) # $ getAPathArgument="path"
|
||||
os.open(path="path", flags=os.O_RDONLY) # $ getAPathArgument="path"
|
||||
|
||||
os.access("path", os.R_OK) # $ getAPathArgument="path"
|
||||
os.access(path="path", mode=os.R_OK) # $ getAPathArgument="path"
|
||||
|
||||
os.chdir("path") # $ getAPathArgument="path"
|
||||
os.chdir(path="path") # $ getAPathArgument="path"
|
||||
|
||||
os.chflags("path", stat.UF_NODUMP) # $ getAPathArgument="path"
|
||||
os.chflags(path="path", flags=stat.UF_NODUMP) # $ getAPathArgument="path"
|
||||
|
||||
os.chmod("path", 0o700) # $ getAPathArgument="path"
|
||||
os.chmod(path="path", mode=0o700) # $ getAPathArgument="path"
|
||||
|
||||
os.chown("path", -1, -1) # $ getAPathArgument="path"
|
||||
os.chown(path="path", uid=-1, gid=-1) # $ getAPathArgument="path"
|
||||
|
||||
# unix only
|
||||
os.chroot("path") # $ getAPathArgument="path"
|
||||
os.chroot(path="path") # $ getAPathArgument="path"
|
||||
|
||||
# unix only
|
||||
os.lchflags("path", stat.UF_NODUMP) # $ getAPathArgument="path"
|
||||
os.lchflags(path="path", flags=stat.UF_NODUMP) # $ getAPathArgument="path"
|
||||
|
||||
# unix only
|
||||
os.lchmod("path", 0o700) # $ getAPathArgument="path"
|
||||
os.lchmod(path="path", mode=0o700) # $ getAPathArgument="path"
|
||||
|
||||
# unix only
|
||||
os.lchown("path", -1, -1) # $ getAPathArgument="path"
|
||||
os.lchown(path="path", uid=-1, gid=-1) # $ getAPathArgument="path"
|
||||
|
||||
os.link("src", "dst") # $ getAPathArgument="src" getAPathArgument="dst"
|
||||
os.link(src="src", dst="dst") # $ getAPathArgument="src" getAPathArgument="dst"
|
||||
|
||||
os.listdir("path") # $ getAPathArgument="path"
|
||||
os.listdir(path="path") # $ getAPathArgument="path"
|
||||
|
||||
os.lstat("path") # $ getAPathArgument="path"
|
||||
os.lstat(path="path") # $ getAPathArgument="path"
|
||||
|
||||
os.mkdir("path") # $ getAPathArgument="path"
|
||||
os.mkdir(path="path") # $ getAPathArgument="path"
|
||||
|
||||
os.makedirs("name") # $ getAPathArgument="name"
|
||||
os.makedirs(name="name") # $ getAPathArgument="name"
|
||||
|
||||
os.mkfifo("path") # $ getAPathArgument="path"
|
||||
os.mkfifo(path="path") # $ getAPathArgument="path"
|
||||
|
||||
os.mknod("path") # $ getAPathArgument="path"
|
||||
os.mknod(path="path") # $ getAPathArgument="path"
|
||||
|
||||
os.pathconf("path", "name") # $ getAPathArgument="path"
|
||||
os.pathconf(path="path", name="name") # $ getAPathArgument="path"
|
||||
|
||||
os.readlink("path") # $ getAPathArgument="path"
|
||||
os.readlink(path="path") # $ getAPathArgument="path"
|
||||
|
||||
os.remove("path") # $ getAPathArgument="path"
|
||||
os.remove(path="path") # $ getAPathArgument="path"
|
||||
|
||||
os.removedirs("name") # $ getAPathArgument="name"
|
||||
os.removedirs(name="name") # $ getAPathArgument="name"
|
||||
|
||||
os.rename("src", "dst") # $ getAPathArgument="src" getAPathArgument="dst"
|
||||
os.rename(src="src", dst="dst") # $ getAPathArgument="src" getAPathArgument="dst"
|
||||
|
||||
os.renames("old", "new") # $ getAPathArgument="old" getAPathArgument="new"
|
||||
os.renames(old="old", new="new") # $ getAPathArgument="old" getAPathArgument="new"
|
||||
|
||||
os.replace("src", "dst") # $ getAPathArgument="src" getAPathArgument="dst"
|
||||
os.replace(src="src", dst="dst") # $ getAPathArgument="src" getAPathArgument="dst"
|
||||
|
||||
os.rmdir("path") # $ getAPathArgument="path"
|
||||
os.rmdir(path="path") # $ getAPathArgument="path"
|
||||
|
||||
os.scandir("path") # $ getAPathArgument="path"
|
||||
os.scandir(path="path") # $ getAPathArgument="path"
|
||||
|
||||
os.stat("path") # $ getAPathArgument="path"
|
||||
os.stat(path="path") # $ getAPathArgument="path"
|
||||
|
||||
os.statvfs("path") # $ getAPathArgument="path"
|
||||
os.statvfs(path="path") # $ getAPathArgument="path"
|
||||
|
||||
os.symlink("src", "dst") # $ getAPathArgument="src" getAPathArgument="dst"
|
||||
os.symlink(src="src", dst="dst") # $ getAPathArgument="src" getAPathArgument="dst"
|
||||
|
||||
os.truncate("path", 42) # $ getAPathArgument="path"
|
||||
os.truncate(path="path", length=42) # $ getAPathArgument="path"
|
||||
|
||||
os.unlink("path") # $ getAPathArgument="path"
|
||||
os.unlink(path="path") # $ getAPathArgument="path"
|
||||
|
||||
os.utime("path") # $ getAPathArgument="path"
|
||||
os.utime(path="path") # $ getAPathArgument="path"
|
||||
|
||||
os.walk("top") # $ getAPathArgument="top"
|
||||
os.walk(top="top") # $ getAPathArgument="top"
|
||||
|
||||
os.fwalk("top") # $ getAPathArgument="top"
|
||||
os.fwalk(top="top") # $ getAPathArgument="top"
|
||||
|
||||
# Linux only
|
||||
os.getxattr("path", "attribute") # $ getAPathArgument="path"
|
||||
os.getxattr(path="path", attribute="attribute") # $ getAPathArgument="path"
|
||||
|
||||
# Linux only
|
||||
os.listxattr("path") # $ getAPathArgument="path"
|
||||
os.listxattr(path="path") # $ getAPathArgument="path"
|
||||
|
||||
# Linux only
|
||||
os.removexattr("path", "attribute") # $ getAPathArgument="path"
|
||||
os.removexattr(path="path", attribute="attribute") # $ getAPathArgument="path"
|
||||
|
||||
# Linux only
|
||||
os.setxattr("path", "attribute", "value") # $ getAPathArgument="path"
|
||||
os.setxattr(path="path", attribute="attribute", value="value") # $ getAPathArgument="path"
|
||||
|
||||
# Windows only
|
||||
os.add_dll_directory("path") # $ getAPathArgument="path"
|
||||
os.add_dll_directory(path="path") # $ getAPathArgument="path"
|
||||
|
||||
# for `os.exec*`, `os.spawn*`, and `os.posix_spawn*` functions, see the
|
||||
# `SystemCommandExecution.py` file.
|
||||
|
||||
# Windows only
|
||||
os.startfile("path") # $ getAPathArgument="path"
|
||||
os.startfile(path="path") # $ getAPathArgument="path"
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# tempfile
|
||||
# ------------------------------------------------------------------------------
|
||||
|
||||
# _mkstemp_inner does `_os.path.join(dir, pre + name + suf)`
|
||||
|
||||
tempfile.mkstemp("suffix", "prefix", "dir") # $ getAPathArgument="suffix" getAPathArgument="prefix" getAPathArgument="dir"
|
||||
tempfile.mkstemp(suffix="suffix", prefix="prefix", dir="dir") # $ getAPathArgument="suffix" getAPathArgument="prefix" getAPathArgument="dir"
|
||||
|
||||
tempfile.NamedTemporaryFile('w+b', -1, None, None, "suffix", "prefix", "dir") # $ getAPathArgument="suffix" getAPathArgument="prefix" getAPathArgument="dir"
|
||||
tempfile.NamedTemporaryFile(suffix="suffix", prefix="prefix", dir="dir") # $ getAPathArgument="suffix" getAPathArgument="prefix" getAPathArgument="dir"
|
||||
|
||||
tempfile.TemporaryFile('w+b', -1, None, None, "suffix", "prefix", "dir") # $ getAPathArgument="suffix" getAPathArgument="prefix" getAPathArgument="dir"
|
||||
tempfile.TemporaryFile(suffix="suffix", prefix="prefix", dir="dir") # $ getAPathArgument="suffix" getAPathArgument="prefix" getAPathArgument="dir"
|
||||
|
||||
tempfile.SpooledTemporaryFile(0, 'w+b', -1, None, None, "suffix", "prefix", "dir") # $ getAPathArgument="suffix" getAPathArgument="prefix" getAPathArgument="dir"
|
||||
tempfile.SpooledTemporaryFile(suffix="suffix", prefix="prefix", dir="dir") # $ getAPathArgument="suffix" getAPathArgument="prefix" getAPathArgument="dir"
|
||||
|
||||
# mkdtemp does `_os.path.join(dir, prefix + name + suffix)`
|
||||
tempfile.mkdtemp("suffix", "prefix", "dir") # $ getAPathArgument="suffix" getAPathArgument="prefix" getAPathArgument="dir"
|
||||
tempfile.mkdtemp(suffix="suffix", prefix="prefix", dir="dir") # $ getAPathArgument="suffix" getAPathArgument="prefix" getAPathArgument="dir"
|
||||
|
||||
tempfile.TemporaryDirectory("suffix", "prefix", "dir") # $ getAPathArgument="suffix" getAPathArgument="prefix" getAPathArgument="dir"
|
||||
tempfile.TemporaryDirectory(suffix="suffix", prefix="prefix", dir="dir") # $ getAPathArgument="suffix" getAPathArgument="prefix" getAPathArgument="dir"
|
||||
|
|
|
@ -34,33 +34,52 @@ def os_members():
|
|||
# VS Code extension will ignore rest of program if encountering one of these, which we
|
||||
# don't want. We could use `if False`, but just to be 100% sure we don't do anything too
|
||||
# clever in our analysis that discards that code, I used `if UNKNOWN` instead
|
||||
#
|
||||
# below, `path` is an relative/absolute path, for the `p` variants this could also be
|
||||
# the name of a executable, which will be looked up in the PATH environment variable,
|
||||
# which we call `file` to highlight this difference.
|
||||
#
|
||||
# These are also modeled as FileSystemAccess, although they are not super relevant for
|
||||
# the path-injection query -- a user being able to control which program is executed
|
||||
# doesn't sound safe even if that is restricted to be within a certain directory.
|
||||
if UNKNOWN:
|
||||
env = {"FOO": "foo"}
|
||||
os.execl("executable", "<progname>", "arg0") # $getCommand="executable"
|
||||
os.execle("executable", "<progname>", "arg0", env) # $getCommand="executable"
|
||||
os.execlp("executable", "<progname>", "arg0") # $getCommand="executable"
|
||||
os.execlpe("executable", "<progname>", "arg0", env) # $getCommand="executable"
|
||||
os.execv("executable", ["<progname>", "arg0"]) # $getCommand="executable"
|
||||
os.execve("executable", ["<progname>", "arg0"], env) # $getCommand="executable"
|
||||
os.execvp("executable", ["<progname>", "arg0"]) # $getCommand="executable"
|
||||
os.execvpe("executable", ["<progname>", "arg0"], env) # $getCommand="executable"
|
||||
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, "executable", "<progname>", "arg0") # $getCommand="executable"
|
||||
os.spawnle(os.P_WAIT, "executable", "<progname>", "arg0", env) # $getCommand="executable"
|
||||
os.spawnlp(os.P_WAIT, "executable", "<progname>", "arg0") # $getCommand="executable"
|
||||
os.spawnlpe(os.P_WAIT, "executable", "<progname>", "arg0", env) # $getCommand="executable"
|
||||
os.spawnv(os.P_WAIT, "executable", ["<progname>", "arg0"]) # $getCommand="executable"
|
||||
os.spawnve(os.P_WAIT, "executable", ["<progname>", "arg0"], env) # $getCommand="executable"
|
||||
os.spawnvp(os.P_WAIT, "executable", ["<progname>", "arg0"]) # $getCommand="executable"
|
||||
os.spawnvpe(os.P_WAIT, "executable", ["<progname>", "arg0"], env) # $getCommand="executable"
|
||||
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"
|
||||
|
||||
# Added in Python 3.8
|
||||
os.posix_spawn("executable", ["<progname>", "arg0"], env) # $getCommand="executable"
|
||||
os.posix_spawnp("executable", ["<progname>", "arg0"], env) # $getCommand="executable"
|
||||
# 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" 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" 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" getAPathArgument="path"
|
||||
os.posix_spawnp(path="path", argv=["<progname>", "arg0"], env=env) # $ getCommand="path" getAPathArgument="path"
|
||||
|
||||
########################################
|
||||
|
||||
|
@ -107,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"
|
||||
|
||||
|
||||
########################################
|
||||
|
|
Загрузка…
Ссылка в новой задаче