mirror of
https://github.com/github/codeql.git
synced 2026-04-30 11:15:13 +02:00
OpenUrlRedirect: Use a taint-tracking safe URLs
This commit is contained in:
@@ -53,7 +53,7 @@ module OpenUrlRedirect {
|
||||
/**
|
||||
* A data-flow configuration for reasoning about safe URLs for unvalidated URL redirections.
|
||||
*/
|
||||
class SafeUrlConfiguration extends DataFlow::Configuration {
|
||||
class SafeUrlConfiguration extends TaintTracking::Configuration {
|
||||
SafeUrlConfiguration() { this = "SafeUrlFlow" }
|
||||
|
||||
override predicate isSource(DataFlow::Node source) {
|
||||
@@ -64,35 +64,27 @@ module OpenUrlRedirect {
|
||||
|
||||
override predicate isSink(DataFlow::Node sink) { sink instanceof Sink }
|
||||
|
||||
override predicate isAdditionalFlowStep(DataFlow::Node pred, DataFlow::Node succ) {
|
||||
TaintTracking::functionModelStep(any(SafeUrlMethod m), pred, succ)
|
||||
or
|
||||
TaintTracking::functionModelStep(any(Path::PathManipulatingFunction pmf), pred, succ)
|
||||
or
|
||||
TaintTracking::functionModelStep(any(StringRightTrimmer rt), pred, succ)
|
||||
or
|
||||
TaintTracking::referenceStep(pred, succ)
|
||||
or
|
||||
TaintTracking::stringConcatStep(pred, succ)
|
||||
or
|
||||
TaintTracking::tupleStep(pred, succ)
|
||||
or
|
||||
exists(DataFlow::FieldReadNode frn | succ = frn |
|
||||
frn.getBase() = pred and
|
||||
(frn.getFieldName() = "Host" or frn.getFieldName() = "Path")
|
||||
)
|
||||
or
|
||||
override predicate isAdditionalTaintStep(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()
|
||||
)
|
||||
}
|
||||
|
||||
override predicate isBarrierOut(DataFlow::Node node) {
|
||||
override predicate isSanitizerOut(DataFlow::Node node) {
|
||||
// block propagation of this safe value when its host is overwritten
|
||||
exists(Write w, Field f | f.hasQualifiedName("net/url", "URL", "Host") |
|
||||
w.writesField(node.getASuccessor(), f, _)
|
||||
)
|
||||
or
|
||||
exists(DataFlow::FieldReadNode frn, string name |
|
||||
(name = "RawQuery" or name = "Fragment" or name = "User") and
|
||||
frn.getField().hasQualifiedName("net/url", "URL")
|
||||
|
|
||||
node = frn.getBase()
|
||||
)
|
||||
or
|
||||
TaintTracking::functionModelStep(any(UnsafeUrlMethod um), node, _)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,20 +33,10 @@ module OpenUrlRedirect {
|
||||
abstract class BarrierGuard extends DataFlow::BarrierGuard { }
|
||||
|
||||
/**
|
||||
* A method on a `net/url.URL` that is considered safe to redirect to.
|
||||
* A method on a `net/url.URL` that is considered unsafe to redirect to.
|
||||
*/
|
||||
class SafeUrlMethod extends TaintTracking::FunctionModel, Method {
|
||||
SafeUrlMethod() {
|
||||
this instanceof StringMethod
|
||||
or
|
||||
exists(string m | this.hasQualifiedName("net/url", "URL", m) |
|
||||
m = "Hostname" or m = "Port" or m = "RequestURI"
|
||||
)
|
||||
}
|
||||
|
||||
override predicate hasTaintFlow(DataFlow::FunctionInput inp, DataFlow::FunctionOutput outp) {
|
||||
inp.isReceiver() and outp.isResult()
|
||||
}
|
||||
class UnsafeUrlMethod extends URL::UrlGetter {
|
||||
UnsafeUrlMethod() { this.getName() = "Query" }
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user