JS: Port ClientSideRequestForgery

This commit is contained in:
Asger F
2023-10-04 21:34:26 +02:00
parent b2216627be
commit 92816b1c9a
4 changed files with 63 additions and 42 deletions

View File

@@ -14,7 +14,34 @@ import RequestForgeryCustomizations::RequestForgery
/**
* A taint tracking configuration for client-side request forgery.
*/
class Configuration extends TaintTracking::Configuration {
module ClientSideRequestForgeryConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) {
exists(Source src |
source = src and
not src.isServerSide()
)
}
predicate isSink(DataFlow::Node sink) { sink instanceof Sink }
predicate isBarrier(DataFlow::Node node) { node instanceof Sanitizer }
predicate isBarrierOut(DataFlow::Node node) { sanitizingPrefixEdge(node, _) }
predicate isAdditionalFlowStep(DataFlow::Node pred, DataFlow::Node succ) {
isAdditionalRequestForgeryStep(pred, succ)
}
}
/**
* Taint tracking for client-side request forgery.
*/
module ClientSideRequestForgeryFlow = TaintTracking::Global<ClientSideRequestForgeryConfig>;
/**
* DEPRECATED. Use the `ClientSideRequestForgeryFlow` module instead.
*/
deprecated class Configuration extends TaintTracking::Configuration {
Configuration() { this = "ClientSideRequestForgery" }
override predicate isSource(DataFlow::Node source) {

View File

@@ -13,11 +13,13 @@
import javascript
import semmle.javascript.security.dataflow.ClientSideRequestForgeryQuery
import DataFlow::PathGraph
import ClientSideRequestForgeryFlow::PathGraph
from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink, DataFlow::Node request
from
ClientSideRequestForgeryFlow::PathNode source, ClientSideRequestForgeryFlow::PathNode sink,
DataFlow::Node request
where
cfg.hasFlowPath(source, sink) and
ClientSideRequestForgeryFlow::flowPath(source, sink) and
request = sink.getNode().(Sink).getARequest()
select request, source, sink, "The $@ of this request depends on a $@.", sink.getNode(),
sink.getNode().(Sink).getKind(), source, "user-provided value"

View File

@@ -1,50 +1,34 @@
nodes
| clientSide.js:11:11:11:53 | query |
| clientSide.js:11:19:11:40 | window. ... .search |
| clientSide.js:11:19:11:40 | window. ... .search |
| clientSide.js:11:19:11:53 | window. ... ring(1) |
| clientSide.js:12:13:12:54 | 'https: ... + '/id' |
| clientSide.js:12:13:12:54 | 'https: ... + '/id' |
| clientSide.js:12:42:12:46 | query |
| clientSide.js:14:13:14:63 | 'https: ... .search |
| clientSide.js:14:13:14:63 | 'https: ... .search |
| clientSide.js:14:42:14:63 | window. ... .search |
| clientSide.js:14:42:14:63 | window. ... .search |
| clientSide.js:16:11:16:54 | fragment |
| clientSide.js:16:22:16:41 | window.location.hash |
| clientSide.js:16:22:16:41 | window.location.hash |
| clientSide.js:16:22:16:54 | window. ... ring(1) |
| clientSide.js:17:13:17:57 | 'https: ... + '/id' |
| clientSide.js:17:13:17:57 | 'https: ... + '/id' |
| clientSide.js:17:42:17:49 | fragment |
| clientSide.js:20:11:20:28 | name |
| clientSide.js:20:18:20:28 | window.name |
| clientSide.js:20:18:20:28 | window.name |
| clientSide.js:21:13:21:53 | 'https: ... + '/id' |
| clientSide.js:21:13:21:53 | 'https: ... + '/id' |
| clientSide.js:21:42:21:45 | name |
edges
| clientSide.js:11:11:11:53 | query | clientSide.js:12:42:12:46 | query |
| clientSide.js:11:19:11:40 | window. ... .search | clientSide.js:11:19:11:53 | window. ... ring(1) |
| clientSide.js:11:19:11:40 | window. ... .search | clientSide.js:11:19:11:53 | window. ... ring(1) |
| clientSide.js:11:19:11:53 | window. ... ring(1) | clientSide.js:11:11:11:53 | query |
| clientSide.js:12:42:12:46 | query | clientSide.js:12:13:12:54 | 'https: ... + '/id' |
| clientSide.js:12:42:12:46 | query | clientSide.js:12:13:12:54 | 'https: ... + '/id' |
| clientSide.js:14:42:14:63 | window. ... .search | clientSide.js:14:13:14:63 | 'https: ... .search |
| clientSide.js:14:42:14:63 | window. ... .search | clientSide.js:14:13:14:63 | 'https: ... .search |
| clientSide.js:14:42:14:63 | window. ... .search | clientSide.js:14:13:14:63 | 'https: ... .search |
| clientSide.js:14:42:14:63 | window. ... .search | clientSide.js:14:13:14:63 | 'https: ... .search |
| clientSide.js:16:11:16:54 | fragment | clientSide.js:17:42:17:49 | fragment |
| clientSide.js:16:22:16:41 | window.location.hash | clientSide.js:16:22:16:54 | window. ... ring(1) |
| clientSide.js:16:22:16:41 | window.location.hash | clientSide.js:16:22:16:54 | window. ... ring(1) |
| clientSide.js:16:22:16:54 | window. ... ring(1) | clientSide.js:16:11:16:54 | fragment |
| clientSide.js:17:42:17:49 | fragment | clientSide.js:17:13:17:57 | 'https: ... + '/id' |
| clientSide.js:17:42:17:49 | fragment | clientSide.js:17:13:17:57 | 'https: ... + '/id' |
| clientSide.js:20:11:20:28 | name | clientSide.js:21:42:21:45 | name |
| clientSide.js:20:18:20:28 | window.name | clientSide.js:20:11:20:28 | name |
| clientSide.js:20:18:20:28 | window.name | clientSide.js:20:11:20:28 | name |
| clientSide.js:21:42:21:45 | name | clientSide.js:21:13:21:53 | 'https: ... + '/id' |
| clientSide.js:21:42:21:45 | name | clientSide.js:21:13:21:53 | 'https: ... + '/id' |
nodes
| clientSide.js:11:11:11:53 | query | semmle.label | query |
| clientSide.js:11:19:11:40 | window. ... .search | semmle.label | window. ... .search |
| clientSide.js:11:19:11:53 | window. ... ring(1) | semmle.label | window. ... ring(1) |
| clientSide.js:12:13:12:54 | 'https: ... + '/id' | semmle.label | 'https: ... + '/id' |
| clientSide.js:12:42:12:46 | query | semmle.label | query |
| clientSide.js:14:13:14:63 | 'https: ... .search | semmle.label | 'https: ... .search |
| clientSide.js:14:42:14:63 | window. ... .search | semmle.label | window. ... .search |
| clientSide.js:16:11:16:54 | fragment | semmle.label | fragment |
| clientSide.js:16:22:16:41 | window.location.hash | semmle.label | window.location.hash |
| clientSide.js:16:22:16:54 | window. ... ring(1) | semmle.label | window. ... ring(1) |
| clientSide.js:17:13:17:57 | 'https: ... + '/id' | semmle.label | 'https: ... + '/id' |
| clientSide.js:17:42:17:49 | fragment | semmle.label | fragment |
| clientSide.js:20:11:20:28 | name | semmle.label | name |
| clientSide.js:20:18:20:28 | window.name | semmle.label | window.name |
| clientSide.js:21:13:21:53 | 'https: ... + '/id' | semmle.label | 'https: ... + '/id' |
| clientSide.js:21:42:21:45 | name | semmle.label | name |
subpaths
#select
| clientSide.js:12:5:12:55 | request ... '/id') | clientSide.js:11:19:11:40 | window. ... .search | clientSide.js:12:13:12:54 | 'https: ... + '/id' | The $@ of this request depends on a $@. | clientSide.js:12:13:12:54 | 'https: ... + '/id' | URL | clientSide.js:11:19:11:40 | window. ... .search | user-provided value |
| clientSide.js:14:5:14:64 | request ... search) | clientSide.js:14:42:14:63 | window. ... .search | clientSide.js:14:13:14:63 | 'https: ... .search | The $@ of this request depends on a $@. | clientSide.js:14:13:14:63 | 'https: ... .search | URL | clientSide.js:14:42:14:63 | window. ... .search | user-provided value |

View File

@@ -4,14 +4,22 @@ import semmle.javascript.security.dataflow.ClientSideRequestForgeryQuery as Clie
import testUtilities.ConsistencyChecking
query predicate resultInWrongFile(DataFlow::Node node) {
exists(DataFlow::Configuration cfg, string filePattern |
cfg instanceof RequestForgery::Configuration and
exists(string filePattern |
RequestForgery::RequestForgeryFlow::flowTo(node) and
filePattern = ".*serverSide.*"
or
cfg instanceof ClientSideRequestForgery::Configuration and
ClientSideRequestForgery::ClientSideRequestForgeryFlow::flowTo(node) and
filePattern = ".*clientSide.*"
|
cfg.hasFlow(_, node) and
not node.getFile().getRelativePath().regexpMatch(filePattern)
)
}
class Consistency extends ConsistencyConfiguration {
Consistency() { this = "Consistency" }
override DataFlow::Node getAnAlert() {
RequestForgery::RequestForgeryFlow::flowTo(result) or
ClientSideRequestForgery::ClientSideRequestForgeryFlow::flowTo(result)
}
}