Skip to content

Commit 260638c

Browse files
committed
JS: Add ClientSideRequestForgery and split request-forgery results between the two
1 parent f710850 commit 260638c

File tree

4 files changed

+84
-9
lines changed

4 files changed

+84
-9
lines changed
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
/**
2+
* Provides a taint-tracking configuration for reasoning about request
3+
* forgery.
4+
*
5+
* Note, for performance reasons: only import this file if
6+
* `RequestForgery::Configuration` is needed, otherwise
7+
* `RequestForgeryCustomizations` should be imported instead.
8+
*/
9+
10+
import javascript
11+
import UrlConcatenation
12+
import RequestForgeryCustomizations::RequestForgery
13+
14+
/**
15+
* A taint tracking configuration for client-side request forgery.
16+
*/
17+
class Configuration extends TaintTracking::Configuration {
18+
Configuration() { this = "ClientSideRequestForgery" }
19+
20+
override predicate isSource(DataFlow::Node source) {
21+
exists(Source src |
22+
source = src and
23+
not src.isServerSide()
24+
)
25+
}
26+
27+
override predicate isSink(DataFlow::Node sink) { sink instanceof Sink }
28+
29+
override predicate isSanitizer(DataFlow::Node node) {
30+
super.isSanitizer(node) or
31+
node instanceof Sanitizer
32+
}
33+
34+
override predicate isSanitizerEdge(DataFlow::Node source, DataFlow::Node sink) {
35+
sanitizingPrefixEdge(source, sink)
36+
}
37+
38+
override predicate isAdditionalTaintStep(DataFlow::Node pred, DataFlow::Node succ) {
39+
isAdditionalRequestForgeryStep(pred, succ)
40+
}
41+
}

javascript/ql/lib/semmle/javascript/security/dataflow/RequestForgeryCustomizations.qll

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,15 @@ module RequestForgery {
99
/**
1010
* A data flow source for request forgery.
1111
*/
12-
abstract class Source extends DataFlow::Node { }
12+
abstract class Source extends DataFlow::Node {
13+
/**
14+
* Holds if this source is relevant for server-side request forgery (SSRF).
15+
*
16+
* Otherwise, it is considered to be a source for client-side request forgery, which is
17+
* considered less severe than the server-side variant.
18+
*/
19+
predicate isServerSide() { any() }
20+
}
1321

1422
/**
1523
* A data flow sink for request forgery.
@@ -31,15 +39,18 @@ module RequestForgery {
3139
*/
3240
abstract class Sanitizer extends DataFlow::Node { }
3341

34-
/** A source of remote user input, considered as a flow source for request forgery. */
35-
private class RemoteFlowSourceAsSource extends Source {
36-
RemoteFlowSourceAsSource() {
42+
/** A source of server-side remote user input, considered as a flow source for request forgery. */
43+
private class ServerSideSource extends Source instanceof RemoteFlowSource {
44+
ServerSideSource() { not this instanceof ClientSideRemoteFlowSource }
45+
}
46+
47+
private class ClientSideSource extends Source instanceof ClientSideRemoteFlowSource {
48+
ClientSideSource() {
3749
// Reduce FPs by excluding sources from client-side path or URL
38-
exists(RemoteFlowSource src |
39-
this = src and
40-
not src.(ClientSideRemoteFlowSource).getKind().isPathOrUrl()
41-
)
50+
not ClientSideRemoteFlowSource.super.getKind().isPathOrUrl()
4251
}
52+
53+
override predicate isServerSide() { none() }
4354
}
4455

4556
/**

javascript/ql/lib/semmle/javascript/security/dataflow/RequestForgeryQuery.qll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ import RequestForgeryCustomizations::RequestForgery
1717
class Configuration extends TaintTracking::Configuration {
1818
Configuration() { this = "RequestForgery" }
1919

20-
override predicate isSource(DataFlow::Node source) { source instanceof Source }
20+
override predicate isSource(DataFlow::Node source) { source.(Source).isServerSide() }
2121

2222
override predicate isSink(DataFlow::Node sink) { sink instanceof Sink }
2323

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
/**
2+
* @name Client-side request forgery
3+
* @description Making a client-to-server request with user-controlled data in the URL allows a request forgery attack
4+
* against the client.
5+
* @kind path-problem
6+
* @problem.severity error
7+
* @security-severity 5.0
8+
* @precision medium
9+
* @id js/client-side-request-forgery
10+
* @tags security
11+
* external/cwe/cwe-918
12+
*/
13+
14+
import javascript
15+
import semmle.javascript.security.dataflow.ClientSideRequestForgeryQuery
16+
import DataFlow::PathGraph
17+
18+
from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink, DataFlow::Node request
19+
where
20+
cfg.hasFlowPath(source, sink) and
21+
request = sink.getNode().(Sink).getARequest()
22+
select request, source, sink, "The $@ of this request depends on $@.", sink.getNode(),
23+
sink.getNode().(Sink).getKind(), source, "a user-provided value"

0 commit comments

Comments
 (0)