Python: Add redirects to bottle framework support.

This commit is contained in:
Mark Shannon
2019-02-04 15:04:25 +00:00
parent d514fc543d
commit aab0a243dc
8 changed files with 67 additions and 1 deletions

View File

@@ -35,3 +35,5 @@ Removes false positives seen when using Python 3.6, but not when using earlier v
## Changes to QL libraries
* Added support for the `dill` pickle library.
* Added support for the bottle web framework.

View File

@@ -6,3 +6,4 @@ import semmle.python.web.django.Redirect
import semmle.python.web.flask.Redirect
import semmle.python.web.tornado.Redirect
import semmle.python.web.pyramid.Redirect
import semmle.python.web.bottle.Redirect

View File

@@ -0,0 +1,35 @@
/** Provides class representing the `bottle.redirect` function.
* This module is intended to be imported into a taint-tracking query
* to extend `TaintSink`.
*/
import python
import semmle.python.security.TaintTracking
import semmle.python.security.strings.Basic
import semmle.python.web.bottle.General
FunctionObject bottle_redirect() {
result = theBottleModule().getAttribute("redirect")
}
/**
* Represents an argument to the `bottle.redirect` function.
*/
class BottleRedirect extends TaintSink {
override string toString() {
result = "bottle.redirect"
}
BottleRedirect() {
exists(CallNode call |
bottle_redirect().getACall() = call and
this = call.getAnArg()
)
}
override predicate sinks(TaintKind kind) {
kind instanceof StringKind
}
}

View File

@@ -1,3 +1,6 @@
| /args | test.py:31:1:31:14 | Function unsafe2 |
| /bye/<name> | test.py:12:1:12:25 | Function bye |
| /hello/<name> | test.py:8:1:8:27 | Function hello |
| /other | test.py:17:1:17:12 | Function other |
| /wrong/<where> | test.py:27:1:27:31 | Function unsafe |
| /wrong/url | test.py:23:1:23:11 | Function safe |

View File

@@ -5,3 +5,5 @@
| test.py:8 | name | externally controlled string |
| test.py:12 | name | externally controlled string |
| test.py:18 | request | bottle.request |
| test.py:27 | where | externally controlled string |
| test.py:32 | request | bottle.request |

View File

@@ -1,5 +1,6 @@
| ../../../query-tests/Security/lib/bottle.py:64 | LocalRequest() | bottle.request |
| ../../../query-tests/Security/lib/bottle.py:64 | request | bottle.request |
| ../../../query-tests/Security/lib/bottle.py:68 | url | externally controlled string |
| test.py:3 | ImportMember | bottle.request |
| test.py:3 | request | bottle.request |
| test.py:8 | name | externally controlled string |
@@ -13,3 +14,8 @@
| test.py:18 | request | bottle.request |
| test.py:19 | BinaryExpr | externally controlled string |
| test.py:19 | name | externally controlled string |
| test.py:27 | where | externally controlled string |
| test.py:28 | where | externally controlled string |
| test.py:32 | Attribute | bottle.FormsDict |
| test.py:32 | Attribute | externally controlled string |
| test.py:32 | request | bottle.request |

View File

@@ -1,6 +1,6 @@
from bottle import Bottle, route, request
from bottle import Bottle, route, request, redirect
app = Bottle()
@@ -17,3 +17,16 @@ def bye(name = "World!"):
def other():
name = request.cookies.username
return "User name is " + name
@route('/wrong/url')
def safe():
redirect("/right/url")
@route('/wrong/<where>')
def unsafe(where="/right/url"):
redirect(where)
@route('/args')
def unsafe2():
redirect(request.query.where, code)

View File

@@ -64,3 +64,7 @@ class LocalResponse(LocalProxy):
request = LocalRequest()
response = LocalResponse()
def redirect(url, code=None):
pass