mirror of
https://github.com/github/codeql.git
synced 2025-12-16 16:53:25 +01:00
Merge pull request #528 from taus-semmle/python-flask-debug
Python: Implement check for flask debug mode.
This commit is contained in:
@@ -56,6 +56,7 @@ A new predicate `Stmt.getAnEntryNode()` has been added to make it easier to writ
|
||||
|
||||
| **Query** | **Tags** | **Purpose** |
|
||||
|-----------------------------|-----------|--------------------------------------------------------------------|
|
||||
| Flask app is run in debug mode (`py/flask-debug`) | security, external/cwe/cwe-215, external/cwe/cwe-489 | Finds instances where a Flask application is run in debug mode. Enabled on LGTM by default. |
|
||||
| Information exposure through an exception (`py/stack-trace-exposure`) | security, external/cwe/cwe-209, external/cwe/cwe-497 | Finds instances where information about an exception may be leaked to an external user. Enabled on LGTM by default. |
|
||||
| Request without certificate validation (`py/request-without-cert-validation`) | security, external/cwe/cwe-295 | Finds requests where certificate verification has been explicitly turned off, possibly allowing man-in-the-middle attacks. Not enabled on LGTM by default. |
|
||||
|
||||
|
||||
9
python/ql/src/Security/CWE-215/FlaskDebug.py
Normal file
9
python/ql/src/Security/CWE-215/FlaskDebug.py
Normal file
@@ -0,0 +1,9 @@
|
||||
from flask import Flask
|
||||
|
||||
app = Flask(__name__)
|
||||
|
||||
@app.route('/crash')
|
||||
def main():
|
||||
raise Exception()
|
||||
|
||||
app.run(debug=True)
|
||||
39
python/ql/src/Security/CWE-215/FlaskDebug.qhelp
Normal file
39
python/ql/src/Security/CWE-215/FlaskDebug.qhelp
Normal file
@@ -0,0 +1,39 @@
|
||||
<!DOCTYPE qhelp PUBLIC
|
||||
"-//Semmle//qhelp//EN"
|
||||
"qhelp.dtd">
|
||||
<qhelp>
|
||||
<overview>
|
||||
<p>
|
||||
Running a Flask application with debug mode enabled may allow an
|
||||
attacker to gain access through the Werkzeug debugger.
|
||||
</p>
|
||||
|
||||
</overview>
|
||||
<recommendation>
|
||||
|
||||
<p>
|
||||
Ensure that Flask applications that are run in a production
|
||||
environment have debugging disabled.
|
||||
</p>
|
||||
|
||||
</recommendation>
|
||||
<example>
|
||||
|
||||
<p>
|
||||
Running the following code starts a Flask webserver that has
|
||||
debugging enabled. By visiting <code>/crash</code>, it is possible
|
||||
to gain access to the debugger, and run arbitrary code through the
|
||||
interactive debugger.
|
||||
</p>
|
||||
|
||||
<sample src="FlaskDebug.py" />
|
||||
|
||||
</example>
|
||||
|
||||
<references>
|
||||
<li>Flask Quickstart Documentation: <a href="http://flask.pocoo.org/docs/1.0/quickstart/#debug-mode">Debug Mode</a>.</li>
|
||||
<li>Werkzeug Documentation: <a href="http://werkzeug.pocoo.org/docs/0.14/debug/">Debugging Applications</a>.</li>
|
||||
</references>
|
||||
|
||||
</qhelp>
|
||||
|
||||
23
python/ql/src/Security/CWE-215/FlaskDebug.ql
Normal file
23
python/ql/src/Security/CWE-215/FlaskDebug.ql
Normal file
@@ -0,0 +1,23 @@
|
||||
/**
|
||||
* @name Flask app is run in debug mode
|
||||
* @description Running a Flask app in debug mode may allow an attacker to run arbitrary code through the Werkzeug debugger.
|
||||
* @kind problem
|
||||
* @problem.severity error
|
||||
* @precision high
|
||||
* @id py/flask-debug
|
||||
* @tags security
|
||||
* external/cwe/cwe-215
|
||||
* external/cwe/cwe-489
|
||||
*/
|
||||
|
||||
import python
|
||||
|
||||
import semmle.python.web.flask.General
|
||||
|
||||
|
||||
from CallNode call, Object isTrue
|
||||
where
|
||||
call = theFlaskClass().declaredAttribute("run").(FunctionObject).getACall() and
|
||||
call.getArgByName("debug").refersTo(isTrue) and
|
||||
isTrue.booleanValue() = true
|
||||
select call, "A Flask app appears to be run in debug mode. This may allow an attacker to run arbitrary code through the debugger."
|
||||
@@ -0,0 +1,3 @@
|
||||
| test.py:10:1:10:19 | ControlFlowNode for Attribute() | A Flask app appears to be run in debug mode. This may allow an attacker to run arbitrary code through the debugger. |
|
||||
| test.py:25:1:25:20 | ControlFlowNode for Attribute() | A Flask app appears to be run in debug mode. This may allow an attacker to run arbitrary code through the debugger. |
|
||||
| test.py:29:1:29:20 | ControlFlowNode for Attribute() | A Flask app appears to be run in debug mode. This may allow an attacker to run arbitrary code through the debugger. |
|
||||
@@ -0,0 +1 @@
|
||||
Security/CWE-215/FlaskDebug.ql
|
||||
1
python/ql/test/query-tests/Security/CWE-215/options
Normal file
1
python/ql/test/query-tests/Security/CWE-215/options
Normal file
@@ -0,0 +1 @@
|
||||
semmle-extractor-options: --max-import-depth=2 -p ../lib
|
||||
37
python/ql/test/query-tests/Security/CWE-215/test.py
Normal file
37
python/ql/test/query-tests/Security/CWE-215/test.py
Normal file
@@ -0,0 +1,37 @@
|
||||
from flask import Flask
|
||||
|
||||
app = Flask(__name__)
|
||||
|
||||
@app.route('/crash')
|
||||
def main():
|
||||
raise Exception()
|
||||
|
||||
# bad
|
||||
app.run(debug=True)
|
||||
|
||||
# okay
|
||||
app.run()
|
||||
app.run(debug=False)
|
||||
|
||||
# also okay
|
||||
run(debug=True)
|
||||
|
||||
app.notrun(debug=True)
|
||||
|
||||
# a slightly more involved example using flow and truthy values
|
||||
|
||||
DEBUG = True
|
||||
|
||||
app.run(debug=DEBUG)
|
||||
|
||||
DEBUG = 1
|
||||
|
||||
app.run(debug=DEBUG)
|
||||
|
||||
if False:
|
||||
app.run(debug=True)
|
||||
|
||||
# false negative
|
||||
|
||||
runapp = app.run
|
||||
runapp(debug=True)
|
||||
@@ -1,7 +1,7 @@
|
||||
|
||||
|
||||
class Flask(object):
|
||||
pass
|
||||
def run(self, *args, **kwargs): pass
|
||||
|
||||
from .globals import request
|
||||
|
||||
|
||||
Reference in New Issue
Block a user