I've added 2 queries:

- one that detects full SSRF, where an attacker can control the full URL,
  which is always bad
- and one for partial SSRF, where an attacker can control parts of an
  URL (such as the path, query parameters, or fragment), which is not a
  big problem in many cases (but might still be exploitable)

full SSRF should run by default, and partial SSRF should not (but makes
it easy to see the other results).

Some elements of the full SSRF queries needs a bit more polishing, like
being able to detect `"https://" + user_input` is in fact controlling
the full URL.
This commit is contained in:
Rasmus Wriedt Larsen 2021-12-16 01:48:34 +01:00
Родитель 579de0c3f0
Коммит 1cc5e54357
12 изменённых файлов: 648 добавлений и 0 удалений

Просмотреть файл

@ -0,0 +1,69 @@
/**
* Provides a taint-tracking configuration for detecting "Server-side request forgery" vulnerabilities.
*
* Note, for performance reasons: only import this file if
* `ServerSideRequestForgery::Configuration` is needed, otherwise
* `ServerSideRequestForgeryCustomizations` should be imported instead.
*/
private import python
import semmle.python.dataflow.new.DataFlow
import semmle.python.dataflow.new.TaintTracking
/**
* Provides a taint-tracking configuration for detecting "Server-side request forgery" vulnerabilities.
*
* This configuration has a sanitizer to limit results to cases where attacker has full control of URL.
* See `PartialServerSideRequestForgery` for a variant without this requirement.
*/
module FullServerSideRequestForgery {
import ServerSideRequestForgeryCustomizations::ServerSideRequestForgery
/**
* A taint-tracking configuration for detecting "Server-side request forgery" vulnerabilities.
*/
class Configuration extends TaintTracking::Configuration {
Configuration() { this = "FullServerSideRequestForgery" }
override predicate isSource(DataFlow::Node source) { source instanceof Source }
override predicate isSink(DataFlow::Node sink) { sink instanceof Sink }
override predicate isSanitizer(DataFlow::Node node) {
node instanceof Sanitizer
or
node instanceof FullUrlControlSanitizer
}
override predicate isSanitizerGuard(DataFlow::BarrierGuard guard) {
guard instanceof SanitizerGuard
}
}
}
/**
* Provides a taint-tracking configuration for detecting "Server-side request forgery" vulnerabilities.
*
* This configuration has results, even when the attacker does not have full control over the URL.
* See `FullServerSideRequestForgery` for variant that has this requirement.
*/
module PartialServerSideRequestForgery {
import ServerSideRequestForgeryCustomizations::ServerSideRequestForgery
/**
* A taint-tracking configuration for detecting "Server-side request forgery" vulnerabilities.
*/
class Configuration extends TaintTracking::Configuration {
Configuration() { this = "PartialServerSideRequestForgery" }
override predicate isSource(DataFlow::Node source) { source instanceof Source }
override predicate isSink(DataFlow::Node sink) { sink instanceof Sink }
override predicate isSanitizer(DataFlow::Node node) { node instanceof Sanitizer }
override predicate isSanitizerGuard(DataFlow::BarrierGuard guard) {
guard instanceof SanitizerGuard
}
}
}

Просмотреть файл

@ -0,0 +1,94 @@
/**
* Provides default sources, sinks and sanitizers for detecting
* "Server-side request forgery"
* 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
/**
* Provides default sources, sinks and sanitizers for detecting
* "Server-side request forgery"
* vulnerabilities, as well as extension points for adding your own.
*/
module ServerSideRequestForgery {
/**
* A data flow source for "Server-side request forgery" vulnerabilities.
*/
abstract class Source extends DataFlow::Node { }
/**
* A data flow sink for "Server-side request forgery" vulnerabilities.
*/
abstract class Sink extends DataFlow::Node { }
/**
* A sanitizer for "Server-side request forgery" vulnerabilities.
*/
abstract class Sanitizer extends DataFlow::Node { }
/**
* A sanitizer for "Server-side request forgery" vulnerabilities,
* that ensures the attacker does not have full control of the URL. (that is, might
* still be able to control path or query parameters).
*/
abstract class FullUrlControlSanitizer extends DataFlow::Node { }
/**
* A sanitizer guard for "Server-side request forgery" vulnerabilities.
*/
abstract class SanitizerGuard extends DataFlow::BarrierGuard { }
/**
* A source of remote user input, considered as a flow source.
*/
class RemoteFlowSourceAsSource extends Source, RemoteFlowSource { }
/** The URL of an HTTP request, considered as a sink. */
class HttpRequestUrlAsSink extends Sink {
HttpRequestUrlAsSink() {
exists(HTTP::Client::Request req | req.getAUrlPart() = this) and
// Since we find sinks inside stdlib, we need to exclude them manually. See
// comment for command injection sinks for more details.
not this.getScope().getEnclosingModule().getName() in ["http.client", "httplib"]
}
}
/**
* A comparison with a constant string, considered as a sanitizer-guard.
*/
class StringConstCompareAsSanitizerGuard extends SanitizerGuard, StringConstCompare { }
/**
* A string construction (concat, format, f-string) where the left side is not
* user-controlled.
*/
class StringConstructioneAsFullUrlControlSanitizer extends FullUrlControlSanitizer {
StringConstructioneAsFullUrlControlSanitizer() {
// string concat
exists(BinaryExprNode add |
add.getOp() instanceof Add and
add.getRight() = this.asCfgNode()
)
or
// % formatting
exists(BinaryExprNode fmt |
fmt.getOp() instanceof Mod and
fmt.getRight() = this.asCfgNode()
)
or
// arguments to a format call
exists(DataFlow::MethodCallNode call |
call.getMethodName() = "format" and
this in [call.getArg(_), call.getArgByName(_)]
)
or
// f-string
exists(Fstring fstring | fstring.getValue(any(int i | i > 0)) = this.asExpr())
}
}
}

Просмотреть файл

@ -0,0 +1,22 @@
/**
* @name Full server-side request forgery
* @description Making a network request to a URL that is fully user-controlled allows for request forgery attacks.
* @kind path-problem
* @problem.severity error
* @security-severity 9.1
* @precision high
* @id py/full-ssrf
* @tags security
* external/cwe/cwe-918
*/
import python
import semmle.python.security.dataflow.ServerSideRequestForgery
import DataFlow::PathGraph
from
FullServerSideRequestForgery::Configuration config, DataFlow::PathNode source,
DataFlow::PathNode sink
where config.hasFlowPath(source, sink)
select sink.getNode(), source, sink, "The full URL of this request depends on $@.",
source.getNode(), "a user-provided value"

Просмотреть файл

@ -0,0 +1,25 @@
/**
* @name Partial server-side request forgery
* @description Making a network request to a URL that is partially user-controlled allows for request forgery attacks.
* @kind path-problem
* @problem.severity error
* @security-severity 9.1
* @precision medium
* @id py/partial-ssrf
* @tags security
* external/cwe/cwe-918
*/
import python
import semmle.python.security.dataflow.ServerSideRequestForgery
import DataFlow::PathGraph
from
FullServerSideRequestForgery::Configuration fullConfig,
PartialServerSideRequestForgery::Configuration partialConfig, DataFlow::PathNode source,
DataFlow::PathNode sink
where
partialConfig.hasFlowPath(source, sink) and
not fullConfig.hasFlow(source.getNode(), sink.getNode())
select sink.getNode(), source, sink, "Part of the URL of this request depends on $@.",
source.getNode(), "a user-provided value"

