mirror of
https://github.com/github/codeql.git
synced 2026-01-04 10:10:20 +01:00
Add support for vulnerable CORS middlewares
This commit is contained in:
@@ -1411,6 +1411,56 @@ module Http {
|
||||
override DataFlow::Node getValueArg() { none() }
|
||||
}
|
||||
|
||||
/**
|
||||
* A data-flow node that enables or disables CORS
|
||||
* in a global manner.
|
||||
*
|
||||
* Extend this class to refine existing API models. If you want to model new APIs,
|
||||
* extend `CorsMiddleware::Range` instead.
|
||||
*/
|
||||
class CorsMiddleware extends DataFlow::Node instanceof CorsMiddleware::Range {
|
||||
/**
|
||||
* Gets the string corresponding to the middleware
|
||||
*/
|
||||
string middleware_name() { result = super.middleware_name() }
|
||||
|
||||
/**
|
||||
* Gets the boolean value corresponding to if CORS credentials is enabled
|
||||
* (`true`) or disabled (`false`) by this node.
|
||||
*/
|
||||
DataFlow::Node allowed_origins() { result = super.allowed_origins() }
|
||||
|
||||
DataFlow::Node allowed_credentials() { result = super.allowed_credentials() }
|
||||
}
|
||||
|
||||
/** Provides a class for modeling new CORS middleware APIs. */
|
||||
module CorsMiddleware {
|
||||
/**
|
||||
* A data-flow node that enables or disables Cross-site request forgery protection
|
||||
* in a global manner.
|
||||
*
|
||||
* Extend this class to model new APIs. If you want to refine existing API models,
|
||||
* extend `CorsMiddleware` instead.
|
||||
*/
|
||||
abstract class Range extends DataFlow::Node {
|
||||
/**
|
||||
* Gets the string corresponding to the middleware
|
||||
*/
|
||||
abstract string middleware_name();
|
||||
|
||||
/**
|
||||
* Gets the boolean value corresponding to if CORS credentials is enabled
|
||||
* (`true`) or disabled (`false`) by this node.
|
||||
*/
|
||||
abstract DataFlow::Node allowed_credentials();
|
||||
|
||||
/**
|
||||
* Gets the strings corresponding to the origins allowed by the cors policy
|
||||
*/
|
||||
abstract DataFlow::Node allowed_origins();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A data-flow node that enables or disables Cross-site request forgery protection
|
||||
* in a global manner.
|
||||
|
||||
@@ -30,6 +30,32 @@ module FastApi {
|
||||
API::Node instance() { result = cls().getReturn() }
|
||||
}
|
||||
|
||||
/**
|
||||
* A call to `app.add_middleware` adding a generic middleware.
|
||||
*/
|
||||
private class AddMiddlewareCall extends DataFlow::CallCfgNode {
|
||||
AddMiddlewareCall() { this = App::instance().getMember("add_middleware").getACall() }
|
||||
|
||||
string middleware_name() { result = this.getArg(0).asExpr().(Name).toString() }
|
||||
}
|
||||
|
||||
/**
|
||||
* A call to `app.add_middleware` adding CORSMiddleware.
|
||||
*/
|
||||
class AddCorsMiddlewareCall extends Http::Server::CorsMiddleware::Range, AddMiddlewareCall {
|
||||
override string middleware_name() { result = this.getArg(0).asExpr().(Name).toString() }
|
||||
|
||||
override DataFlow::Node allowed_origins() { result = this.getArgByName("allow_origins") }
|
||||
|
||||
override DataFlow::Node allowed_credentials() {
|
||||
result = this.getArgByName("allow_credentials")
|
||||
}
|
||||
|
||||
DataFlow::Node allowed_methods() { result = this.getArgByName("allow_methods") }
|
||||
|
||||
DataFlow::Node allowed_headers() { result = this.getArgByName("allow_headers") }
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides models for the `fastapi.APIRouter` class
|
||||
*
|
||||
|
||||
@@ -25,6 +25,87 @@ private import semmle.python.frameworks.data.ModelsAsData
|
||||
* - https://www.starlette.io/
|
||||
*/
|
||||
module Starlette {
|
||||
/**
|
||||
* Provides models for the `starlette.app` class
|
||||
*
|
||||
* See https://www.starlette.io/websockets/.
|
||||
*/
|
||||
module App {
|
||||
API::Node cls() { result = API::moduleImport("starlette").getMember("app") }
|
||||
|
||||
/** Gets a reference to a FastAPI application (an instance of `fastapi.FastAPI`). */
|
||||
API::Node instance() { result = cls().getReturn() }
|
||||
}
|
||||
|
||||
/**
|
||||
* A call to any of the execute methods on a `app.add_middleware`.
|
||||
*/
|
||||
class AddMiddlewareCall extends DataFlow::CallCfgNode {
|
||||
AddMiddlewareCall() {
|
||||
this = [App::instance().getMember("add_middleware").getACall(), Middleware::instance()]
|
||||
}
|
||||
|
||||
string middleware_name() { result = this.getArg(0).asExpr().(Name).toString() }
|
||||
}
|
||||
|
||||
/**
|
||||
* A call to any of the execute methods on a `app.add_middleware` with CORSMiddleware.
|
||||
*/
|
||||
class AddCorsMiddlewareCall extends AddMiddlewareCall, Http::Server::CorsMiddleware::Range {
|
||||
override string middleware_name() { result = this.getArg(0).asExpr().(Name).toString() }
|
||||
|
||||
override DataFlow::Node allowed_origins() { result = this.getArgByName("allow_origins") }
|
||||
|
||||
override DataFlow::Node allowed_credentials() {
|
||||
result = this.getArgByName("allow_credentials")
|
||||
}
|
||||
|
||||
DataFlow::Node allowed_methods() { result = this.getArgByName("allow_methods") }
|
||||
|
||||
DataFlow::Node allowed_headers() { result = this.getArgByName("allow_headers") }
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides models for the `starlette.middleware.Middleware` class
|
||||
*
|
||||
* See https://www.starlette.io/.
|
||||
*/
|
||||
module Middleware {
|
||||
/** Gets a reference to the `starlette.middleware.Middleware` class. */
|
||||
API::Node classRef() {
|
||||
result = API::moduleImport("starlette").getMember("middleware").getMember("Middleware")
|
||||
or
|
||||
result = ModelOutput::getATypeNode("starlette.middleware.Middleware~Subclass").getASubclass*()
|
||||
}
|
||||
|
||||
/**
|
||||
* A source of instances of `starlette.middleware.Middleware`, extend this class to model new instances.
|
||||
*
|
||||
* This can include instantiations of the class, return values from function
|
||||
* calls, or a special parameter that will be set when functions are called by an external
|
||||
* library.
|
||||
*
|
||||
* Use the predicate `Middleware::instance()` to get references to instances of `starlette.middleware.middleware`.
|
||||
*/
|
||||
abstract class InstanceSource extends DataFlow::LocalSourceNode { }
|
||||
|
||||
/** A direct instantiation of `starlette.middleware.Middleware`. */
|
||||
class ClassInstantiation extends InstanceSource, DataFlow::CallCfgNode {
|
||||
ClassInstantiation() { this = classRef().getACall() }
|
||||
}
|
||||
|
||||
/** Gets a reference to an instance of `starlette.middleware.Middleware`. */
|
||||
private DataFlow::TypeTrackingNode instance(DataFlow::TypeTracker t) {
|
||||
t.start() and
|
||||
result instanceof InstanceSource
|
||||
or
|
||||
exists(DataFlow::TypeTracker t2 | result = instance(t2).track(t2, t))
|
||||
}
|
||||
|
||||
/** Gets a reference to an instance of `starlette.middleware.Middleware`. */
|
||||
DataFlow::Node instance() { instance(DataFlow::TypeTracker::end()).flowsTo(result) }
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides models for the `starlette.websockets.WebSocket` class
|
||||
*
|
||||
|
||||
Reference in New Issue
Block a user