Make RequestForgery use new API

The extra nodes in .expected files are due to the changes from
https://github.com/github/codeql/pull/13717, which are not applied to
configuration classes extending DataFlow::Configuration or
TaintTracking::Configuration.
This commit is contained in:
Owen Mansel-Chan
2023-06-30 16:43:46 +01:00
parent 1c2536321c
commit 97c32970a0
4 changed files with 49 additions and 21 deletions

View File

@@ -17,9 +17,11 @@ module RequestForgery {
import RequestForgeryCustomizations::RequestForgery
/**
* DEPRECATED: Use `Flow` instead.
*
* A taint-tracking configuration for reasoning about request forgery.
*/
class Configuration extends TaintTracking::Configuration {
deprecated class Configuration extends TaintTracking::Configuration {
Configuration() { this = "RequestForgery" }
override predicate isSource(DataFlow::Node source) { source instanceof Source }
@@ -47,4 +49,23 @@ module RequestForgery {
super.isSanitizerGuard(guard) or guard instanceof SanitizerGuard
}
}
private module Config implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) { source instanceof Source }
predicate isSink(DataFlow::Node sink) { sink instanceof Sink }
predicate isBarrier(DataFlow::Node node) { node instanceof Sanitizer }
predicate isBarrierOut(DataFlow::Node node) { node instanceof SanitizerEdge }
predicate isAdditionalFlowStep(DataFlow::Node pred, DataFlow::Node succ) {
// propagate to a URL when its host is assigned to
exists(Write w, Field f, SsaWithFields v | f.hasQualifiedName("net/url", "URL", "Host") |
w.writesField(v.getAUse(), f, pred) and succ = v.getAUse()
)
}
}
module Flow = TaintTracking::Global<Config>;
}

View File

@@ -11,17 +11,17 @@
*/
import go
import semmle.go.security.RequestForgery::RequestForgery
import semmle.go.security.RequestForgery
import semmle.go.security.SafeUrlFlow
import DataFlow::PathGraph
import RequestForgery::Flow::PathGraph
from
Configuration cfg, SafeUrlFlow::Configuration scfg, DataFlow::PathNode source,
DataFlow::PathNode sink, DataFlow::Node request
SafeUrlFlow::Configuration scfg, RequestForgery::Flow::PathNode source,
RequestForgery::Flow::PathNode sink, DataFlow::Node request
where
cfg.hasFlowPath(source, sink) and
request = sink.getNode().(Sink).getARequest() and
RequestForgery::Flow::flowPath(source, sink) and
request = sink.getNode().(RequestForgery::Sink).getARequest() and
// this excludes flow from safe parts of request URLs, for example the full URL
not scfg.hasFlow(_, sink.getNode())
select request, source, sink, "The $@ of this request depends on a $@.", sink.getNode(),
sink.getNode().(Sink).getKind(), source, "user-provided value"
sink.getNode().(RequestForgery::Sink).getKind(), source, "user-provided value"

View File

@@ -67,9 +67,7 @@ query predicate passingPositiveTests(string res, string expectation, InlineTest
exists(Twirp::ServerConstructor n | t.inEntity(n))
or
expectation = "ssrf" and
exists(RequestForgery::Configuration cfg, DataFlow::Node sink |
cfg.hasFlow(_, sink) and t.inNode(sink)
)
exists(DataFlow::Node sink | RequestForgery::Flow::flowTo(sink) and t.inNode(sink))
)
}
@@ -105,9 +103,7 @@ query predicate failingPositiveTests(string res, string expectation, InlineTest
not exists(Twirp::ServerConstructor n | t.inEntity(n))
or
expectation = "ssrf" and
not exists(RequestForgery::Configuration cfg, DataFlow::Node sink |
cfg.hasFlow(_, sink) and t.inNode(sink)
)
not exists(DataFlow::Node sink | RequestForgery::Flow::flowTo(sink) and t.inNode(sink))
)
}
@@ -143,9 +139,7 @@ query predicate passingNegativeTests(string res, string expectation, InlineTest
not exists(Twirp::ServerConstructor n | t.inEntity(n))
or
expectation = "!ssrf" and
not exists(RequestForgery::Configuration cfg, DataFlow::Node sink |
cfg.hasFlow(_, sink) and t.inNode(sink)
)
not exists(DataFlow::Node sink | RequestForgery::Flow::flowTo(sink) and t.inNode(sink))
)
}
@@ -181,8 +175,6 @@ query predicate failingNegativeTests(string res, string expectation, InlineTest
exists(Twirp::ServerConstructor n | t.inEntity(n))
or
expectation = "!ssrf" and
exists(RequestForgery::Configuration cfg, DataFlow::Node sink |
cfg.hasFlow(_, sink) and t.inNode(sink)
)
exists(DataFlow::Node sink | RequestForgery::Flow::flowTo(sink) and t.inNode(sink))
)
}

View File

@@ -6,7 +6,17 @@ edges
| tst.go:10:13:10:35 | call to FormValue | tst.go:24:66:24:72 | tainted |
| tst.go:10:13:10:35 | call to FormValue | tst.go:27:11:27:29 | ...+... |
| tst.go:10:13:10:35 | call to FormValue | tst.go:29:11:29:40 | ...+... |
| tst.go:10:13:10:35 | call to FormValue | tst.go:37:11:37:11 | u |
| tst.go:10:13:10:35 | call to FormValue | tst.go:36:11:36:17 | tainted |
| tst.go:35:2:35:2 | definition of u [pointer] | tst.go:36:2:36:2 | u [pointer] |
| tst.go:36:2:36:2 | implicit dereference | tst.go:35:2:35:2 | definition of u [pointer] |
| tst.go:36:2:36:2 | implicit dereference | tst.go:36:2:36:2 | u |
| tst.go:36:2:36:2 | implicit dereference | tst.go:37:11:37:11 | u |
| tst.go:36:2:36:2 | u | tst.go:36:2:36:2 | implicit dereference |
| tst.go:36:2:36:2 | u | tst.go:36:2:36:2 | u |
| tst.go:36:2:36:2 | u | tst.go:37:11:37:11 | u |
| tst.go:36:2:36:2 | u [pointer] | tst.go:36:2:36:2 | implicit dereference |
| tst.go:36:11:36:17 | tainted | tst.go:36:2:36:2 | u |
| tst.go:36:11:36:17 | tainted | tst.go:37:11:37:11 | u |
| tst.go:37:11:37:11 | u | tst.go:37:11:37:20 | call to String |
| websocket.go:60:21:60:31 | call to Referer | websocket.go:65:27:65:40 | untrustedInput |
| websocket.go:74:21:74:31 | call to Referer | websocket.go:78:36:78:49 | untrustedInput |
@@ -27,6 +37,11 @@ nodes
| tst.go:24:66:24:72 | tainted | semmle.label | tainted |
| tst.go:27:11:27:29 | ...+... | semmle.label | ...+... |
| tst.go:29:11:29:40 | ...+... | semmle.label | ...+... |
| tst.go:35:2:35:2 | definition of u [pointer] | semmle.label | definition of u [pointer] |
| tst.go:36:2:36:2 | implicit dereference | semmle.label | implicit dereference |
| tst.go:36:2:36:2 | u | semmle.label | u |
| tst.go:36:2:36:2 | u [pointer] | semmle.label | u [pointer] |
| tst.go:36:11:36:17 | tainted | semmle.label | tainted |
| tst.go:37:11:37:11 | u | semmle.label | u |
| tst.go:37:11:37:20 | call to String | semmle.label | call to String |
| websocket.go:60:21:60:31 | call to Referer | semmle.label | call to Referer |