Просмотреть файл

@ -0,0 +1,147 @@
edges
| full_partial_test.py:7:18:7:24 | ControlFlowNode for request | full_partial_test.py:7:18:7:29 | ControlFlowNode for Attribute |
| full_partial_test.py:7:18:7:24 | ControlFlowNode for request | full_partial_test.py:7:18:7:29 | ControlFlowNode for Attribute |
| full_partial_test.py:7:18:7:24 | ControlFlowNode for request | full_partial_test.py:8:17:8:23 | ControlFlowNode for request |
| full_partial_test.py:7:18:7:24 | ControlFlowNode for request | full_partial_test.py:8:17:8:28 | ControlFlowNode for Attribute |
| full_partial_test.py:7:18:7:29 | ControlFlowNode for Attribute | full_partial_test.py:7:18:7:48 | ControlFlowNode for Subscript |
| full_partial_test.py:7:18:7:29 | ControlFlowNode for Attribute | full_partial_test.py:7:18:7:48 | ControlFlowNode for Subscript |
| full_partial_test.py:7:18:7:48 | ControlFlowNode for Subscript | full_partial_test.py:10:18:10:27 | ControlFlowNode for user_input |
| full_partial_test.py:7:18:7:48 | ControlFlowNode for Subscript | full_partial_test.py:10:18:10:27 | ControlFlowNode for user_input |
| full_partial_test.py:7:18:7:48 | ControlFlowNode for Subscript | full_partial_test.py:13:18:13:20 | ControlFlowNode for url |
| full_partial_test.py:7:18:7:48 | ControlFlowNode for Subscript | full_partial_test.py:19:18:19:20 | ControlFlowNode for url |
| full_partial_test.py:7:18:7:48 | ControlFlowNode for Subscript | full_partial_test.py:23:18:23:20 | ControlFlowNode for url |
| full_partial_test.py:7:18:7:48 | ControlFlowNode for Subscript | full_partial_test.py:28:18:28:20 | ControlFlowNode for url |
| full_partial_test.py:7:18:7:48 | ControlFlowNode for Subscript | full_partial_test.py:31:18:31:20 | ControlFlowNode for url |
| full_partial_test.py:7:18:7:48 | ControlFlowNode for Subscript | full_partial_test.py:34:18:34:20 | ControlFlowNode for url |
| full_partial_test.py:7:18:7:48 | ControlFlowNode for Subscript | full_partial_test.py:39:18:39:20 | ControlFlowNode for url |
| full_partial_test.py:7:18:7:48 | ControlFlowNode for Subscript | full_partial_test.py:42:18:42:20 | ControlFlowNode for url |
| full_partial_test.py:7:18:7:48 | ControlFlowNode for Subscript | full_partial_test.py:44:38:44:58 | ControlFlowNode for Tuple |
| full_partial_test.py:7:18:7:48 | ControlFlowNode for Subscript | full_partial_test.py:50:18:50:20 | ControlFlowNode for url |
| full_partial_test.py:7:18:7:48 | ControlFlowNode for Subscript | full_partial_test.py:53:18:53:20 | ControlFlowNode for url |
| full_partial_test.py:7:18:7:48 | ControlFlowNode for Subscript | full_partial_test.py:56:18:56:20 | ControlFlowNode for url |
| full_partial_test.py:8:17:8:23 | ControlFlowNode for request | full_partial_test.py:8:17:8:28 | ControlFlowNode for Attribute |
| full_partial_test.py:8:17:8:28 | ControlFlowNode for Attribute | full_partial_test.py:8:17:8:41 | ControlFlowNode for Subscript |
| full_partial_test.py:8:17:8:41 | ControlFlowNode for Subscript | full_partial_test.py:23:18:23:20 | ControlFlowNode for url |
| full_partial_test.py:8:17:8:41 | ControlFlowNode for Subscript | full_partial_test.py:34:18:34:20 | ControlFlowNode for url |
| full_partial_test.py:8:17:8:41 | ControlFlowNode for Subscript | full_partial_test.py:44:38:44:58 | ControlFlowNode for Tuple |
| full_partial_test.py:8:17:8:41 | ControlFlowNode for Subscript | full_partial_test.py:56:18:56:20 | ControlFlowNode for url |
| full_partial_test.py:44:38:44:58 | ControlFlowNode for Tuple | full_partial_test.py:45:18:45:20 | ControlFlowNode for url |
| full_partial_test.py:60:18:60:24 | ControlFlowNode for request | full_partial_test.py:60:18:60:29 | ControlFlowNode for Attribute |
| full_partial_test.py:60:18:60:29 | ControlFlowNode for Attribute | full_partial_test.py:60:18:60:48 | ControlFlowNode for Subscript |
| full_partial_test.py:60:18:60:48 | ControlFlowNode for Subscript | full_partial_test.py:63:18:63:20 | ControlFlowNode for url |
| full_partial_test.py:60:18:60:48 | ControlFlowNode for Subscript | full_partial_test.py:66:18:66:20 | ControlFlowNode for url |
| full_partial_test.py:60:18:60:48 | ControlFlowNode for Subscript | full_partial_test.py:69:18:69:20 | ControlFlowNode for url |
| full_partial_test.py:60:18:60:48 | ControlFlowNode for Subscript | full_partial_test.py:72:18:72:20 | ControlFlowNode for url |
| full_partial_test.py:60:18:60:48 | ControlFlowNode for Subscript | full_partial_test.py:78:18:78:20 | ControlFlowNode for url |
| full_partial_test.py:60:18:60:48 | ControlFlowNode for Subscript | full_partial_test.py:81:18:81:20 | ControlFlowNode for url |
| test_http_client.py:9:19:9:25 | ControlFlowNode for request | test_http_client.py:9:19:9:30 | ControlFlowNode for Attribute |
| test_http_client.py:9:19:9:25 | ControlFlowNode for request | test_http_client.py:9:19:9:30 | ControlFlowNode for Attribute |
| test_http_client.py:9:19:9:25 | ControlFlowNode for request | test_http_client.py:10:19:10:25 | ControlFlowNode for request |
| test_http_client.py:9:19:9:25 | ControlFlowNode for request | test_http_client.py:10:19:10:25 | ControlFlowNode for request |
| test_http_client.py:9:19:9:25 | ControlFlowNode for request | test_http_client.py:10:19:10:30 | ControlFlowNode for Attribute |
| test_http_client.py:9:19:9:25 | ControlFlowNode for request | test_http_client.py:10:19:10:30 | ControlFlowNode for Attribute |
| test_http_client.py:9:19:9:25 | ControlFlowNode for request | test_http_client.py:11:18:11:24 | ControlFlowNode for request |
| test_http_client.py:9:19:9:25 | ControlFlowNode for request | test_http_client.py:11:18:11:29 | ControlFlowNode for Attribute |
| test_http_client.py:9:19:9:30 | ControlFlowNode for Attribute | test_http_client.py:9:19:9:38 | ControlFlowNode for Subscript |
| test_http_client.py:9:19:9:30 | ControlFlowNode for Attribute | test_http_client.py:9:19:9:38 | ControlFlowNode for Subscript |
| test_http_client.py:9:19:9:38 | ControlFlowNode for Subscript | test_http_client.py:13:27:13:37 | ControlFlowNode for unsafe_host |
| test_http_client.py:9:19:9:38 | ControlFlowNode for Subscript | test_http_client.py:13:27:13:37 | ControlFlowNode for unsafe_host |
| test_http_client.py:9:19:9:38 | ControlFlowNode for Subscript | test_http_client.py:17:27:17:37 | ControlFlowNode for unsafe_host |
| test_http_client.py:9:19:9:38 | ControlFlowNode for Subscript | test_http_client.py:17:27:17:37 | ControlFlowNode for unsafe_host |
| test_http_client.py:10:19:10:25 | ControlFlowNode for request | test_http_client.py:10:19:10:30 | ControlFlowNode for Attribute |
| test_http_client.py:10:19:10:25 | ControlFlowNode for request | test_http_client.py:10:19:10:30 | ControlFlowNode for Attribute |
| test_http_client.py:10:19:10:25 | ControlFlowNode for request | test_http_client.py:11:18:11:24 | ControlFlowNode for request |
| test_http_client.py:10:19:10:25 | ControlFlowNode for request | test_http_client.py:11:18:11:29 | ControlFlowNode for Attribute |
| test_http_client.py:10:19:10:30 | ControlFlowNode for Attribute | test_http_client.py:10:19:10:38 | ControlFlowNode for Subscript |
| test_http_client.py:10:19:10:30 | ControlFlowNode for Attribute | test_http_client.py:10:19:10:38 | ControlFlowNode for Subscript |
| test_http_client.py:10:19:10:38 | ControlFlowNode for Subscript | test_http_client.py:14:25:14:35 | ControlFlowNode for unsafe_path |
| test_http_client.py:10:19:10:38 | ControlFlowNode for Subscript | test_http_client.py:14:25:14:35 | ControlFlowNode for unsafe_path |
| test_http_client.py:10:19:10:38 | ControlFlowNode for Subscript | test_http_client.py:21:25:21:35 | ControlFlowNode for unsafe_path |
| test_http_client.py:10:19:10:38 | ControlFlowNode for Subscript | test_http_client.py:21:25:21:35 | ControlFlowNode for unsafe_path |
| test_http_client.py:11:18:11:24 | ControlFlowNode for request | test_http_client.py:11:18:11:29 | ControlFlowNode for Attribute |
| test_http_client.py:11:18:11:29 | ControlFlowNode for Attribute | test_http_client.py:11:18:11:48 | ControlFlowNode for Subscript |
| test_http_client.py:11:18:11:48 | ControlFlowNode for Subscript | test_http_client.py:25:25:25:28 | ControlFlowNode for path |
| test_http_client.py:11:18:11:48 | ControlFlowNode for Subscript | test_http_client.py:29:25:29:28 | ControlFlowNode for path |
| test_requests.py:6:18:6:24 | ControlFlowNode for request | test_requests.py:6:18:6:29 | ControlFlowNode for Attribute |
| test_requests.py:6:18:6:24 | ControlFlowNode for request | test_requests.py:6:18:6:29 | ControlFlowNode for Attribute |
| test_requests.py:6:18:6:29 | ControlFlowNode for Attribute | test_requests.py:6:18:6:48 | ControlFlowNode for Subscript |
| test_requests.py:6:18:6:29 | ControlFlowNode for Attribute | test_requests.py:6:18:6:48 | ControlFlowNode for Subscript |
| test_requests.py:6:18:6:48 | ControlFlowNode for Subscript | test_requests.py:8:18:8:27 | ControlFlowNode for user_input |
| test_requests.py:6:18:6:48 | ControlFlowNode for Subscript | test_requests.py:8:18:8:27 | ControlFlowNode for user_input |
nodes
| full_partial_test.py:7:18:7:24 | ControlFlowNode for request | semmle.label | ControlFlowNode for request |
| full_partial_test.py:7:18:7:24 | ControlFlowNode for request | semmle.label | ControlFlowNode for request |
| full_partial_test.py:7:18:7:29 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute |
| full_partial_test.py:7:18:7:29 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute |
| full_partial_test.py:7:18:7:48 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript |
| full_partial_test.py:7:18:7:48 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript |
| full_partial_test.py:8:17:8:23 | ControlFlowNode for request | semmle.label | ControlFlowNode for request |
| full_partial_test.py:8:17:8:28 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute |
| full_partial_test.py:8:17:8:41 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript |
| full_partial_test.py:10:18:10:27 | ControlFlowNode for user_input | semmle.label | ControlFlowNode for user_input |
| full_partial_test.py:10:18:10:27 | ControlFlowNode for user_input | semmle.label | ControlFlowNode for user_input |
| full_partial_test.py:13:18:13:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url |
| full_partial_test.py:19:18:19:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url |
| full_partial_test.py:23:18:23:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url |
| full_partial_test.py:28:18:28:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url |
| full_partial_test.py:31:18:31:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url |
| full_partial_test.py:34:18:34:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url |
| full_partial_test.py:39:18:39:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url |
| full_partial_test.py:42:18:42:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url |
| full_partial_test.py:44:38:44:58 | ControlFlowNode for Tuple | semmle.label | ControlFlowNode for Tuple |
| full_partial_test.py:45:18:45:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url |
| full_partial_test.py:50:18:50:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url |
| full_partial_test.py:53:18:53:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url |
| full_partial_test.py:56:18:56:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url |
| full_partial_test.py:60:18:60:24 | ControlFlowNode for request | semmle.label | ControlFlowNode for request |
| full_partial_test.py:60:18:60:29 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute |
| full_partial_test.py:60:18:60:48 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript |
| full_partial_test.py:63:18:63:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url |
| full_partial_test.py:66:18:66:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url |
| full_partial_test.py:69:18:69:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url |
| full_partial_test.py:72:18:72:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url |
| full_partial_test.py:78:18:78:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url |
| full_partial_test.py:81:18:81:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url |
| test_http_client.py:9:19:9:25 | ControlFlowNode for request | semmle.label | ControlFlowNode for request |
| test_http_client.py:9:19:9:25 | ControlFlowNode for request | semmle.label | ControlFlowNode for request |
| test_http_client.py:9:19:9:30 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute |
| test_http_client.py:9:19:9:30 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute |
| test_http_client.py:9:19:9:38 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript |
| test_http_client.py:9:19:9:38 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript |
| test_http_client.py:10:19:10:25 | ControlFlowNode for request | semmle.label | ControlFlowNode for request |
| test_http_client.py:10:19:10:25 | ControlFlowNode for request | semmle.label | ControlFlowNode for request |
| test_http_client.py:10:19:10:30 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute |
| test_http_client.py:10:19:10:30 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute |
| test_http_client.py:10:19:10:38 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript |
| test_http_client.py:10:19:10:38 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript |
| test_http_client.py:11:18:11:24 | ControlFlowNode for request | semmle.label | ControlFlowNode for request |
| test_http_client.py:11:18:11:29 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute |
| test_http_client.py:11:18:11:48 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript |
| test_http_client.py:13:27:13:37 | ControlFlowNode for unsafe_host | semmle.label | ControlFlowNode for unsafe_host |
| test_http_client.py:13:27:13:37 | ControlFlowNode for unsafe_host | semmle.label | ControlFlowNode for unsafe_host |
| test_http_client.py:14:25:14:35 | ControlFlowNode for unsafe_path | semmle.label | ControlFlowNode for unsafe_path |
| test_http_client.py:14:25:14:35 | ControlFlowNode for unsafe_path | semmle.label | ControlFlowNode for unsafe_path |
| test_http_client.py:17:27:17:37 | ControlFlowNode for unsafe_host | semmle.label | ControlFlowNode for unsafe_host |
| test_http_client.py:17:27:17:37 | ControlFlowNode for unsafe_host | semmle.label | ControlFlowNode for unsafe_host |
| test_http_client.py:21:25:21:35 | ControlFlowNode for unsafe_path | semmle.label | ControlFlowNode for unsafe_path |
| test_http_client.py:21:25:21:35 | ControlFlowNode for unsafe_path | semmle.label | ControlFlowNode for unsafe_path |
| test_http_client.py:25:25:25:28 | ControlFlowNode for path | semmle.label | ControlFlowNode for path |
| test_http_client.py:29:25:29:28 | ControlFlowNode for path | semmle.label | ControlFlowNode for path |
| test_requests.py:6:18:6:24 | ControlFlowNode for request | semmle.label | ControlFlowNode for request |
| test_requests.py:6:18:6:24 | ControlFlowNode for request | semmle.label | ControlFlowNode for request |
| test_requests.py:6:18:6:29 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute |
| test_requests.py:6:18:6:29 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute |
| test_requests.py:6:18:6:48 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript |
| test_requests.py:6:18:6:48 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript |
| test_requests.py:8:18:8:27 | ControlFlowNode for user_input | semmle.label | ControlFlowNode for user_input |
| test_requests.py:8:18:8:27 | ControlFlowNode for user_input | semmle.label | ControlFlowNode for user_input |
subpaths
#select
| full_partial_test.py:10:18:10:27 | ControlFlowNode for user_input | full_partial_test.py:7:18:7:24 | ControlFlowNode for request | full_partial_test.py:10:18:10:27 | ControlFlowNode for user_input | The full URL of this request depends on $@. | full_partial_test.py:7:18:7:24 | ControlFlowNode for request | a user-provided value |
| test_http_client.py:13:27:13:37 | ControlFlowNode for unsafe_host | test_http_client.py:9:19:9:25 | ControlFlowNode for request | test_http_client.py:13:27:13:37 | ControlFlowNode for unsafe_host | The full URL of this request depends on $@. | test_http_client.py:9:19:9:25 | ControlFlowNode for request | a user-provided value |
| test_http_client.py:14:25:14:35 | ControlFlowNode for unsafe_path | test_http_client.py:9:19:9:25 | ControlFlowNode for request | test_http_client.py:14:25:14:35 | ControlFlowNode for unsafe_path | The full URL of this request depends on $@. | test_http_client.py:9:19:9:25 | ControlFlowNode for request | a user-provided value |
| test_http_client.py:14:25:14:35 | ControlFlowNode for unsafe_path | test_http_client.py:10:19:10:25 | ControlFlowNode for request | test_http_client.py:14:25:14:35 | ControlFlowNode for unsafe_path | The full URL of this request depends on $@. | test_http_client.py:10:19:10:25 | ControlFlowNode for request | a user-provided value |
| test_http_client.py:17:27:17:37 | ControlFlowNode for unsafe_host | test_http_client.py:9:19:9:25 | ControlFlowNode for request | test_http_client.py:17:27:17:37 | ControlFlowNode for unsafe_host | The full URL of this request depends on $@. | test_http_client.py:9:19:9:25 | ControlFlowNode for request | a user-provided value |
| test_http_client.py:21:25:21:35 | ControlFlowNode for unsafe_path | test_http_client.py:9:19:9:25 | ControlFlowNode for request | test_http_client.py:21:25:21:35 | ControlFlowNode for unsafe_path | The full URL of this request depends on $@. | test_http_client.py:9:19:9:25 | ControlFlowNode for request | a user-provided value |
| test_http_client.py:21:25:21:35 | ControlFlowNode for unsafe_path | test_http_client.py:10:19:10:25 | ControlFlowNode for request | test_http_client.py:21:25:21:35 | ControlFlowNode for unsafe_path | The full URL of this request depends on $@. | test_http_client.py:10:19:10:25 | ControlFlowNode for request | a user-provided value |
| test_requests.py:8:18:8:27 | ControlFlowNode for user_input | test_requests.py:6:18:6:24 | ControlFlowNode for request | test_requests.py:8:18:8:27 | ControlFlowNode for user_input | The full URL of this request depends on $@. | test_requests.py:6:18:6:24 | ControlFlowNode for request | a user-provided value |

