Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ private import semmle.python.Concepts
private import semmle.python.dataflow.new.RemoteFlowSources
private import semmle.python.dataflow.new.BarrierGuards
private import semmle.python.frameworks.data.ModelsAsData
private import semmle.python.ApiGraphs

/**
* Provides default sources, sinks and sanitizers for detecting
Expand Down Expand Up @@ -102,4 +103,16 @@ module CommandInjection {
class SanitizerFromModel extends Sanitizer {
SanitizerFromModel() { ModelOutput::barrierNode(this, "command-injection") }
}

/**
* A call to `shlex.quote` or `pipes.quote`, considered as a sanitizer.
* These functions properly escape shell metacharacters, preventing command injection.
*/
class ShellQuoteSanitizer extends Sanitizer {
ShellQuoteSanitizer() {
this = API::moduleImport("shlex").getMember("quote").getACall()
or
this = API::moduleImport("pipes").getMember("quote").getACall()
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import os
import shlex
from flask import Flask, request # $ Source

app = Flask(__name__)


@app.route("/run")
def run_command_safe():
"""shlex.quote properly escapes shell metacharacters - safe from injection."""
filename = request.args.get("filename", "")
safe_filename = shlex.quote(filename)
os.system("cat " + safe_filename) # Safe - shlex.quote sanitizes


@app.route("/run_unsafe")
def run_command_unsafe():
"""Direct concatenation without quoting is vulnerable."""
filename = request.args.get("filename", "")
os.system("cat " + filename) # $ Alert


@app.route("/run_pipes")
def run_command_pipes_quote():
"""pipes.quote is the Python 2 equivalent of shlex.quote."""
import pipes
filename = request.args.get("filename", "")
safe_filename = pipes.quote(filename)
os.system("cat " + safe_filename) # Safe - pipes.quote sanitizes
Loading