Skip to content

Commit 38b7812

Browse files
authored
Merge pull request github#13990 from RasmusWL/experimental-cleanup
Python: Port old experimental points-to based queries
2 parents 9957e26 + 7cba6cd commit 38b7812

File tree

83 files changed

+693
-1009
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

83 files changed

+693
-1009
lines changed
Lines changed: 159 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,159 @@
1+
private import python
2+
private import semmle.python.dataflow.new.DataFlow
3+
private import semmle.python.ApiGraphs
4+
5+
/**
6+
* A data-flow node that constructs a template.
7+
*
8+
* Extend this class to refine existing API models. If you want to model new APIs,
9+
* extend `TemplateConstruction::Range` instead.
10+
*/
11+
class TemplateConstruction extends DataFlow::Node instanceof TemplateConstruction::Range {
12+
/** Gets the argument that specifies the template source. */
13+
DataFlow::Node getSourceArg() { result = super.getSourceArg() }
14+
}
15+
16+
/** Provides a class for modeling new system-command execution APIs. */
17+
module TemplateConstruction {
18+
/**
19+
* A data-flow node that constructs a template.
20+
*
21+
* Extend this class to model new APIs. If you want to refine existing API models,
22+
* extend `TemplateConstruction` instead.
23+
*/
24+
abstract class Range extends DataFlow::Node {
25+
/** Gets the argument that specifies the template source. */
26+
abstract DataFlow::Node getSourceArg();
27+
}
28+
}
29+
30+
// -----------------------------------------------------------------------------
31+
/** A call to `airspeed.Template`. */
32+
class AirspeedTemplateConstruction extends TemplateConstruction::Range, API::CallNode {
33+
AirspeedTemplateConstruction() {
34+
this = API::moduleImport("airspeed").getMember("Template").getACall()
35+
}
36+
37+
override DataFlow::Node getSourceArg() { result = this.getArg(0) }
38+
}
39+
40+
/** A call to `bottle.SimpleTemplate`. */
41+
class BottleSimpleTemplateConstruction extends TemplateConstruction::Range, API::CallNode {
42+
BottleSimpleTemplateConstruction() {
43+
this = API::moduleImport("bottle").getMember("SimpleTemplate").getACall()
44+
}
45+
46+
override DataFlow::Node getSourceArg() { result = this.getArg(0) }
47+
}
48+
49+
/** A call to `bottle.template`. */
50+
class BottleTemplateConstruction extends TemplateConstruction::Range, API::CallNode {
51+
BottleTemplateConstruction() {
52+
this = API::moduleImport("bottle").getMember("template").getACall()
53+
}
54+
55+
override DataFlow::Node getSourceArg() { result = this.getArg(0) }
56+
}
57+
58+
/** A call to `chameleon.PageTemplate`. */
59+
class ChameleonTemplateConstruction extends TemplateConstruction::Range, API::CallNode {
60+
ChameleonTemplateConstruction() {
61+
this = API::moduleImport("chameleon").getMember("PageTemplate").getACall()
62+
}
63+
64+
override DataFlow::Node getSourceArg() { result = this.getArg(0) }
65+
}
66+
67+
/** A call to `Cheetah.Template.Template`. */
68+
class CheetahTemplateConstruction extends TemplateConstruction::Range, API::CallNode {
69+
CheetahTemplateConstruction() {
70+
this =
71+
API::moduleImport("Cheetah")
72+
.getMember("Template")
73+
.getMember("Template")
74+
.getASubclass*()
75+
.getACall()
76+
}
77+
78+
override DataFlow::Node getSourceArg() { result = this.getArg(0) }
79+
}
80+
81+
/** A call to `chevron.render`. */
82+
class ChevronRenderConstruction extends TemplateConstruction::Range, API::CallNode {
83+
ChevronRenderConstruction() { this = API::moduleImport("chevron").getMember("render").getACall() }
84+
85+
override DataFlow::Node getSourceArg() { result = this.getArg(0) }
86+
}
87+
88+
/** A call to `django.template.Template` */
89+
class DjangoTemplateConstruction extends TemplateConstruction::Range, API::CallNode {
90+
DjangoTemplateConstruction() {
91+
this = API::moduleImport("django").getMember("template").getMember("Template").getACall()
92+
}
93+
94+
override DataFlow::Node getSourceArg() { result = this.getArg(0) }
95+
}
96+
97+
// TODO: support django.template.engines["django"]].from_string
98+
/** A call to `flask.render_template_string`. */
99+
class FlaskTemplateConstruction extends TemplateConstruction::Range, API::CallNode {
100+
FlaskTemplateConstruction() {
101+
this = API::moduleImport("flask").getMember("render_template_string").getACall()
102+
}
103+
104+
override DataFlow::Node getSourceArg() { result = this.getArg(0) }
105+
}
106+
107+
/** A call to `genshi.template.TextTemplate`. */
108+
class GenshiTextTemplateConstruction extends TemplateConstruction::Range, API::CallNode {
109+
GenshiTextTemplateConstruction() {
110+
this = API::moduleImport("genshi").getMember("template").getMember("TextTemplate").getACall()
111+
}
112+
113+
override DataFlow::Node getSourceArg() { result = this.getArg(0) }
114+
}
115+
116+
/** A call to `genshi.template.MarkupTemplate` */
117+
class GenshiMarkupTemplateConstruction extends TemplateConstruction::Range, API::CallNode {
118+
GenshiMarkupTemplateConstruction() {
119+
this = API::moduleImport("genshi").getMember("template").getMember("MarkupTemplate").getACall()
120+
}
121+
122+
override DataFlow::Node getSourceArg() { result = this.getArg(0) }
123+
}
124+
125+
/** A call to `jinja2.Template`. */
126+
class Jinja2TemplateConstruction extends TemplateConstruction::Range, API::CallNode {
127+
Jinja2TemplateConstruction() {
128+
this = API::moduleImport("jinja2").getMember("Template").getACall()
129+
}
130+
131+
override DataFlow::Node getSourceArg() { result = this.getArg(0) }
132+
}
133+
134+
/** A call to `jinja2.from_string`. */
135+
class Jinja2FromStringConstruction extends TemplateConstruction::Range, API::CallNode {
136+
Jinja2FromStringConstruction() {
137+
this = API::moduleImport("jinja2").getMember("from_string").getACall()
138+
}
139+
140+
override DataFlow::Node getSourceArg() { result = this.getArg(0) }
141+
}
142+
143+
/** A call to `mako.template.Template`. */
144+
class MakoTemplateConstruction extends TemplateConstruction::Range, API::CallNode {
145+
MakoTemplateConstruction() {
146+
this = API::moduleImport("mako").getMember("template").getMember("Template").getACall()
147+
}
148+
149+
override DataFlow::Node getSourceArg() { result = this.getArg(0) }
150+
}
151+
152+
/** A call to `trender.TRender`. */
153+
class TRenderTemplateConstruction extends TemplateConstruction::Range, API::CallNode {
154+
TRenderTemplateConstruction() {
155+
this = API::moduleImport("trender").getMember("TRender").getACall()
156+
}
157+
158+
override DataFlow::Node getSourceArg() { result = this.getArg(0) }
159+
}

