JS: Replace DocumentUrl with TaintedUrlSuffix

This commit is contained in:
Asger F
2024-12-04 13:56:56 +01:00
parent e2b2d1c9ab
commit ef833de60e
7 changed files with 44 additions and 32 deletions

View File

@@ -5,6 +5,7 @@
*/
import javascript
private import semmle.javascript.security.TaintedUrlSuffix
module ClientSideUrlRedirect {
/**
@@ -31,12 +32,12 @@ module ClientSideUrlRedirect {
abstract class Sanitizer extends DataFlow::Node { }
/**
* DEPRECATED. Replaced by functionality from the `TaintedUrlSuffix` library.
*
* A flow label for values that represent the URL of the current document, and
* hence are only partially user-controlled.
*/
abstract class DocumentUrl extends DataFlow::FlowLabel {
DocumentUrl() { this = "document.url" } // TODO: replace with TaintedUrlSuffix
}
deprecated class DocumentUrl = TaintedUrlSuffix::TaintedUrlSuffixLabel;
/**
* DEPRECATED: Use `ActiveThreatModelSource` from Concepts instead!
@@ -50,8 +51,8 @@ module ClientSideUrlRedirect {
ActiveThreatModelSourceAsSource() { not this.(ClientSideRemoteFlowSource).getKind().isPath() }
override DataFlow::FlowLabel getAFlowLabel() {
if this.(ClientSideRemoteFlowSource).getKind().isUrl()
then result instanceof DocumentUrl
if this = TaintedUrlSuffix::source()
then result = TaintedUrlSuffix::label()
else result.isTaint()
}
}
@@ -60,7 +61,7 @@ module ClientSideUrlRedirect {
* Holds if `node` extracts a part of a URL that does not contain the suffix.
*/
pragma[inline]
predicate isPrefixExtraction(DataFlow::MethodCallNode node) {
deprecated predicate isPrefixExtraction(DataFlow::MethodCallNode node) {
// Block flow through prefix-extraction `substring(0, ...)` and `split("#")[0]`
node.getMethodName() = [StringOps::substringMethodName(), "split"] and
not untrustedUrlSubstring(_, node)
@@ -70,7 +71,7 @@ module ClientSideUrlRedirect {
* Holds if `substring` refers to a substring of `base` which is considered untrusted
* when `base` is the current URL.
*/
predicate untrustedUrlSubstring(DataFlow::Node base, DataFlow::Node substring) {
deprecated predicate untrustedUrlSubstring(DataFlow::Node base, DataFlow::Node substring) {
exists(DataFlow::MethodCallNode mcn, string methodName |
mcn = substring and mcn.calls(base, methodName)
|

View File

@@ -10,9 +10,10 @@
import javascript
import UrlConcatenation
import ClientSideUrlRedirectCustomizations::ClientSideUrlRedirect
import semmle.javascript.security.TaintedUrlSuffix
// Materialize flow labels
private class ConcreteDocumentUrl extends DocumentUrl {
deprecated private class ConcreteDocumentUrl extends DocumentUrl {
ConcreteDocumentUrl() { this = this }
}
@@ -35,8 +36,7 @@ module ClientSideUrlRedirectConfig implements DataFlow::StateConfigSig {
}
predicate isBarrier(DataFlow::Node node, DataFlow::FlowLabel state) {
isPrefixExtraction(node) and
state instanceof DocumentUrl
TaintedUrlSuffix::isBarrier(node, state)
}
predicate isBarrierOut(DataFlow::Node node) { hostnameSanitizingPrefixEdge(node, _) }
@@ -47,9 +47,7 @@ module ClientSideUrlRedirectConfig implements DataFlow::StateConfigSig {
DataFlow::Node node1, DataFlow::FlowLabel state1, DataFlow::Node node2,
DataFlow::FlowLabel state2
) {
untrustedUrlSubstring(node1, node2) and
state1 instanceof DocumentUrl and
state2.isTaint()
TaintedUrlSuffix::step(node1, node2, state1, state2)
or
exists(HtmlSanitizerCall call |
node1 = call.getInput() and