Просмотреть файл

@ -0,0 +1 @@
Security/CWE-918/FullServerSideRequestForgery.ql

Просмотреть файл

@ -0,0 +1,167 @@
edges
| full_partial_test.py:7:18:7:24 | ControlFlowNode for request | full_partial_test.py:7:18:7:29 | ControlFlowNode for Attribute |
| full_partial_test.py:7:18:7:24 | ControlFlowNode for request | full_partial_test.py:7:18:7:29 | ControlFlowNode for Attribute |
| full_partial_test.py:7:18:7:24 | ControlFlowNode for request | full_partial_test.py:8:17:8:23 | ControlFlowNode for request |
| full_partial_test.py:7:18:7:24 | ControlFlowNode for request | full_partial_test.py:8:17:8:28 | ControlFlowNode for Attribute |
| full_partial_test.py:7:18:7:29 | ControlFlowNode for Attribute | full_partial_test.py:7:18:7:48 | ControlFlowNode for Subscript |
| full_partial_test.py:7:18:7:29 | ControlFlowNode for Attribute | full_partial_test.py:7:18:7:48 | ControlFlowNode for Subscript |
| full_partial_test.py:7:18:7:48 | ControlFlowNode for Subscript | full_partial_test.py:10:18:10:27 | ControlFlowNode for user_input |
| full_partial_test.py:7:18:7:48 | ControlFlowNode for Subscript | full_partial_test.py:10:18:10:27 | ControlFlowNode for user_input |
| full_partial_test.py:7:18:7:48 | ControlFlowNode for Subscript | full_partial_test.py:13:18:13:20 | ControlFlowNode for url |
| full_partial_test.py:7:18:7:48 | ControlFlowNode for Subscript | full_partial_test.py:19:18:19:20 | ControlFlowNode for url |
| full_partial_test.py:7:18:7:48 | ControlFlowNode for Subscript | full_partial_test.py:23:18:23:20 | ControlFlowNode for url |
| full_partial_test.py:7:18:7:48 | ControlFlowNode for Subscript | full_partial_test.py:28:18:28:20 | ControlFlowNode for url |
| full_partial_test.py:7:18:7:48 | ControlFlowNode for Subscript | full_partial_test.py:31:18:31:20 | ControlFlowNode for url |
| full_partial_test.py:7:18:7:48 | ControlFlowNode for Subscript | full_partial_test.py:34:18:34:20 | ControlFlowNode for url |
| full_partial_test.py:7:18:7:48 | ControlFlowNode for Subscript | full_partial_test.py:39:18:39:20 | ControlFlowNode for url |
| full_partial_test.py:7:18:7:48 | ControlFlowNode for Subscript | full_partial_test.py:42:18:42:20 | ControlFlowNode for url |
| full_partial_test.py:7:18:7:48 | ControlFlowNode for Subscript | full_partial_test.py:44:38:44:58 | ControlFlowNode for Tuple |
| full_partial_test.py:7:18:7:48 | ControlFlowNode for Subscript | full_partial_test.py:50:18:50:20 | ControlFlowNode for url |
| full_partial_test.py:7:18:7:48 | ControlFlowNode for Subscript | full_partial_test.py:53:18:53:20 | ControlFlowNode for url |
| full_partial_test.py:7:18:7:48 | ControlFlowNode for Subscript | full_partial_test.py:56:18:56:20 | ControlFlowNode for url |
| full_partial_test.py:8:17:8:23 | ControlFlowNode for request | full_partial_test.py:8:17:8:28 | ControlFlowNode for Attribute |
| full_partial_test.py:8:17:8:28 | ControlFlowNode for Attribute | full_partial_test.py:8:17:8:41 | ControlFlowNode for Subscript |
| full_partial_test.py:8:17:8:41 | ControlFlowNode for Subscript | full_partial_test.py:23:18:23:20 | ControlFlowNode for url |
| full_partial_test.py:8:17:8:41 | ControlFlowNode for Subscript | full_partial_test.py:34:18:34:20 | ControlFlowNode for url |
| full_partial_test.py:8:17:8:41 | ControlFlowNode for Subscript | full_partial_test.py:44:38:44:58 | ControlFlowNode for Tuple |
| full_partial_test.py:8:17:8:41 | ControlFlowNode for Subscript | full_partial_test.py:56:18:56:20 | ControlFlowNode for url |
| full_partial_test.py:44:38:44:58 | ControlFlowNode for Tuple | full_partial_test.py:45:18:45:20 | ControlFlowNode for url |
| full_partial_test.py:60:18:60:24 | ControlFlowNode for request | full_partial_test.py:60:18:60:29 | ControlFlowNode for Attribute |
| full_partial_test.py:60:18:60:29 | ControlFlowNode for Attribute | full_partial_test.py:60:18:60:48 | ControlFlowNode for Subscript |
| full_partial_test.py:60:18:60:48 | ControlFlowNode for Subscript | full_partial_test.py:63:18:63:20 | ControlFlowNode for url |
| full_partial_test.py:60:18:60:48 | ControlFlowNode for Subscript | full_partial_test.py:66:18:66:20 | ControlFlowNode for url |
| full_partial_test.py:60:18:60:48 | ControlFlowNode for Subscript | full_partial_test.py:69:18:69:20 | ControlFlowNode for url |
| full_partial_test.py:60:18:60:48 | ControlFlowNode for Subscript | full_partial_test.py:72:18:72:20 | ControlFlowNode for url |
| full_partial_test.py:60:18:60:48 | ControlFlowNode for Subscript | full_partial_test.py:78:18:78:20 | ControlFlowNode for url |
| full_partial_test.py:60:18:60:48 | ControlFlowNode for Subscript | full_partial_test.py:81:18:81:20 | ControlFlowNode for url |
| test_http_client.py:9:19:9:25 | ControlFlowNode for request | test_http_client.py:9:19:9:30 | ControlFlowNode for Attribute |
| test_http_client.py:9:19:9:25 | ControlFlowNode for request | test_http_client.py:9:19:9:30 | ControlFlowNode for Attribute |
| test_http_client.py:9:19:9:25 | ControlFlowNode for request | test_http_client.py:10:19:10:25 | ControlFlowNode for request |
| test_http_client.py:9:19:9:25 | ControlFlowNode for request | test_http_client.py:10:19:10:25 | ControlFlowNode for request |
| test_http_client.py:9:19:9:25 | ControlFlowNode for request | test_http_client.py:10:19:10:30 | ControlFlowNode for Attribute |
| test_http_client.py:9:19:9:25 | ControlFlowNode for request | test_http_client.py:10:19:10:30 | ControlFlowNode for Attribute |
| test_http_client.py:9:19:9:25 | ControlFlowNode for request | test_http_client.py:11:18:11:24 | ControlFlowNode for request |
| test_http_client.py:9:19:9:25 | ControlFlowNode for request | test_http_client.py:11:18:11:29 | ControlFlowNode for Attribute |
| test_http_client.py:9:19:9:30 | ControlFlowNode for Attribute | test_http_client.py:9:19:9:38 | ControlFlowNode for Subscript |
| test_http_client.py:9:19:9:30 | ControlFlowNode for Attribute | test_http_client.py:9:19:9:38 | ControlFlowNode for Subscript |
| test_http_client.py:9:19:9:38 | ControlFlowNode for Subscript | test_http_client.py:13:27:13:37 | ControlFlowNode for unsafe_host |
| test_http_client.py:9:19:9:38 | ControlFlowNode for Subscript | test_http_client.py:13:27:13:37 | ControlFlowNode for unsafe_host |
| test_http_client.py:9:19:9:38 | ControlFlowNode for Subscript | test_http_client.py:17:27:17:37 | ControlFlowNode for unsafe_host |
| test_http_client.py:9:19:9:38 | ControlFlowNode for Subscript | test_http_client.py:17:27:17:37 | ControlFlowNode for unsafe_host |
| test_http_client.py:10:19:10:25 | ControlFlowNode for request | test_http_client.py:10:19:10:30 | ControlFlowNode for Attribute |
| test_http_client.py:10:19:10:25 | ControlFlowNode for request | test_http_client.py:10:19:10:30 | ControlFlowNode for Attribute |
| test_http_client.py:10:19:10:25 | ControlFlowNode for request | test_http_client.py:11:18:11:24 | ControlFlowNode for request |
| test_http_client.py:10:19:10:25 | ControlFlowNode for request | test_http_client.py:11:18:11:29 | ControlFlowNode for Attribute |
| test_http_client.py:10:19:10:30 | ControlFlowNode for Attribute | test_http_client.py:10:19:10:38 | ControlFlowNode for Subscript |
| test_http_client.py:10:19:10:30 | ControlFlowNode for Attribute | test_http_client.py:10:19:10:38 | ControlFlowNode for Subscript |
| test_http_client.py:10:19:10:38 | ControlFlowNode for Subscript | test_http_client.py:14:25:14:35 | ControlFlowNode for unsafe_path |
| test_http_client.py:10:19:10:38 | ControlFlowNode for Subscript | test_http_client.py:14:25:14:35 | ControlFlowNode for unsafe_path |
| test_http_client.py:10:19:10:38 | ControlFlowNode for Subscript | test_http_client.py:21:25:21:35 | ControlFlowNode for unsafe_path |
| test_http_client.py:10:19:10:38 | ControlFlowNode for Subscript | test_http_client.py:21:25:21:35 | ControlFlowNode for unsafe_path |
| test_http_client.py:11:18:11:24 | ControlFlowNode for request | test_http_client.py:11:18:11:29 | ControlFlowNode for Attribute |
| test_http_client.py:11:18:11:29 | ControlFlowNode for Attribute | test_http_client.py:11:18:11:48 | ControlFlowNode for Subscript |
| test_http_client.py:11:18:11:48 | ControlFlowNode for Subscript | test_http_client.py:25:25:25:28 | ControlFlowNode for path |
| test_http_client.py:11:18:11:48 | ControlFlowNode for Subscript | test_http_client.py:29:25:29:28 | ControlFlowNode for path |
| test_requests.py:6:18:6:24 | ControlFlowNode for request | test_requests.py:6:18:6:29 | ControlFlowNode for Attribute |
| test_requests.py:6:18:6:24 | ControlFlowNode for request | test_requests.py:6:18:6:29 | ControlFlowNode for Attribute |
| test_requests.py:6:18:6:29 | ControlFlowNode for Attribute | test_requests.py:6:18:6:48 | ControlFlowNode for Subscript |
| test_requests.py:6:18:6:29 | ControlFlowNode for Attribute | test_requests.py:6:18:6:48 | ControlFlowNode for Subscript |
| test_requests.py:6:18:6:48 | ControlFlowNode for Subscript | test_requests.py:8:18:8:27 | ControlFlowNode for user_input |
| test_requests.py:6:18:6:48 | ControlFlowNode for Subscript | test_requests.py:8:18:8:27 | ControlFlowNode for user_input |
nodes
| full_partial_test.py:7:18:7:24 | ControlFlowNode for request | semmle.label | ControlFlowNode for request |
| full_partial_test.py:7:18:7:24 | ControlFlowNode for request | semmle.label | ControlFlowNode for request |
| full_partial_test.py:7:18:7:29 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute |
| full_partial_test.py:7:18:7:29 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute |
| full_partial_test.py:7:18:7:48 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript |
| full_partial_test.py:7:18:7:48 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript |
| full_partial_test.py:8:17:8:23 | ControlFlowNode for request | semmle.label | ControlFlowNode for request |
| full_partial_test.py:8:17:8:28 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute |
| full_partial_test.py:8:17:8:41 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript |
| full_partial_test.py:10:18:10:27 | ControlFlowNode for user_input | semmle.label | ControlFlowNode for user_input |
| full_partial_test.py:10:18:10:27 | ControlFlowNode for user_input | semmle.label | ControlFlowNode for user_input |
| full_partial_test.py:13:18:13:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url |
| full_partial_test.py:19:18:19:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url |
| full_partial_test.py:23:18:23:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url |
| full_partial_test.py:28:18:28:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url |
| full_partial_test.py:31:18:31:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url |
| full_partial_test.py:34:18:34:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url |
| full_partial_test.py:39:18:39:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url |
| full_partial_test.py:42:18:42:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url |
| full_partial_test.py:44:38:44:58 | ControlFlowNode for Tuple | semmle.label | ControlFlowNode for Tuple |
| full_partial_test.py:45:18:45:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url |
| full_partial_test.py:50:18:50:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url |
| full_partial_test.py:53:18:53:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url |
| full_partial_test.py:56:18:56:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url |
| full_partial_test.py:60:18:60:24 | ControlFlowNode for request | semmle.label | ControlFlowNode for request |
| full_partial_test.py:60:18:60:29 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute |
| full_partial_test.py:60:18:60:48 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript |
| full_partial_test.py:63:18:63:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url |
| full_partial_test.py:66:18:66:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url |
| full_partial_test.py:69:18:69:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url |
| full_partial_test.py:72:18:72:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url |
| full_partial_test.py:78:18:78:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url |
| full_partial_test.py:81:18:81:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url |
| test_http_client.py:9:19:9:25 | ControlFlowNode for request | semmle.label | ControlFlowNode for request |
| test_http_client.py:9:19:9:25 | ControlFlowNode for request | semmle.label | ControlFlowNode for request |
| test_http_client.py:9:19:9:30 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute |
| test_http_client.py:9:19:9:30 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute |
| test_http_client.py:9:19:9:38 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript |
| test_http_client.py:9:19:9:38 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript |
| test_http_client.py:10:19:10:25 | ControlFlowNode for request | semmle.label | ControlFlowNode for request |
| test_http_client.py:10:19:10:25 | ControlFlowNode for request | semmle.label | ControlFlowNode for request |
| test_http_client.py:10:19:10:30 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute |
| test_http_client.py:10:19:10:30 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute |
| test_http_client.py:10:19:10:38 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript |
| test_http_client.py:10:19:10:38 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript |
| test_http_client.py:11:18:11:24 | ControlFlowNode for request | semmle.label | ControlFlowNode for request |
| test_http_client.py:11:18:11:29 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute |
| test_http_client.py:11:18:11:48 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript |
| test_http_client.py:13:27:13:37 | ControlFlowNode for unsafe_host | semmle.label | ControlFlowNode for unsafe_host |
| test_http_client.py:13:27:13:37 | ControlFlowNode for unsafe_host | semmle.label | ControlFlowNode for unsafe_host |
| test_http_client.py:14:25:14:35 | ControlFlowNode for unsafe_path | semmle.label | ControlFlowNode for unsafe_path |
| test_http_client.py:14:25:14:35 | ControlFlowNode for unsafe_path | semmle.label | ControlFlowNode for unsafe_path |
| test_http_client.py:17:27:17:37 | ControlFlowNode for unsafe_host | semmle.label | ControlFlowNode for unsafe_host |
| test_http_client.py:17:27:17:37 | ControlFlowNode for unsafe_host | semmle.label | ControlFlowNode for unsafe_host |
| test_http_client.py:21:25:21:35 | ControlFlowNode for unsafe_path | semmle.label | ControlFlowNode for unsafe_path |
| test_http_client.py:21:25:21:35 | ControlFlowNode for unsafe_path | semmle.label | ControlFlowNode for unsafe_path |
| test_http_client.py:25:25:25:28 | ControlFlowNode for path | semmle.label | ControlFlowNode for path |
| test_http_client.py:29:25:29:28 | ControlFlowNode for path | semmle.label | ControlFlowNode for path |
| test_requests.py:6:18:6:24 | ControlFlowNode for request | semmle.label | ControlFlowNode for request |
| test_requests.py:6:18:6:24 | ControlFlowNode for request | semmle.label | ControlFlowNode for request |
| test_requests.py:6:18:6:29 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute |
| test_requests.py:6:18:6:29 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute |
| test_requests.py:6:18:6:48 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript |
| test_requests.py:6:18:6:48 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript |
| test_requests.py:8:18:8:27 | ControlFlowNode for user_input | semmle.label | ControlFlowNode for user_input |
| test_requests.py:8:18:8:27 | ControlFlowNode for user_input | semmle.label | ControlFlowNode for user_input |
subpaths
#select
| full_partial_test.py:13:18:13:20 | ControlFlowNode for url | full_partial_test.py:7:18:7:24 | ControlFlowNode for request | full_partial_test.py:13:18:13:20 | ControlFlowNode for url | Part of the URL of this request depends on $@. | full_partial_test.py:7:18:7:24 | ControlFlowNode for request | a user-provided value |
| full_partial_test.py:19:18:19:20 | ControlFlowNode for url | full_partial_test.py:7:18:7:24 | ControlFlowNode for request | full_partial_test.py:19:18:19:20 | ControlFlowNode for url | Part of the URL of this request depends on $@. | full_partial_test.py:7:18:7:24 | ControlFlowNode for request | a user-provided value |
| full_partial_test.py:23:18:23:20 | ControlFlowNode for url | full_partial_test.py:7:18:7:24 | ControlFlowNode for request | full_partial_test.py:23:18:23:20 | ControlFlowNode for url | Part of the URL of this request depends on $@. | full_partial_test.py:7:18:7:24 | ControlFlowNode for request | a user-provided value |
| full_partial_test.py:23:18:23:20 | ControlFlowNode for url | full_partial_test.py:8:17:8:23 | ControlFlowNode for request | full_partial_test.py:23:18:23:20 | ControlFlowNode for url | Part of the URL of this request depends on $@. | full_partial_test.py:8:17:8:23 | ControlFlowNode for request | a user-provided value |
| full_partial_test.py:28:18:28:20 | ControlFlowNode for url | full_partial_test.py:7:18:7:24 | ControlFlowNode for request | full_partial_test.py:28:18:28:20 | ControlFlowNode for url | Part of the URL of this request depends on $@. | full_partial_test.py:7:18:7:24 | ControlFlowNode for request | a user-provided value |
| full_partial_test.py:31:18:31:20 | ControlFlowNode for url | full_partial_test.py:7:18:7:24 | ControlFlowNode for request | full_partial_test.py:31:18:31:20 | ControlFlowNode for url | Part of the URL of this request depends on $@. | full_partial_test.py:7:18:7:24 | ControlFlowNode for request | a user-provided value |
| full_partial_test.py:34:18:34:20 | ControlFlowNode for url | full_partial_test.py:7:18:7:24 | ControlFlowNode for request | full_partial_test.py:34:18:34:20 | ControlFlowNode for url | Part of the URL of this request depends on $@. | full_partial_test.py:7:18:7:24 | ControlFlowNode for request | a user-provided value |
| full_partial_test.py:34:18:34:20 | ControlFlowNode for url | full_partial_test.py:8:17:8:23 | ControlFlowNode for request | full_partial_test.py:34:18:34:20 | ControlFlowNode for url | Part of the URL of this request depends on $@. | full_partial_test.py:8:17:8:23 | ControlFlowNode for request | a user-provided value |
| full_partial_test.py:39:18:39:20 | ControlFlowNode for url | full_partial_test.py:7:18:7:24 | ControlFlowNode for request | full_partial_test.py:39:18:39:20 | ControlFlowNode for url | Part of the URL of this request depends on $@. | full_partial_test.py:7:18:7:24 | ControlFlowNode for request | a user-provided value |
| full_partial_test.py:42:18:42:20 | ControlFlowNode for url | full_partial_test.py:7:18:7:24 | ControlFlowNode for request | full_partial_test.py:42:18:42:20 | ControlFlowNode for url | Part of the URL of this request depends on $@. | full_partial_test.py:7:18:7:24 | ControlFlowNode for request | a user-provided value |
| full_partial_test.py:45:18:45:20 | ControlFlowNode for url | full_partial_test.py:7:18:7:24 | ControlFlowNode for request | full_partial_test.py:45:18:45:20 | ControlFlowNode for url | Part of the URL of this request depends on $@. | full_partial_test.py:7:18:7:24 | ControlFlowNode for request | a user-provided value |
| full_partial_test.py:45:18:45:20 | ControlFlowNode for url | full_partial_test.py:8:17:8:23 | ControlFlowNode for request | full_partial_test.py:45:18:45:20 | ControlFlowNode for url | Part of the URL of this request depends on $@. | full_partial_test.py:8:17:8:23 | ControlFlowNode for request | a user-provided value |
| full_partial_test.py:50:18:50:20 | ControlFlowNode for url | full_partial_test.py:7:18:7:24 | ControlFlowNode for request | full_partial_test.py:50:18:50:20 | ControlFlowNode for url | Part of the URL of this request depends on $@. | full_partial_test.py:7:18:7:24 | ControlFlowNode for request | a user-provided value |
| full_partial_test.py:53:18:53:20 | ControlFlowNode for url | full_partial_test.py:7:18:7:24 | ControlFlowNode for request | full_partial_test.py:53:18:53:20 | ControlFlowNode for url | Part of the URL of this request depends on $@. | full_partial_test.py:7:18:7:24 | ControlFlowNode for request | a user-provided value |
| full_partial_test.py:56:18:56:20 | ControlFlowNode for url | full_partial_test.py:7:18:7:24 | ControlFlowNode for request | full_partial_test.py:56:18:56:20 | ControlFlowNode for url | Part of the URL of this request depends on $@. | full_partial_test.py:7:18:7:24 | ControlFlowNode for request | a user-provided value |
| full_partial_test.py:56:18:56:20 | ControlFlowNode for url | full_partial_test.py:8:17:8:23 | ControlFlowNode for request | full_partial_test.py:56:18:56:20 | ControlFlowNode for url | Part of the URL of this request depends on $@. | full_partial_test.py:8:17:8:23 | ControlFlowNode for request | a user-provided value |
| full_partial_test.py:63:18:63:20 | ControlFlowNode for url | full_partial_test.py:60:18:60:24 | ControlFlowNode for request | full_partial_test.py:63:18:63:20 | ControlFlowNode for url | Part of the URL of this request depends on $@. | full_partial_test.py:60:18:60:24 | ControlFlowNode for request | a user-provided value |
| full_partial_test.py:66:18:66:20 | ControlFlowNode for url | full_partial_test.py:60:18:60:24 | ControlFlowNode for request | full_partial_test.py:66:18:66:20 | ControlFlowNode for url | Part of the URL of this request depends on $@. | full_partial_test.py:60:18:60:24 | ControlFlowNode for request | a user-provided value |
| full_partial_test.py:69:18:69:20 | ControlFlowNode for url | full_partial_test.py:60:18:60:24 | ControlFlowNode for request | full_partial_test.py:69:18:69:20 | ControlFlowNode for url | Part of the URL of this request depends on $@. | full_partial_test.py:60:18:60:24 | ControlFlowNode for request | a user-provided value |
| full_partial_test.py:72:18:72:20 | ControlFlowNode for url | full_partial_test.py:60:18:60:24 | ControlFlowNode for request | full_partial_test.py:72:18:72:20 | ControlFlowNode for url | Part of the URL of this request depends on $@. | full_partial_test.py:60:18:60:24 | ControlFlowNode for request | a user-provided value |
| full_partial_test.py:78:18:78:20 | ControlFlowNode for url | full_partial_test.py:60:18:60:24 | ControlFlowNode for request | full_partial_test.py:78:18:78:20 | ControlFlowNode for url | Part of the URL of this request depends on $@. | full_partial_test.py:60:18:60:24 | ControlFlowNode for request | a user-provided value |
| full_partial_test.py:81:18:81:20 | ControlFlowNode for url | full_partial_test.py:60:18:60:24 | ControlFlowNode for request | full_partial_test.py:81:18:81:20 | ControlFlowNode for url | Part of the URL of this request depends on $@. | full_partial_test.py:60:18:60:24 | ControlFlowNode for request | a user-provided value |
| test_http_client.py:25:25:25:28 | ControlFlowNode for path | test_http_client.py:9:19:9:25 | ControlFlowNode for request | test_http_client.py:25:25:25:28 | ControlFlowNode for path | Part of the URL of this request depends on $@. | test_http_client.py:9:19:9:25 | ControlFlowNode for request | a user-provided value |
| test_http_client.py:25:25:25:28 | ControlFlowNode for path | test_http_client.py:10:19:10:25 | ControlFlowNode for request | test_http_client.py:25:25:25:28 | ControlFlowNode for path | Part of the URL of this request depends on $@. | test_http_client.py:10:19:10:25 | ControlFlowNode for request | a user-provided value |
| test_http_client.py:25:25:25:28 | ControlFlowNode for path | test_http_client.py:11:18:11:24 | ControlFlowNode for request | test_http_client.py:25:25:25:28 | ControlFlowNode for path | Part of the URL of this request depends on $@. | test_http_client.py:11:18:11:24 | ControlFlowNode for request | a user-provided value |
| test_http_client.py:29:25:29:28 | ControlFlowNode for path | test_http_client.py:9:19:9:25 | ControlFlowNode for request | test_http_client.py:29:25:29:28 | ControlFlowNode for path | Part of the URL of this request depends on $@. | test_http_client.py:9:19:9:25 | ControlFlowNode for request | a user-provided value |
| test_http_client.py:29:25:29:28 | ControlFlowNode for path | test_http_client.py:10:19:10:25 | ControlFlowNode for request | test_http_client.py:29:25:29:28 | ControlFlowNode for path | Part of the URL of this request depends on $@. | test_http_client.py:10:19:10:25 | ControlFlowNode for request | a user-provided value |
| test_http_client.py:29:25:29:28 | ControlFlowNode for path | test_http_client.py:11:18:11:24 | ControlFlowNode for request | test_http_client.py:29:25:29:28 | ControlFlowNode for path | Part of the URL of this request depends on $@. | test_http_client.py:11:18:11:24 | ControlFlowNode for request | a user-provided value |