python/ql/src/experimental/Security/CWE-074/TemplateInjection.ql

Lines changed: 6 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -11,25 +11,10 @@
1111
*/
1212

1313
import python
14-
import semmle.python.security.Paths
15-
/* Sources */
16-
import semmle.python.web.HttpRequest
17-
/* Sinks */
18-
import experimental.semmle.python.templates.Ssti
19-
/* Flow */
20-
import semmle.python.security.strings.Untrusted
14+
import TemplateInjectionQuery
15+
import TemplateInjectionFlow::PathGraph
2116

22-
class TemplateInjectionConfiguration extends TaintTracking::Configuration {
23-
TemplateInjectionConfiguration() { this = "Template injection configuration" }
24-
25-
deprecated override predicate isSource(TaintTracking::Source source) {
26-
source instanceof HttpRequestTaintSource
27-
}
28-
29-
deprecated override predicate isSink(TaintTracking::Sink sink) { sink instanceof SSTISink }
30-
}
31-
32-
from TemplateInjectionConfiguration config, TaintedPathSource src, TaintedPathSink sink
33-
where config.hasFlowPath(src, sink)
34-
select sink.getSink(), src, sink, "This Template depends on $@.", src.getSource(),
35-
"a user-provided value"
17+
from TemplateInjectionFlow::PathNode source, TemplateInjectionFlow::PathNode sink
18+
where TemplateInjectionFlow::flowPath(source, sink)
19+
select sink.getNode(), source, sink, "This Template depends on $@.", source.getNode(),
20+
"user-provided value"
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
/**
2+
* Provides default sources, sinks and sanitizers for detecting
3+
* "template injection"
4+
* vulnerabilities, as well as extension points for adding your own.
5+
*/
6+
7+
private import python
8+
private import semmle.python.dataflow.new.DataFlow
9+
private import semmle.python.Concepts
10+
private import semmle.python.dataflow.new.RemoteFlowSources
11+
private import semmle.python.dataflow.new.BarrierGuards
12+
private import TemplateConstructionConcept
13+
14+
/**
15+
* Provides default sources, sinks and sanitizers for detecting
16+
* "template injection"
17+
* vulnerabilities, as well as extension points for adding your own.
18+
*/
19+
module TemplateInjection {
20+
/**
21+
* A data flow source for "template injection" vulnerabilities.
22+
*/
23+
abstract class Source extends DataFlow::Node { }
24+
25+
/**
26+
* A data flow sink for "template injection" vulnerabilities.
27+
*/
28+
abstract class Sink extends DataFlow::Node { }
29+
30+
/**
31+
* A sanitizer for "template injection" vulnerabilities.
32+
*/
33+
abstract class Sanitizer extends DataFlow::Node { }
34+
35+
/**
36+
* A source of remote user input, considered as a flow source.
37+
*/
38+
class RemoteFlowSourceAsSource extends Source, RemoteFlowSource { }
39+
40+
/**
41+
* A SQL statement of a SQL construction, considered as a flow sink.
42+
*/
43+
class TemplateConstructionAsSink extends Sink {
44+
TemplateConstructionAsSink() { this = any(TemplateConstruction c).getSourceArg() }
45+
}
46+
47+
/**
48+
* A comparison with a constant string, considered as a sanitizer-guard.
49+
*/
50+
class StringConstCompareAsSanitizerGuard extends Sanitizer, StringConstCompareBarrier { }
51+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
/**
2+
* Provides a taint-tracking configuration for detecting "template injection" vulnerabilities.
3+
*/
4+
5+
private import python
6+
import semmle.python.dataflow.new.DataFlow
7+
import semmle.python.dataflow.new.TaintTracking
8+
import TemplateInjectionCustomizations::TemplateInjection
9+
10+
module TemplateInjectionConfig implements DataFlow::ConfigSig {
11+
predicate isSource(DataFlow::Node node) { node instanceof Source }
12+
13+
predicate isSink(DataFlow::Node node) { node instanceof Sink }
14+
15+
predicate isBarrierIn(DataFlow::Node node) { node instanceof Sanitizer }
16+
}
17+
18+
module TemplateInjectionFlow = TaintTracking::Global<TemplateInjectionConfig>;

python/ql/src/experimental/Security/CWE-091/Xslt.ql

Lines changed: 0 additions & 36 deletions
This file was deleted.

0 commit comments

Comments
 (0)