-
Notifications
You must be signed in to change notification settings - Fork 1.6k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #13990 from RasmusWL/experimental-cleanup
Python: Port old experimental points-to based queries
- Loading branch information
Showing
83 changed files
with
693 additions
and
1,009 deletions.
There are no files selected for viewing
159 changes: 159 additions & 0 deletions
159
python/ql/src/experimental/Security/CWE-074/TemplateConstructionConcept.qll
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,159 @@ | ||
private import python | ||
private import semmle.python.dataflow.new.DataFlow | ||
private import semmle.python.ApiGraphs | ||
|
||
/** | ||
* A data-flow node that constructs a template. | ||
* | ||
* Extend this class to refine existing API models. If you want to model new APIs, | ||
* extend `TemplateConstruction::Range` instead. | ||
*/ | ||
class TemplateConstruction extends DataFlow::Node instanceof TemplateConstruction::Range { | ||
/** Gets the argument that specifies the template source. */ | ||
DataFlow::Node getSourceArg() { result = super.getSourceArg() } | ||
} | ||
|
||
/** Provides a class for modeling new system-command execution APIs. */ | ||
module TemplateConstruction { | ||
/** | ||
* A data-flow node that constructs a template. | ||
* | ||
* Extend this class to model new APIs. If you want to refine existing API models, | ||
* extend `TemplateConstruction` instead. | ||
*/ | ||
abstract class Range extends DataFlow::Node { | ||
/** Gets the argument that specifies the template source. */ | ||
abstract DataFlow::Node getSourceArg(); | ||
} | ||
} | ||
|
||
// ----------------------------------------------------------------------------- | ||
/** A call to `airspeed.Template`. */ | ||
class AirspeedTemplateConstruction extends TemplateConstruction::Range, API::CallNode { | ||
AirspeedTemplateConstruction() { | ||
this = API::moduleImport("airspeed").getMember("Template").getACall() | ||
} | ||
|
||
override DataFlow::Node getSourceArg() { result = this.getArg(0) } | ||
} | ||
|
||
/** A call to `bottle.SimpleTemplate`. */ | ||
class BottleSimpleTemplateConstruction extends TemplateConstruction::Range, API::CallNode { | ||
BottleSimpleTemplateConstruction() { | ||
this = API::moduleImport("bottle").getMember("SimpleTemplate").getACall() | ||
} | ||
|
||
override DataFlow::Node getSourceArg() { result = this.getArg(0) } | ||
} | ||
|
||
/** A call to `bottle.template`. */ | ||
class BottleTemplateConstruction extends TemplateConstruction::Range, API::CallNode { | ||
BottleTemplateConstruction() { | ||
this = API::moduleImport("bottle").getMember("template").getACall() | ||
} | ||
|
||
override DataFlow::Node getSourceArg() { result = this.getArg(0) } | ||
} | ||
|
||
/** A call to `chameleon.PageTemplate`. */ | ||
class ChameleonTemplateConstruction extends TemplateConstruction::Range, API::CallNode { | ||
ChameleonTemplateConstruction() { | ||
this = API::moduleImport("chameleon").getMember("PageTemplate").getACall() | ||
} | ||
|
||
override DataFlow::Node getSourceArg() { result = this.getArg(0) } | ||
} | ||
|
||
/** A call to `Cheetah.Template.Template`. */ | ||
class CheetahTemplateConstruction extends TemplateConstruction::Range, API::CallNode { | ||
CheetahTemplateConstruction() { | ||
this = | ||
API::moduleImport("Cheetah") | ||
.getMember("Template") | ||
.getMember("Template") | ||
.getASubclass*() | ||
.getACall() | ||
} | ||
|
||
override DataFlow::Node getSourceArg() { result = this.getArg(0) } | ||
} | ||
|
||
/** A call to `chevron.render`. */ | ||
class ChevronRenderConstruction extends TemplateConstruction::Range, API::CallNode { | ||
ChevronRenderConstruction() { this = API::moduleImport("chevron").getMember("render").getACall() } | ||
|
||
override DataFlow::Node getSourceArg() { result = this.getArg(0) } | ||
} | ||
|
||
/** A call to `django.template.Template` */ | ||
class DjangoTemplateConstruction extends TemplateConstruction::Range, API::CallNode { | ||
DjangoTemplateConstruction() { | ||
this = API::moduleImport("django").getMember("template").getMember("Template").getACall() | ||
} | ||
|
||
override DataFlow::Node getSourceArg() { result = this.getArg(0) } | ||
} | ||
|
||
// TODO: support django.template.engines["django"]].from_string | ||
/** A call to `flask.render_template_string`. */ | ||
class FlaskTemplateConstruction extends TemplateConstruction::Range, API::CallNode { | ||
FlaskTemplateConstruction() { | ||
this = API::moduleImport("flask").getMember("render_template_string").getACall() | ||
} | ||
|
||
override DataFlow::Node getSourceArg() { result = this.getArg(0) } | ||
} | ||
|
||
/** A call to `genshi.template.TextTemplate`. */ | ||
class GenshiTextTemplateConstruction extends TemplateConstruction::Range, API::CallNode { | ||
GenshiTextTemplateConstruction() { | ||
this = API::moduleImport("genshi").getMember("template").getMember("TextTemplate").getACall() | ||
} | ||
|
||
override DataFlow::Node getSourceArg() { result = this.getArg(0) } | ||
} | ||
|
||
/** A call to `genshi.template.MarkupTemplate` */ | ||
class GenshiMarkupTemplateConstruction extends TemplateConstruction::Range, API::CallNode { | ||
GenshiMarkupTemplateConstruction() { | ||
this = API::moduleImport("genshi").getMember("template").getMember("MarkupTemplate").getACall() | ||
} | ||
|
||
override DataFlow::Node getSourceArg() { result = this.getArg(0) } | ||
} | ||
|
||
/** A call to `jinja2.Template`. */ | ||
class Jinja2TemplateConstruction extends TemplateConstruction::Range, API::CallNode { | ||
Jinja2TemplateConstruction() { | ||
this = API::moduleImport("jinja2").getMember("Template").getACall() | ||
} | ||
|
||
override DataFlow::Node getSourceArg() { result = this.getArg(0) } | ||
} | ||
|
||
/** A call to `jinja2.from_string`. */ | ||
class Jinja2FromStringConstruction extends TemplateConstruction::Range, API::CallNode { | ||
Jinja2FromStringConstruction() { | ||
this = API::moduleImport("jinja2").getMember("from_string").getACall() | ||
} | ||
|
||
override DataFlow::Node getSourceArg() { result = this.getArg(0) } | ||
} | ||
|
||
/** A call to `mako.template.Template`. */ | ||
class MakoTemplateConstruction extends TemplateConstruction::Range, API::CallNode { | ||
MakoTemplateConstruction() { | ||
this = API::moduleImport("mako").getMember("template").getMember("Template").getACall() | ||
} | ||
|
||
override DataFlow::Node getSourceArg() { result = this.getArg(0) } | ||
} | ||
|
||
/** A call to `trender.TRender`. */ | ||
class TRenderTemplateConstruction extends TemplateConstruction::Range, API::CallNode { | ||
TRenderTemplateConstruction() { | ||
this = API::moduleImport("trender").getMember("TRender").getACall() | ||
} | ||
|
||
override DataFlow::Node getSourceArg() { result = this.getArg(0) } | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
51 changes: 51 additions & 0 deletions
51
python/ql/src/experimental/Security/CWE-074/TemplateInjectionCustomizations.qll
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
/** | ||
* Provides default sources, sinks and sanitizers for detecting | ||
* "template injection" | ||
* vulnerabilities, as well as extension points for adding your own. | ||
*/ | ||
|
||
private import python | ||
private import semmle.python.dataflow.new.DataFlow | ||
private import semmle.python.Concepts | ||
private import semmle.python.dataflow.new.RemoteFlowSources | ||
private import semmle.python.dataflow.new.BarrierGuards | ||
private import TemplateConstructionConcept | ||
|
||
/** | ||
* Provides default sources, sinks and sanitizers for detecting | ||
* "template injection" | ||
* vulnerabilities, as well as extension points for adding your own. | ||
*/ | ||
module TemplateInjection { | ||
/** | ||
* A data flow source for "template injection" vulnerabilities. | ||
*/ | ||
abstract class Source extends DataFlow::Node { } | ||
|
||
/** | ||
* A data flow sink for "template injection" vulnerabilities. | ||
*/ | ||
abstract class Sink extends DataFlow::Node { } | ||
|
||
/** | ||
* A sanitizer for "template injection" vulnerabilities. | ||
*/ | ||
abstract class Sanitizer extends DataFlow::Node { } | ||
|
||
/** | ||
* A source of remote user input, considered as a flow source. | ||
*/ | ||
class RemoteFlowSourceAsSource extends Source, RemoteFlowSource { } | ||
|
||
/** | ||
* A SQL statement of a SQL construction, considered as a flow sink. | ||
*/ | ||
class TemplateConstructionAsSink extends Sink { | ||
TemplateConstructionAsSink() { this = any(TemplateConstruction c).getSourceArg() } | ||
} | ||
|
||
/** | ||
* A comparison with a constant string, considered as a sanitizer-guard. | ||
*/ | ||
class StringConstCompareAsSanitizerGuard extends Sanitizer, StringConstCompareBarrier { } | ||
} |
18 changes: 18 additions & 0 deletions
18
python/ql/src/experimental/Security/CWE-074/TemplateInjectionQuery.qll
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
/** | ||
* Provides a taint-tracking configuration for detecting "template injection" vulnerabilities. | ||
*/ | ||
|
||
private import python | ||
import semmle.python.dataflow.new.DataFlow | ||
import semmle.python.dataflow.new.TaintTracking | ||
import TemplateInjectionCustomizations::TemplateInjection | ||
|
||
module TemplateInjectionConfig implements DataFlow::ConfigSig { | ||
predicate isSource(DataFlow::Node node) { node instanceof Source } | ||
|
||
predicate isSink(DataFlow::Node node) { node instanceof Sink } | ||
|
||
predicate isBarrierIn(DataFlow::Node node) { node instanceof Sanitizer } | ||
} | ||
|
||
module TemplateInjectionFlow = TaintTracking::Global<TemplateInjectionConfig>; |
This file was deleted.
Oops, something went wrong.
Oops, something went wrong.