Просмотреть файл

@ -0,0 +1 @@
Security/CWE-918/PartialServerSideRequestForgery.ql

Просмотреть файл

@ -0,0 +1,81 @@
from flask import request
import requests
def full_ssrf():
user_input = request.args['untrusted_input']
query_val = request.args['query_val']
requests.get(user_input) # NOT OK -- user has full control
url = "https://" + user_input
requests.get(url) # NOT OK -- user has full control
# although the path `/foo` is added here, this can be circumvented such that the
# final URL is `https://evil.com/#/foo" -- since the fragment (#) is not sent to the
# server.
url = "https://" + user_input + "/foo"
requests.get(url) # NOT OK -- user has full control
# this might seem like a dummy test, but it serves to check how our sanitizers work.
url = "https://" + user_input + "/foo?key=" + query_val
requests.get(url) # NOT OK -- user has full control
# using .format
url = "https://{}".format(user_input)
requests.get(url) # NOT OK -- user has full control
url = "https://{}/foo".format(user_input)
requests.get(url) # NOT OK -- user has full control
url = "https://{}/foo?key={}".format(user_input, query_val)
requests.get(url) # NOT OK -- user has full control
# using %-formatting
url = "https://%s" % user_input
requests.get(url) # NOT OK -- user has full control
url = "https://%s/foo" % user_input
requests.get(url) # NOT OK -- user has full control
url = "https://%s/foo/key=%s" % (user_input, query_val)
requests.get(url) # NOT OK -- user has full control
# using f-strings
url = f"https://{user_input}"
requests.get(url) # NOT OK -- user has full control
url = f"https://{user_input}/foo"
requests.get(url) # NOT OK -- user has full control
url = f"https://{user_input}/foo?key={query_val}"
requests.get(url) # NOT OK -- user has full control
def partial_ssrf():
user_input = request.args['untrusted_input']
url = "https://example.com/foo?" + user_input
requests.get(url) # NOT OK -- user controls query parameters
url = "https://example.com/" + user_input
requests.get(url) # NOT OK -- user controls path
url = "https://example.com/" + user_input
requests.get(url) # NOT OK -- user controls path
url = "https://example.com/foo#{}".format(user_input)
requests.get(url) # NOT OK -- user contollred fragment
# this is probably the least interesting one, since it's only the fragment that is
# controlled
url = "https://example.com/foo#%s" % user_input
requests.get(url) # NOT OK -- user contollred fragment
url = f"https://example.com/foo#{user_input}"
requests.get(url) # NOT OK -- user only controlled fragment

