Skip to content

Commit 657b199

Browse files
committed
Python: Move FullServerSideRequestForgery and PartialServerSideRequestForgery to new dataflow API
1 parent dbfe517 commit 657b199

File tree

5 files changed

+61
-316
lines changed

5 files changed

+61
-316
lines changed

python/ql/lib/semmle/python/security/dataflow/ServerSideRequestForgeryQuery.qll

Lines changed: 53 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ import semmle.python.Concepts
1313
import ServerSideRequestForgeryCustomizations::ServerSideRequestForgery
1414

1515
/**
16+
* DEPRECATED: Use `FullServerSideRequestForgeryFlow` module instead.
17+
*
1618
* A taint-tracking configuration for detecting "Server-side request forgery" vulnerabilities.
1719
*
1820
* This configuration has a sanitizer to limit results to cases where attacker has full control of URL.
@@ -21,7 +23,7 @@ import ServerSideRequestForgeryCustomizations::ServerSideRequestForgery
2123
* You should use the `fullyControlledRequest` to only select results where all
2224
* URL parts are fully controlled.
2325
*/
24-
class FullServerSideRequestForgeryConfiguration extends TaintTracking::Configuration {
26+
deprecated class FullServerSideRequestForgeryConfiguration extends TaintTracking::Configuration {
2527
FullServerSideRequestForgeryConfiguration() { this = "FullServerSideRequestForgery" }
2628

2729
override predicate isSource(DataFlow::Node source) { source instanceof Source }
@@ -39,24 +41,51 @@ class FullServerSideRequestForgeryConfiguration extends TaintTracking::Configura
3941
}
4042
}
4143

44+
/**
45+
* This configuration has a sanitizer to limit results to cases where attacker has full control of URL.
46+
* See `PartialServerSideRequestForgery` for a variant without this requirement.
47+
*
48+
* You should use the `fullyControlledRequest` to only select results where all
49+
* URL parts are fully controlled.
50+
*/
51+
private module FullServerSideRequestForgeryConfig implements DataFlow::ConfigSig {
52+
predicate isSource(DataFlow::Node source) { source instanceof Source }
53+
54+
predicate isSink(DataFlow::Node sink) { sink instanceof Sink }
55+
56+
predicate isBarrier(DataFlow::Node node) {
57+
node instanceof Sanitizer
58+
or
59+
node instanceof FullUrlControlSanitizer
60+
}
61+
}
62+
63+
/**
64+
* Global taint-tracking for detecting "Full server-side request forgery" vulnerabilities.
65+
*
66+
* You should use the `fullyControlledRequest` to only select results where all
67+
* URL parts are fully controlled.
68+
*/
69+
module FullServerSideRequestForgeryFlow = TaintTracking::Global<FullServerSideRequestForgeryConfig>;
70+
4271
/**
4372
* Holds if all URL parts of `request` is fully user controlled.
4473
*/
4574
predicate fullyControlledRequest(Http::Client::Request request) {
46-
exists(FullServerSideRequestForgeryConfiguration fullConfig |
47-
forall(DataFlow::Node urlPart | urlPart = request.getAUrlPart() |
48-
fullConfig.hasFlow(_, urlPart)
49-
)
75+
forall(DataFlow::Node urlPart | urlPart = request.getAUrlPart() |
76+
FullServerSideRequestForgeryFlow::flow(_, urlPart)
5077
)
5178
}
5279

5380
/**
81+
* DEPRECATED: Use `FullServerSideRequestForgeryFlow` module instead.
82+
*
5483
* A taint-tracking configuration for detecting "Server-side request forgery" vulnerabilities.
5584
*
5685
* This configuration has results, even when the attacker does not have full control over the URL.
5786
* See `FullServerSideRequestForgeryConfiguration`, and the `fullyControlledRequest` predicate.
5887
*/
59-
class PartialServerSideRequestForgeryConfiguration extends TaintTracking::Configuration {
88+
deprecated class PartialServerSideRequestForgeryConfiguration extends TaintTracking::Configuration {
6089
PartialServerSideRequestForgeryConfiguration() { this = "PartialServerSideRequestForgery" }
6190

6291
override predicate isSource(DataFlow::Node source) { source instanceof Source }
@@ -69,3 +98,21 @@ class PartialServerSideRequestForgeryConfiguration extends TaintTracking::Config
6998
guard instanceof SanitizerGuard
7099
}
71100
}
101+
102+
/**
103+
* This configuration has results, even when the attacker does not have full control over the URL.
104+
* See `FullServerSideRequestForgeryConfiguration`, and the `fullyControlledRequest` predicate.
105+
*/
106+
private module PartialServerSideRequestForgeryConfig implements DataFlow::ConfigSig {
107+
predicate isSource(DataFlow::Node source) { source instanceof Source }
108+
109+
predicate isSink(DataFlow::Node sink) { sink instanceof Sink }
110+
111+
predicate isBarrier(DataFlow::Node node) { node instanceof Sanitizer }
112+
}
113+
114+
/**
115+
* Global taint-tracking for detecting "partial server-side request forgery" vulnerabilities.
116+
*/
117+
module PartialServerSideRequestForgeryFlow =
118+
TaintTracking::Global<PartialServerSideRequestForgeryConfig>;

python/ql/src/Security/CWE-918/FullServerSideRequestForgery.ql

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,14 +12,14 @@
1212

1313
import python
1414
import semmle.python.security.dataflow.ServerSideRequestForgeryQuery
15-
import DataFlow::PathGraph
15+
import FullServerSideRequestForgeryFlow::PathGraph
1616

1717
from
18-
FullServerSideRequestForgeryConfiguration fullConfig, DataFlow::PathNode source,
19-
DataFlow::PathNode sink, Http::Client::Request request
18+
FullServerSideRequestForgeryFlow::PathNode source,
19+
FullServerSideRequestForgeryFlow::PathNode sink, Http::Client::Request request
2020
where
2121
request = sink.getNode().(Sink).getRequest() and
22-
fullConfig.hasFlowPath(source, sink) and
22+
FullServerSideRequestForgeryFlow::flowPath(source, sink) and
2323
fullyControlledRequest(request)
2424
select request, source, sink, "The full URL of this request depends on a $@.", source.getNode(),
2525
"user-provided value"

python/ql/src/Security/CWE-918/PartialServerSideRequestForgery.ql

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,14 +12,14 @@
1212

1313
import python
1414
import semmle.python.security.dataflow.ServerSideRequestForgeryQuery
15-
import DataFlow::PathGraph
15+
import PartialServerSideRequestForgeryFlow::PathGraph
1616

1717
from
18-
PartialServerSideRequestForgeryConfiguration partialConfig, DataFlow::PathNode source,
19-
DataFlow::PathNode sink, Http::Client::Request request
18+
PartialServerSideRequestForgeryFlow::PathNode source,
19+
PartialServerSideRequestForgeryFlow::PathNode sink, Http::Client::Request request
2020
where
2121
request = sink.getNode().(Sink).getRequest() and
22-
partialConfig.hasFlowPath(source, sink) and
22+
PartialServerSideRequestForgeryFlow::flowPath(source, sink) and
2323
not fullyControlledRequest(request)
2424
select request, source, sink, "Part of the URL of this request depends on a $@.", source.getNode(),
2525
"user-provided value"

0 commit comments

Comments
 (0)