mirror of
https://github.com/github/codeql.git
synced 2026-04-27 01:35:13 +02:00
JS: Port UnsafeJQueryPlugin
This commit is contained in:
@@ -31,6 +31,21 @@ module UnsafeJQueryPlugin {
|
||||
*/
|
||||
abstract class Sanitizer extends DataFlow::Node { }
|
||||
|
||||
/**
|
||||
* A barrier guard for XSS in unsafe jQuery plugins.
|
||||
*/
|
||||
abstract class BarrierGuard extends DataFlow::Node {
|
||||
/**
|
||||
* Holds if this node acts as a barrier for data flow, blocking further flow from `e` if `this` evaluates to `outcome`.
|
||||
*/
|
||||
predicate blocksExpr(boolean outcome, Expr e) { none() }
|
||||
}
|
||||
|
||||
/** A subclass of `BarrierGuard` that is used for backward compatibility with the old data flow library. */
|
||||
abstract class BarrierGuardLegacy extends BarrierGuard, TaintTracking::SanitizerGuardNode {
|
||||
override predicate sanitizes(boolean outcome, Expr e) { this.blocksExpr(outcome, e) }
|
||||
}
|
||||
|
||||
/**
|
||||
* The receiver of a function, seen as a sanitizer.
|
||||
*
|
||||
@@ -110,7 +125,7 @@ module UnsafeJQueryPlugin {
|
||||
/**
|
||||
* An expression of form `isElement(x)`, which sanitizes `x`.
|
||||
*/
|
||||
class IsElementSanitizer extends TaintTracking::SanitizerGuardNode, DataFlow::CallNode {
|
||||
class IsElementSanitizer extends BarrierGuardLegacy, DataFlow::CallNode {
|
||||
IsElementSanitizer() {
|
||||
// common ad hoc sanitizing calls
|
||||
exists(string name | this.getCalleeName() = name |
|
||||
@@ -118,7 +133,7 @@ module UnsafeJQueryPlugin {
|
||||
)
|
||||
}
|
||||
|
||||
override predicate sanitizes(boolean outcome, Expr e) {
|
||||
override predicate blocksExpr(boolean outcome, Expr e) {
|
||||
outcome = true and e = this.getArgument(0).asExpr()
|
||||
}
|
||||
}
|
||||
@@ -126,7 +141,7 @@ module UnsafeJQueryPlugin {
|
||||
/**
|
||||
* An expression like `typeof x.<?> !== "undefined"` or `x.<?>`, which sanitizes `x`, as it is unlikely to be a string afterwards.
|
||||
*/
|
||||
class PropertyPresenceSanitizer extends TaintTracking::SanitizerGuardNode, DataFlow::ValueNode {
|
||||
class PropertyPresenceSanitizer extends BarrierGuardLegacy, DataFlow::ValueNode {
|
||||
DataFlow::Node input;
|
||||
boolean polarity;
|
||||
|
||||
@@ -155,20 +170,20 @@ module UnsafeJQueryPlugin {
|
||||
*/
|
||||
DataFlow::PropRead getPropRead() { result = this }
|
||||
|
||||
override predicate sanitizes(boolean outcome, Expr e) {
|
||||
override predicate blocksExpr(boolean outcome, Expr e) {
|
||||
outcome = polarity and
|
||||
e = input.asExpr()
|
||||
}
|
||||
}
|
||||
|
||||
/** A guard that checks whether `x` is a number. */
|
||||
class NumberGuard extends TaintTracking::SanitizerGuardNode instanceof DataFlow::CallNode {
|
||||
class NumberGuard extends BarrierGuardLegacy instanceof DataFlow::CallNode {
|
||||
Expr x;
|
||||
boolean polarity;
|
||||
|
||||
NumberGuard() { TaintTracking::isNumberGuard(this, x, polarity) }
|
||||
|
||||
override predicate sanitizes(boolean outcome, Expr e) { e = x and outcome = polarity }
|
||||
override predicate blocksExpr(boolean outcome, Expr e) { e = x and outcome = polarity }
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -10,7 +10,46 @@ import UnsafeJQueryPluginCustomizations::UnsafeJQueryPlugin
|
||||
/**
|
||||
* A taint-tracking configuration for reasoning about XSS in unsafe jQuery plugins.
|
||||
*/
|
||||
class Configuration extends TaintTracking::Configuration {
|
||||
module UnsafeJQueryPluginConfig implements DataFlow::ConfigSig {
|
||||
// TODO: PropertyPresenceSanitizer should not block values in a content.
|
||||
predicate isSource(DataFlow::Node source) { source instanceof Source }
|
||||
|
||||
predicate isSink(DataFlow::Node sink) { sink instanceof Sink }
|
||||
|
||||
predicate isBarrier(DataFlow::Node node) {
|
||||
node instanceof DomBasedXss::Sanitizer or
|
||||
node instanceof Sanitizer or
|
||||
node = DataFlow::MakeBarrierGuard<BarrierGuard>::getABarrierNode()
|
||||
}
|
||||
|
||||
predicate isAdditionalFlowStep(DataFlow::Node src, DataFlow::Node sink) {
|
||||
// jQuery plugins tend to be implemented as classes that store data in fields initialized by the constructor.
|
||||
// TODO: localFieldStep is too expensive with dataflow2
|
||||
// DataFlow::localFieldStep(pred, succ)
|
||||
none()
|
||||
or
|
||||
aliasPropertyPresenceStep(src, sink)
|
||||
}
|
||||
|
||||
predicate isBarrierOut(DataFlow::Node node) {
|
||||
// prefixing prevents forced html/css confusion:
|
||||
// prefixing through concatenation:
|
||||
StringConcatenation::taintStep(node, _, _, any(int i | i >= 1))
|
||||
or
|
||||
// prefixing through a poor-mans templating system:
|
||||
node = any(StringReplaceCall call).getRawReplacement()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Taint-tracking for reasoning about XSS in unsafe jQuery plugins.
|
||||
*/
|
||||
module UnsafeJQueryPluginFlow = TaintTracking::Global<UnsafeJQueryPluginConfig>;
|
||||
|
||||
/**
|
||||
* DEPRECATED. Use the `UnsafeJQueryPluginFlow` module instead.
|
||||
*/
|
||||
deprecated class Configuration extends TaintTracking::Configuration {
|
||||
Configuration() { this = "UnsafeJQueryPlugin" }
|
||||
|
||||
override predicate isSource(DataFlow::Node source) { source instanceof Source }
|
||||
|
||||
Reference in New Issue
Block a user