Add shutil module path injection sinks

This commit is contained in:
haby0
2021-12-20 16:09:06 +08:00
parent ed006d7283
commit fed1d88268
2 changed files with 125 additions and 0 deletions

View File

@@ -2942,6 +2942,97 @@ private module StdlibPrivate {
]
}
}
// ---------------------------------------------------------------------------
// shutil
// ---------------------------------------------------------------------------
/** Gets a reference to the `shutil` module. */
private API::Node shutil() { result = API::moduleImport("shutil") }
/**
* A call to the `shutil.rmtree` function.
*
* See https://docs.python.org/3/library/shutil.html#shutil.rmtree
*/
private class ShutilRmtreeCall extends FileSystemAccess::Range, DataFlow::CallCfgNode {
ShutilRmtreeCall() { this = shutil().getMember("rmtree").getACall() }
override DataFlow::Node getAPathArgument() {
result in [this.getArg(0), this.getArgByName("path")]
}
}
/**
* The `shutil` module provides methods to copy, move files or copy file attributes.
* See:
* - https://docs.python.org/3/library/shutil.html#shutil.copyfile
* - https://docs.python.org/3/library/shutil.html#shutil.copymode
* - https://docs.python.org/3/library/shutil.html#shutil.copystat
* - https://docs.python.org/3/library/shutil.html#shutil.copy
* - https://docs.python.org/3/library/shutil.html#shutil.copy2
* - https://docs.python.org/3/library/shutil.html#shutil.copytree
* - https://docs.python.org/3/library/shutil.html#shutil.move
*/
private class ShutilCopyCall extends FileSystemAccess::Range, DataFlow::CallCfgNode {
ShutilCopyCall() {
this =
shutil()
.getMember([
// these are used to copy files
"copyfile", "copy", "copy2", "copytree",
// these are used to move files
"move",
// these are used to copy some attributes of the file
"copymode", "copystat"
])
.getACall()
}
override DataFlow::Node getAPathArgument() {
result in [this.getArg(0), this.getArgByName("src"), this.getArg(1), this.getArgByName("dst")]
}
}
/**
* A call to the `shutil.copyfileobj` function.
*
* See https://docs.python.org/3/library/shutil.html#shutil.copyfileobj
*/
private class ShutilCopyfileobjCall extends FileSystemAccess::Range, DataFlow::CallCfgNode {
ShutilCopyfileobjCall() { this = shutil().getMember("copyfileobj").getACall() }
override DataFlow::Node getAPathArgument() {
result in [
this.getArg(0), this.getArgByName("fsrc"), this.getArg(1), this.getArgByName("fdst")
]
}
}
/**
* A call to the `shutil.disk_usage` function.
*
* See https://docs.python.org/3/library/shutil.html#shutil.disk_usage
*/
private class ShutilDiskUsageCall extends FileSystemAccess::Range, DataFlow::CallCfgNode {
ShutilDiskUsageCall() { this = shutil().getMember("disk_usage").getACall() }
override DataFlow::Node getAPathArgument() {
result in [this.getArg(0), this.getArgByName("path")]
}
}
/**
* A call to the `shutil.chown` function.
*
* See https://docs.python.org/3/library/shutil.html#shutil.chown
*/
private class ShutilChownCall extends FileSystemAccess::Range, DataFlow::CallCfgNode {
ShutilChownCall() { this = shutil().getMember("chown").getACall() }
override DataFlow::Node getAPathArgument() {
result in [this.getArg(0), this.getArgByName("path")]
}
}
}
// ---------------------------------------------------------------------------

View File

@@ -0,0 +1,34 @@
import shutil
from flask import Flask, request
app = Flask(__name__)
STATIC_DIR = "/server/static/"
@app.route("/shutil-path1")
def path_injection1():
dir = request.args.get('dir', '')
shutil.rmtree(dir) # NOT OK
@app.route("/shutil-path2")
def path_injection2():
path1 = request.args.get('path1', '')
path2 = request.args.get('path2', '')
shutil.copyfile(path1, path2) # NOT OK
@app.route("/shutil-path3")
def path_injection3():
path1 = request.args.get('path1', '')
path2 = request.args.get('path2', '')
shutil.copy(path1, path2) # NOT OK
@app.route("/shutil-path4")
def path_injection4():
path1 = request.args.get('path1', '')
path2 = request.args.get('path2', '')
shutil.move(path1, path2) # NOT OK
@app.route("/shutil-path4")
def path_injection5():
path1 = request.args.get('path1', '')
path2 = request.args.get('path2', '')
shutil.copymode(path1, path2) # NOT OK