Просмотреть файл

@ -0,0 +1 @@
semmle-extractor-options: --lang=3 --max-import-depth=1

Просмотреть файл

@ -0,0 +1,29 @@
from flask import Flask, request
from http.client import HTTPConnection
app = Flask(__name__)
@app.route("/ssrf_test") # $ routeSetup="/ssrf_test"
def ssrf_test():
unsafe_host = request.args["host"]
unsafe_path = request.args["path"]
user_input = request.args['untrusted_input']
conn = HTTPConnection(unsafe_host)
conn.request("GET", unsafe_path) # NOT OK -- user has full control
# the rest are partial SSRF
conn = HTTPConnection(unsafe_host)
conn.request("GET", "/foo") # NOT OK -- user controlled domain
conn = HTTPConnection("example.com")
conn.request("GET", unsafe_path) # NOT OK -- user controlled path
path = "foo?" + user_input
conn = HTTPConnection("example.com")
conn.request("GET", path) # NOT OK -- user controlled query parameters
path = "foo#" + user_input
conn = HTTPConnection("example.com")
conn.request("GET", path) # NOT OK -- user controlled fragment

Просмотреть файл

@ -0,0 +1,11 @@
from flask import request
import requests
def ssrf_test():
user_input = request.args['untrusted_input']
requests.get(user_input) # NOT OK -- user has full control
# since `requests`` always uses complete URLs, it's not interesting to test more of
# the framework directly. See `full_partial_test.py` for different ways to do SSRF.