mirror of
https://github.com/github/codeql.git
synced 2026-04-22 23:35:14 +02:00
JS: Migrate ExceptionXss
This commit is contained in:
@@ -14,15 +14,48 @@ import javascript
|
||||
module ExceptionXss {
|
||||
private import Xss::Shared as Shared
|
||||
|
||||
private newtype TFlowState =
|
||||
TThrown() or
|
||||
TNotYetThrown()
|
||||
|
||||
/** A flow state to associate with a tracked value. */
|
||||
class FlowState extends TFlowState {
|
||||
/** Gets a string representation fo this flow state */
|
||||
string toString() {
|
||||
this = TThrown() and result = "thrown"
|
||||
or
|
||||
this = TNotYetThrown() and result = "not-yet-thrown"
|
||||
}
|
||||
|
||||
deprecated DataFlow::FlowLabel toFlowLabel() {
|
||||
this = TThrown() and result.isTaint()
|
||||
or
|
||||
this = TNotYetThrown() and result instanceof NotYetThrown
|
||||
}
|
||||
}
|
||||
|
||||
/** Predicates for working with flow states. */
|
||||
module FlowState {
|
||||
deprecated FlowState fromFlowLabel(DataFlow::FlowLabel label) { result.toFlowLabel() = label }
|
||||
|
||||
/** A tainted value originating from a thrown and caught exception. */
|
||||
FlowState thrown() { result = TThrown() }
|
||||
|
||||
/** A value that has not yet been thrown. */
|
||||
FlowState notYetThrown() { result = TNotYetThrown() }
|
||||
}
|
||||
|
||||
/** A data flow source for XSS caused by interpreting exception or error text as HTML. */
|
||||
abstract class Source extends DataFlow::Node {
|
||||
/**
|
||||
* Gets a flow label to associate with this source.
|
||||
* Gets a flow state to associate with this source.
|
||||
*
|
||||
* For sources that should pass through a `throw/catch` before reaching the sink, use the
|
||||
* `NotYetThrown` labe. Otherwise use `taint` (the default).
|
||||
* `FlowState::notYetThrown()` state. Otherwise use `FlowState::thrown()` (the default).
|
||||
*/
|
||||
DataFlow::FlowLabel getAFlowLabel() { result.isTaint() }
|
||||
FlowState getAFlowState() { result = FlowState::thrown() }
|
||||
|
||||
deprecated DataFlow::FlowLabel getAFlowLabel() { result = this.getAFlowState().toFlowLabel() }
|
||||
|
||||
/**
|
||||
* Gets a human-readable description of what type of error this refers to.
|
||||
@@ -33,17 +66,19 @@ module ExceptionXss {
|
||||
}
|
||||
|
||||
/**
|
||||
* DEPRECATED. Use `FlowState` instead.
|
||||
*
|
||||
* A FlowLabel representing tainted data that has not been thrown in an exception.
|
||||
* In the js/xss-through-exception query data-flow can only reach a sink after
|
||||
* the data has been thrown as an exception, and data that has not been thrown
|
||||
* as an exception therefore has this flow label, and only this flow label, associated with it.
|
||||
*/
|
||||
abstract class NotYetThrown extends DataFlow::FlowLabel {
|
||||
abstract deprecated class NotYetThrown extends DataFlow::FlowLabel {
|
||||
NotYetThrown() { this = "NotYetThrown" }
|
||||
}
|
||||
|
||||
private class XssSourceAsSource extends Source instanceof Shared::Source {
|
||||
override DataFlow::FlowLabel getAFlowLabel() { result instanceof NotYetThrown }
|
||||
override FlowState getAFlowState() { result instanceof TNotYetThrown }
|
||||
|
||||
override string getDescription() { result = "Exception text" }
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@ import javascript
|
||||
import DomBasedXssCustomizations::DomBasedXss as DomBasedXssCustom
|
||||
import ReflectedXssCustomizations::ReflectedXss as ReflectedXssCustom
|
||||
import ExceptionXssCustomizations::ExceptionXss
|
||||
private import ExceptionXssCustomizations::ExceptionXss as ExceptionXss
|
||||
private import semmle.javascript.dataflow.InferredTypes
|
||||
import Xss::Shared as XssShared
|
||||
|
||||
@@ -71,7 +72,7 @@ predicate canThrowSensitiveInformation(DataFlow::Node node) {
|
||||
}
|
||||
|
||||
// Materialize flow labels
|
||||
private class ConcreteNotYetThrown extends NotYetThrown {
|
||||
deprecated private class ConcreteNotYetThrown extends NotYetThrown {
|
||||
ConcreteNotYetThrown() { this = this }
|
||||
}
|
||||
|
||||
@@ -130,14 +131,14 @@ private DataFlow::Node getExceptionTarget(DataFlow::Node pred) {
|
||||
* an exception.
|
||||
*/
|
||||
module ExceptionXssConfig implements DataFlow::StateConfigSig {
|
||||
class FlowState = DataFlow::FlowLabel;
|
||||
class FlowState = ExceptionXss::FlowState;
|
||||
|
||||
predicate isSource(DataFlow::Node source, DataFlow::FlowLabel label) {
|
||||
source.(Source).getAFlowLabel() = label
|
||||
predicate isSource(DataFlow::Node source, FlowState state) {
|
||||
source.(Source).getAFlowState() = state
|
||||
}
|
||||
|
||||
predicate isSink(DataFlow::Node sink, DataFlow::FlowLabel label) {
|
||||
sink instanceof XssShared::Sink and not label instanceof NotYetThrown
|
||||
predicate isSink(DataFlow::Node sink, FlowState state) {
|
||||
sink instanceof XssShared::Sink and not state = FlowState::notYetThrown()
|
||||
}
|
||||
|
||||
predicate isBarrier(DataFlow::Node node) {
|
||||
@@ -145,10 +146,10 @@ module ExceptionXssConfig implements DataFlow::StateConfigSig {
|
||||
}
|
||||
|
||||
predicate isAdditionalFlowStep(
|
||||
DataFlow::Node pred, DataFlow::FlowLabel inlbl, DataFlow::Node succ, DataFlow::FlowLabel outlbl
|
||||
DataFlow::Node pred, FlowState inlbl, DataFlow::Node succ, FlowState outlbl
|
||||
) {
|
||||
inlbl instanceof NotYetThrown and
|
||||
(outlbl.isTaint() or outlbl instanceof NotYetThrown) and
|
||||
inlbl = FlowState::notYetThrown() and
|
||||
outlbl = [FlowState::thrown(), FlowState::notYetThrown()] and
|
||||
canThrowSensitiveInformation(pred) and
|
||||
succ = getExceptionTarget(pred)
|
||||
}
|
||||
@@ -178,7 +179,8 @@ deprecated class Configuration extends TaintTracking::Configuration {
|
||||
override predicate isAdditionalFlowStep(
|
||||
DataFlow::Node pred, DataFlow::Node succ, DataFlow::FlowLabel inlbl, DataFlow::FlowLabel outlbl
|
||||
) {
|
||||
ExceptionXssConfig::isAdditionalFlowStep(pred, inlbl, succ, outlbl)
|
||||
ExceptionXssConfig::isAdditionalFlowStep(pred, FlowState::fromFlowLabel(inlbl), succ,
|
||||
FlowState::fromFlowLabel(outlbl))
|
||||
or
|
||||
// All the usual taint-flow steps apply on data-flow before it has been thrown in an exception.
|
||||
// Note: this step is not needed in StateConfigSig module since flow states inherit taint steps.
|
||||
|
||||
Reference in New Issue
Block a user