зеркало из https://github.com/github/codeql.git
Python: Autoformat flask library
This commit is contained in:
Родитель
a9d43a2c49
Коммит
002190f8db
|
@ -2,20 +2,15 @@ import python
|
|||
import semmle.python.web.Http
|
||||
|
||||
/** The flask app class */
|
||||
ClassValue theFlaskClass() {
|
||||
result = Value::named("flask.Flask")
|
||||
}
|
||||
ClassValue theFlaskClass() { result = Value::named("flask.Flask") }
|
||||
|
||||
/** The flask MethodView class */
|
||||
ClassValue theFlaskMethodViewClass() {
|
||||
result = Value::named("flask.views.MethodView")
|
||||
}
|
||||
ClassValue theFlaskMethodViewClass() { result = Value::named("flask.views.MethodView") }
|
||||
|
||||
ClassValue theFlaskReponseClass() {
|
||||
result = Value::named("flask.Response")
|
||||
}
|
||||
ClassValue theFlaskReponseClass() { result = Value::named("flask.Response") }
|
||||
|
||||
/** Holds if `route` is routed to `func`
|
||||
/**
|
||||
* Holds if `route` is routed to `func`
|
||||
* by decorating `func` with `app.route(route)`
|
||||
*/
|
||||
predicate app_route(ControlFlowNode route, Function func) {
|
||||
|
@ -31,7 +26,8 @@ predicate app_route(ControlFlowNode route, Function func) {
|
|||
private predicate add_url_rule_call(ControlFlowNode regex, ControlFlowNode callable) {
|
||||
exists(CallNode call |
|
||||
call.getFunction().(AttrNode).getObject("add_url_rule").pointsTo().getClass() = theFlaskClass() and
|
||||
regex = call.getArg(0) |
|
||||
regex = call.getArg(0)
|
||||
|
|
||||
callable = call.getArg(2) or
|
||||
callable = call.getArgByName("view_func")
|
||||
)
|
||||
|
@ -39,21 +35,19 @@ private predicate add_url_rule_call(ControlFlowNode regex, ControlFlowNode calla
|
|||
|
||||
/** Holds if urls matching `regex` are routed to `func` */
|
||||
predicate add_url_rule(ControlFlowNode regex, Function func) {
|
||||
exists(ControlFlowNode callable |
|
||||
add_url_rule_call(regex, callable)
|
||||
|
|
||||
exists(ControlFlowNode callable | add_url_rule_call(regex, callable) |
|
||||
exists(PythonFunctionValue f | f.getScope() = func and callable.pointsTo(f))
|
||||
or
|
||||
/* MethodView.as_view() */
|
||||
exists(MethodViewClass view_cls |
|
||||
view_cls.asTaint().taints(callable) |
|
||||
exists(MethodViewClass view_cls | view_cls.asTaint().taints(callable) |
|
||||
func = view_cls.lookup(httpVerbLower()).(FunctionValue).getScope()
|
||||
)
|
||||
/* TODO: -- Handle Views that aren't MethodViews */
|
||||
)
|
||||
}
|
||||
|
||||
/** Holds if urls matching `regex` are routed to `func` using
|
||||
/**
|
||||
* Holds if urls matching `regex` are routed to `func` using
|
||||
* any of flask's routing mechanisms.
|
||||
*/
|
||||
predicate flask_routing(ControlFlowNode regex, Function func) {
|
||||
|
@ -64,32 +58,21 @@ predicate flask_routing(ControlFlowNode regex, Function func) {
|
|||
|
||||
/** A class that extends flask.views.MethodView */
|
||||
private class MethodViewClass extends ClassValue {
|
||||
|
||||
MethodViewClass() {
|
||||
this.getASuperType() = theFlaskMethodViewClass()
|
||||
}
|
||||
MethodViewClass() { this.getASuperType() = theFlaskMethodViewClass() }
|
||||
|
||||
/* As we are restricted to strings for taint kinds, we need to map these classes to strings. */
|
||||
string taintString() {
|
||||
result = "flask/" + this.getQualifiedName() + ".as.view"
|
||||
}
|
||||
string taintString() { result = "flask/" + this.getQualifiedName() + ".as.view" }
|
||||
|
||||
/* As we are restricted to strings for taint kinds, we need to map these classes to strings. */
|
||||
TaintKind asTaint() {
|
||||
result = this.taintString()
|
||||
}
|
||||
TaintKind asTaint() { result = this.taintString() }
|
||||
}
|
||||
|
||||
private class MethodViewTaint extends TaintKind {
|
||||
|
||||
MethodViewTaint() {
|
||||
any(MethodViewClass cls).taintString() = this
|
||||
}
|
||||
MethodViewTaint() { any(MethodViewClass cls).taintString() = this }
|
||||
}
|
||||
|
||||
/** A source of method view "taint"s. */
|
||||
private class AsView extends TaintSource {
|
||||
|
||||
AsView() {
|
||||
exists(ClassValue view_class |
|
||||
view_class.getASuperType() = theFlaskMethodViewClass() and
|
||||
|
@ -97,9 +80,7 @@ private class AsView extends TaintSource {
|
|||
)
|
||||
}
|
||||
|
||||
override string toString() {
|
||||
result = "flask.MethodView.as_view()"
|
||||
}
|
||||
override string toString() { result = "flask.MethodView.as_view()" }
|
||||
|
||||
override predicate isSourceOf(TaintKind kind) {
|
||||
exists(MethodViewClass view_class |
|
||||
|
@ -107,12 +88,9 @@ private class AsView extends TaintSource {
|
|||
this.(CallNode).getFunction().(AttrNode).getObject("as_view").pointsTo(view_class)
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
class FlaskCookieSet extends CookieSet, CallNode {
|
||||
|
||||
FlaskCookieSet() {
|
||||
this.getFunction().(AttrNode).getObject("set_cookie").pointsTo().getClass() = theFlaskReponseClass()
|
||||
}
|
||||
|
@ -122,6 +100,4 @@ class FlaskCookieSet extends CookieSet, CallNode {
|
|||
override ControlFlowNode getKey() { result = this.getArg(0) }
|
||||
|
||||
override ControlFlowNode getValue() { result = this.getArg(1) }
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -1,25 +1,21 @@
|
|||
/** Provides class representing the `flask.redirect` function.
|
||||
/**
|
||||
* Provides class representing the `flask.redirect` function.
|
||||
* This module is intended to be imported into a taint-tracking query
|
||||
* to extend `TaintSink`.
|
||||
*/
|
||||
import python
|
||||
|
||||
import python
|
||||
import semmle.python.security.TaintTracking
|
||||
import semmle.python.security.strings.Basic
|
||||
import semmle.python.web.flask.General
|
||||
|
||||
FunctionValue flask_redirect() {
|
||||
result = Value::named("flask.redirect")
|
||||
}
|
||||
FunctionValue flask_redirect() { result = Value::named("flask.redirect") }
|
||||
|
||||
/**
|
||||
* Represents an argument to the `flask.redirect` function.
|
||||
*/
|
||||
class FlaskRedirect extends HttpRedirectTaintSink {
|
||||
|
||||
override string toString() {
|
||||
result = "flask.redirect"
|
||||
}
|
||||
override string toString() { result = "flask.redirect" }
|
||||
|
||||
FlaskRedirect() {
|
||||
exists(CallNode call |
|
||||
|
@ -27,5 +23,4 @@ class FlaskRedirect extends HttpRedirectTaintSink {
|
|||
this = call.getAnArg()
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,13 +1,9 @@
|
|||
import python
|
||||
|
||||
import semmle.python.security.TaintTracking
|
||||
import semmle.python.web.Http
|
||||
import semmle.python.web.flask.General
|
||||
|
||||
private Value theFlaskRequestObject() {
|
||||
result = Value::named("flask.request")
|
||||
|
||||
}
|
||||
private Value theFlaskRequestObject() { result = Value::named("flask.request") }
|
||||
|
||||
/** Holds if `attr` is an access of attribute `name` of the flask request object */
|
||||
private predicate flask_request_attr(AttrNode attr, string name) {
|
||||
|
@ -17,63 +13,44 @@ private predicate flask_request_attr(AttrNode attr, string name) {
|
|||
|
||||
/** Source of external data from a flask request */
|
||||
class FlaskRequestData extends HttpRequestTaintSource {
|
||||
|
||||
FlaskRequestData() {
|
||||
not this instanceof FlaskRequestArgs and
|
||||
exists(string name |
|
||||
flask_request_attr(this, name) |
|
||||
name = "path" or name = "full_path" or
|
||||
name = "base_url" or name = "url"
|
||||
exists(string name | flask_request_attr(this, name) |
|
||||
name = "path" or
|
||||
name = "full_path" or
|
||||
name = "base_url" or
|
||||
name = "url"
|
||||
)
|
||||
}
|
||||
|
||||
override predicate isSourceOf(TaintKind kind) {
|
||||
kind instanceof ExternalStringKind
|
||||
}
|
||||
|
||||
override string toString() {
|
||||
result = "flask.request"
|
||||
}
|
||||
override predicate isSourceOf(TaintKind kind) { kind instanceof ExternalStringKind }
|
||||
|
||||
override string toString() { result = "flask.request" }
|
||||
}
|
||||
|
||||
/** Source of dictionary whose values are externally controlled */
|
||||
class FlaskRequestArgs extends HttpRequestTaintSource {
|
||||
|
||||
FlaskRequestArgs() {
|
||||
exists(string attr |
|
||||
flask_request_attr(this, attr) |
|
||||
attr = "args" or attr = "form" or
|
||||
attr = "values" or attr = "files" or
|
||||
attr = "headers" or attr = "json"
|
||||
exists(string attr | flask_request_attr(this, attr) |
|
||||
attr = "args" or
|
||||
attr = "form" or
|
||||
attr = "values" or
|
||||
attr = "files" or
|
||||
attr = "headers" or
|
||||
attr = "json"
|
||||
)
|
||||
}
|
||||
|
||||
override predicate isSourceOf(TaintKind kind) {
|
||||
kind instanceof ExternalStringDictKind
|
||||
}
|
||||
|
||||
override string toString() {
|
||||
result = "flask.request.args"
|
||||
}
|
||||
override predicate isSourceOf(TaintKind kind) { kind instanceof ExternalStringDictKind }
|
||||
|
||||
override string toString() { result = "flask.request.args" }
|
||||
}
|
||||
|
||||
|
||||
/** Source of dictionary whose values are externally controlled */
|
||||
class FlaskRequestJson extends TaintSource {
|
||||
FlaskRequestJson() { flask_request_attr(this, "json") }
|
||||
|
||||
FlaskRequestJson() {
|
||||
flask_request_attr(this, "json")
|
||||
}
|
||||
|
||||
override predicate isSourceOf(TaintKind kind) {
|
||||
kind instanceof ExternalJsonKind
|
||||
}
|
||||
|
||||
override string toString() {
|
||||
result = "flask.request.json"
|
||||
}
|
||||
override predicate isSourceOf(TaintKind kind) { kind instanceof ExternalJsonKind }
|
||||
|
||||
override string toString() { result = "flask.request.json" }
|
||||
}
|
||||
|
||||
|
|
|
@ -1,15 +1,13 @@
|
|||
import python
|
||||
|
||||
|
||||
import semmle.python.security.TaintTracking
|
||||
import semmle.python.security.strings.Basic
|
||||
|
||||
import semmle.python.web.flask.General
|
||||
|
||||
/** A flask response, which is vulnerable to any sort of
|
||||
* http response malice. */
|
||||
/**
|
||||
* A flask response, which is vulnerable to any sort of
|
||||
* http response malice.
|
||||
*/
|
||||
class FlaskRoutedResponse extends HttpResponseTaintSink {
|
||||
|
||||
FlaskRoutedResponse() {
|
||||
exists(PyFunctionObject response |
|
||||
flask_routing(_, response.getFunction()) and
|
||||
|
@ -17,19 +15,12 @@ class FlaskRoutedResponse extends HttpResponseTaintSink {
|
|||
)
|
||||
}
|
||||
|
||||
override predicate sinks(TaintKind kind) {
|
||||
kind instanceof StringKind
|
||||
}
|
||||
|
||||
override string toString() {
|
||||
result = "flask.routed.response"
|
||||
}
|
||||
override predicate sinks(TaintKind kind) { kind instanceof StringKind }
|
||||
|
||||
override string toString() { result = "flask.routed.response" }
|
||||
}
|
||||
|
||||
|
||||
class FlaskResponseArgument extends HttpResponseTaintSink {
|
||||
|
||||
FlaskResponseArgument() {
|
||||
exists(CallNode call |
|
||||
call.getFunction().pointsTo(theFlaskReponseClass()) and
|
||||
|
@ -37,12 +28,7 @@ class FlaskResponseArgument extends HttpResponseTaintSink {
|
|||
)
|
||||
}
|
||||
|
||||
override predicate sinks(TaintKind kind) {
|
||||
kind instanceof StringKind
|
||||
}
|
||||
override predicate sinks(TaintKind kind) { kind instanceof StringKind }
|
||||
|
||||
override string toString() {
|
||||
result = "flask.response.argument"
|
||||
}
|
||||
|
||||
}
|
||||
override string toString() { result = "flask.response.argument" }
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче