JS: Address review comments

This commit is contained in:
Asger Feldthaus
2020-10-20 12:00:02 +01:00
parent 8779b7c1ce
commit c91cdb5194
5 changed files with 32 additions and 23 deletions

View File

@@ -58,3 +58,5 @@
## Changes to libraries ## Changes to libraries
* The predicate `TypeAnnotation.hasQualifiedName` now works in more cases when the imported library was not present during extraction. * The predicate `TypeAnnotation.hasQualifiedName` now works in more cases when the imported library was not present during extraction.
* The class `DomBasedXss::Configuration` has been deprecated, as it has been split into `DomBasedXss::HtmlInjectionConfiguration` and `DomBasedXss::JQueryHtmlOrSelectorInjectionConfiguration`. Unless specifically working with jQuery sinks, uses of that
class should be replaced with `HtmlInjectionConfiguration`.

View File

@@ -19,7 +19,7 @@ from DataFlow::Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode
where where
( (
cfg instanceof HtmlInjectionConfiguration or cfg instanceof HtmlInjectionConfiguration or
cfg instanceof JQuerySelectorInjectionConfiguration cfg instanceof JQueryHtmlOrSelectorInjectionConfiguration
) and ) and
cfg.hasFlowPath(source, sink) cfg.hasFlowPath(source, sink)
select sink.getNode(), source, sink, select sink.getNode(), source, sink,

View File

@@ -9,7 +9,7 @@ module DomBasedXss {
import DomBasedXssCustomizations::DomBasedXss import DomBasedXssCustomizations::DomBasedXss
/** /**
* DEPRECATED. Use `HtmlInjectionConfiguration` or `JQuerySelectorInjectionConfiguration`. * DEPRECATED. Use `HtmlInjectionConfiguration` or `JQueryHtmlOrSelectorInjectionConfiguration`.
*/ */
deprecated class Configuration = HtmlInjectionConfiguration; deprecated class Configuration = HtmlInjectionConfiguration;
@@ -23,7 +23,7 @@ module DomBasedXss {
override predicate isSink(DataFlow::Node sink) { override predicate isSink(DataFlow::Node sink) {
sink instanceof Sink and sink instanceof Sink and
not sink instanceof JQuerySelectorSink // Handled by JQuerySelectorInjectionConfiguration below not sink instanceof JQueryHtmlOrSelectorSink // Handled by JQueryHtmlOrSelectorInjectionConfiguration below
} }
override predicate isSanitizer(DataFlow::Node node) { override predicate isSanitizer(DataFlow::Node node) {
@@ -47,8 +47,8 @@ module DomBasedXss {
* *
* Values are only considered tainted if they can start with the `<` character. * Values are only considered tainted if they can start with the `<` character.
*/ */
class JQuerySelectorInjectionConfiguration extends TaintTracking::Configuration { class JQueryHtmlOrSelectorInjectionConfiguration extends TaintTracking::Configuration {
JQuerySelectorInjectionConfiguration() { this = "JQuerySelectorInjection" } JQueryHtmlOrSelectorInjectionConfiguration() { this = "JQueryHtmlOrSelectorInjection" }
override predicate isSource(DataFlow::Node source, DataFlow::FlowLabel label) { override predicate isSource(DataFlow::Node source, DataFlow::FlowLabel label) {
// Reuse any source not derived from location // Reuse any source not derived from location
@@ -64,7 +64,7 @@ module DomBasedXss {
} }
override predicate isSink(DataFlow::Node sink, DataFlow::FlowLabel label) { override predicate isSink(DataFlow::Node sink, DataFlow::FlowLabel label) {
sink instanceof JQuerySelectorSink and label.isTaint() sink instanceof JQueryHtmlOrSelectorSink and label.isTaint()
} }
override predicate isAdditionalFlowStep( override predicate isAdditionalFlowStep(

View File

@@ -34,18 +34,11 @@ module UnsafeJQueryPlugin {
/** /**
* An argument that may act as a HTML fragment rather than a CSS selector, as a sink for remote unsafe jQuery plugins. * An argument that may act as a HTML fragment rather than a CSS selector, as a sink for remote unsafe jQuery plugins.
*/ */
class AmbiguousHtmlOrSelectorArgument extends DataFlow::Node { class AmbiguousHtmlOrSelectorArgument extends DataFlow::Node,
DomBasedXss::JQueryHtmlOrSelectorArgument {
AmbiguousHtmlOrSelectorArgument() { AmbiguousHtmlOrSelectorArgument() {
exists(JQuery::MethodCall call |
call.interpretsArgumentAsSelector(this) and call.interpretsArgumentAsHtml(this)
) and
// the $-function in particular will not construct HTML for non-string values
analyze().getAType() = TTString() and
// any fixed prefix makes the call unambiguous // any fixed prefix makes the call unambiguous
not exists(DataFlow::Node prefix | not exists(getAPrefix())
DomBasedXss::isPrefixOfJQueryHtmlString(this, prefix) and
prefix.mayHaveStringValue(_)
)
} }
} }

View File

@@ -3,6 +3,7 @@
*/ */
import javascript import javascript
private import semmle.javascript.dataflow.InferredTypes
/** Provides classes and predicates shared between the XSS queries. */ /** Provides classes and predicates shared between the XSS queries. */
module Shared { module Shared {
@@ -201,20 +202,33 @@ module DomBasedXss {
} }
/** /**
* An argument to the jQuery `$` function, which is interpreted as either a selector * An argument to the jQuery `$` function or similar, which is interpreted as either a selector
* or as an HTML string depending on its first character. * or as an HTML string depending on its first character.
*/ */
class JQuerySelectorSink extends Sink { class JQueryHtmlOrSelectorArgument extends DataFlow::Node {
JQuerySelectorSink() { JQueryHtmlOrSelectorArgument() {
exists(JQuery::MethodCall call | exists(JQuery::MethodCall call |
call.interpretsArgumentAsHtml(this) and call.interpretsArgumentAsHtml(this) and
call.interpretsArgumentAsSelector(this) and call.interpretsArgumentAsSelector(this) and
// If a prefix of the string is known, it must start with '<' or be an empty string analyze().getAType() = TTString()
forall(string strval | strval = getAPrefixOfJQuerySelectorString(this).getStringValue() |
strval.regexpMatch("(?s)\\s*<.*|")
)
) )
} }
/** Gets a string that flows to the prefix of this argument. */
string getAPrefix() { result = getAPrefixOfJQuerySelectorString(this).getStringValue() }
}
/**
* An argument to the jQuery `$` function or similar, which may be interpreted as HTML.
*
* This is the same as `JQueryHtmlOrSelectorArgument`, excluding cases where the value
* is prefixed by something other than `<`.
*/
class JQueryHtmlOrSelectorSink extends Sink, JQueryHtmlOrSelectorArgument {
JQueryHtmlOrSelectorSink() {
// If a prefix of the string is known, it must start with '<' or be an empty string
forall(string strval | strval = getAPrefix() | strval.regexpMatch("(?s)\\s*<.*|"))
}
} }
/** /**