mirror of
https://github.com/github/codeql.git
synced 2026-05-20 22:27:18 +02:00
Boost StoredXss and XssThroughDomATM
Produced with: ``` javascript/ql$tb boost src/Security/CWE-079/StoredXss.ql XssSink javascript/ql$ tb boost src/Security/CWE-079/XssThroughDom.ql XssSink ```
This commit is contained in:
committed by
tombolton
parent
06e5962da7
commit
e5bfb94403
@@ -0,0 +1,72 @@
|
||||
/**
|
||||
* Provides a taint-tracking configuration for reasoning about stored
|
||||
* cross-site scripting vulnerabilities.
|
||||
* Is boosted by ATM.
|
||||
*/
|
||||
|
||||
import javascript
|
||||
import AdaptiveThreatModeling
|
||||
import semmle.javascript.security.dataflow.Xss::StoredXss
|
||||
|
||||
/**
|
||||
* This module provides logic to filter candidate sinks to those which are likely XSS sinks.
|
||||
*/
|
||||
module SinkEndpointFilter {
|
||||
private import StandardEndpointFilters as StandardEndpointFilters
|
||||
|
||||
/**
|
||||
* Provides a set of reasons why a given data flow node should be excluded as a sink candidate.
|
||||
*
|
||||
* If this predicate has no results for a sink candidate `n`, then we should treat `n` as an
|
||||
* effective sink.
|
||||
*/
|
||||
string getAReasonSinkExcluded(DataFlow::Node sinkCandidate) {
|
||||
result = StandardEndpointFilters::getAReasonSinkExcluded(sinkCandidate)
|
||||
}
|
||||
}
|
||||
|
||||
class StoredXssATMConfig extends ATMConfig {
|
||||
StoredXssATMConfig() { this = "StoredXssATMConfig" }
|
||||
|
||||
override predicate isKnownSource(DataFlow::Node source) { source instanceof Source }
|
||||
|
||||
override predicate isKnownSink(DataFlow::Node sink) { sink instanceof Sink }
|
||||
|
||||
override predicate isEffectiveSink(DataFlow::Node sinkCandidate) {
|
||||
not exists(SinkEndpointFilter::getAReasonSinkExcluded(sinkCandidate))
|
||||
}
|
||||
|
||||
override EndpointType getASinkEndpointType() { result instanceof XssSinkType }
|
||||
}
|
||||
|
||||
/**
|
||||
* A taint-tracking configuration for reasoning about XSS.
|
||||
*/
|
||||
class Configuration extends TaintTracking::Configuration {
|
||||
Configuration() { this = "StoredXssATMConfig" }
|
||||
|
||||
override predicate isSource(DataFlow::Node source) { source instanceof Source }
|
||||
|
||||
override predicate isSink(DataFlow::Node sink) {
|
||||
(sink instanceof Sink or any(StoredXssATMConfig cfg).isEffectiveSink(sink))
|
||||
}
|
||||
|
||||
override predicate isSanitizer(DataFlow::Node node) {
|
||||
super.isSanitizer(node) or
|
||||
node instanceof Sanitizer
|
||||
}
|
||||
|
||||
override predicate isSanitizerGuard(TaintTracking::SanitizerGuardNode guard) {
|
||||
guard instanceof SanitizerGuard
|
||||
}
|
||||
}
|
||||
|
||||
/** A file name, considered as a flow source for stored XSS. */
|
||||
class FileNameSourceAsSource extends Source {
|
||||
FileNameSourceAsSource() { this instanceof FileNameSource }
|
||||
}
|
||||
|
||||
/** An instance of user-controlled torrent information, considered as a flow source for stored XSS. */
|
||||
class UserControlledTorrentInfoAsSource extends Source {
|
||||
UserControlledTorrentInfoAsSource() { this instanceof ParseTorrent::UserControlledTorrentInfo }
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
/**
|
||||
* Provides a taint-tracking configuration for reasoning about
|
||||
* cross-site scripting vulnerabilities through the DOM.
|
||||
* Is boosted by ATM.
|
||||
*/
|
||||
|
||||
import javascript
|
||||
import AdaptiveThreatModeling
|
||||
private import semmle.javascript.dataflow.InferredTypes
|
||||
import semmle.javascript.security.dataflow.Xss::XssThroughDom
|
||||
private import semmle.javascript.security.dataflow.XssThroughDomCustomizations::XssThroughDom
|
||||
private import semmle.javascript.security.dataflow.Xss::DomBasedXss as DomBasedXss
|
||||
private import semmle.javascript.security.dataflow.UnsafeJQueryPluginCustomizations::UnsafeJQueryPlugin as UnsafeJQuery
|
||||
|
||||
/**
|
||||
* This module provides logic to filter candidate sinks to those which are likely XSS sinks.
|
||||
*/
|
||||
module SinkEndpointFilter {
|
||||
private import StandardEndpointFilters as StandardEndpointFilters
|
||||
|
||||
/**
|
||||
* Provides a set of reasons why a given data flow node should be excluded as a sink candidate.
|
||||
*
|
||||
* If this predicate has no results for a sink candidate `n`, then we should treat `n` as an
|
||||
* effective sink.
|
||||
*/
|
||||
string getAReasonSinkExcluded(DataFlow::Node sinkCandidate) {
|
||||
result = StandardEndpointFilters::getAReasonSinkExcluded(sinkCandidate)
|
||||
}
|
||||
}
|
||||
|
||||
class XssThroughDOMATMConfig extends ATMConfig {
|
||||
XssThroughDOMATMConfig() { this = "XssThroughDOMATMConfig" }
|
||||
|
||||
override predicate isKnownSource(DataFlow::Node source) { source instanceof Source }
|
||||
|
||||
override predicate isKnownSink(DataFlow::Node sink) { sink instanceof DomBasedXss::Sink }
|
||||
|
||||
override predicate isEffectiveSink(DataFlow::Node sinkCandidate) {
|
||||
not exists(SinkEndpointFilter::getAReasonSinkExcluded(sinkCandidate))
|
||||
}
|
||||
|
||||
override EndpointType getASinkEndpointType() { result instanceof XssSinkType }
|
||||
}
|
||||
|
||||
/**
|
||||
* A taint-tracking configuration for reasoning about XSS through the DOM.
|
||||
*/
|
||||
class Configuration extends TaintTracking::Configuration {
|
||||
Configuration() { this = "XssThroughDOMATMConfig" }
|
||||
|
||||
override predicate isSource(DataFlow::Node source) { source instanceof Source }
|
||||
|
||||
override predicate isSink(DataFlow::Node sink) {
|
||||
(sink instanceof DomBasedXss::Sink or any(XssThroughDOMATMConfig cfg).isEffectiveSink(sink))
|
||||
}
|
||||
|
||||
override predicate isSanitizer(DataFlow::Node node) {
|
||||
super.isSanitizer(node) or
|
||||
node instanceof DomBasedXss::Sanitizer
|
||||
}
|
||||
|
||||
override predicate isSanitizerGuard(TaintTracking::SanitizerGuardNode guard) {
|
||||
guard instanceof TypeTestGuard or
|
||||
guard instanceof UnsafeJQuery::PropertyPresenceSanitizer or
|
||||
guard instanceof DomBasedXss::SanitizerGuard
|
||||
}
|
||||
|
||||
override predicate isSanitizerEdge(DataFlow::Node pred, DataFlow::Node succ) {
|
||||
DomBasedXss::isOptionallySanitizedEdge(pred, succ)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
/**
|
||||
* For internal use only.
|
||||
*
|
||||
* @name Stored cross-site scripting (boosted)
|
||||
* @description Using uncontrolled stored values in HTML allows for a stored cross-site scripting vulnerability.
|
||||
* @kind path-problem
|
||||
* @scored
|
||||
* @problem.severity error
|
||||
* @security-severity 6.1
|
||||
* @id adaptive-threat-modeling/js/stored-xss
|
||||
* @tags experimental experimental/atm security external/cwe/cwe-079 external/cwe/cwe-116
|
||||
*/
|
||||
|
||||
import experimental.adaptivethreatmodeling.StoredXssATM
|
||||
import ATM::ResultsInfo
|
||||
import DataFlow::PathGraph
|
||||
|
||||
from
|
||||
DataFlow::Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink, float score,
|
||||
string scoreString
|
||||
where
|
||||
cfg.hasFlowPath(source, sink) and
|
||||
not isFlowLikelyInBaseQuery(source.getNode(), sink.getNode()) and
|
||||
score = getScoreForFlow(source.getNode(), sink.getNode()) and
|
||||
scoreString = getScoreStringForFlow(source.getNode(), sink.getNode())
|
||||
select sink.getNode(), source, sink,
|
||||
"[Score = " + scoreString + "] This may be a js/stored-xss result depending on $@ " +
|
||||
getAdditionalAlertInfo(source.getNode(), sink.getNode()), source.getNode(),
|
||||
"a user-provided value", score
|
||||
@@ -0,0 +1,29 @@
|
||||
/**
|
||||
* For internal use only.
|
||||
*
|
||||
* @name DOM text reinterpreted as HTML (boosted)
|
||||
* @description Reinterpreting text from the DOM as HTML can lead to a cross-site scripting vulnerability.
|
||||
* @kind path-problem
|
||||
* @scored
|
||||
* @problem.severity warning
|
||||
* @security-severity 6.1
|
||||
* @id adaptive-threat-modeling/js/xss-through-dom
|
||||
* @tags experimental experimental/atm security external/cwe/cwe-079 external/cwe/cwe-116
|
||||
*/
|
||||
|
||||
import experimental.adaptivethreatmodeling.XssThroughDomATM
|
||||
import ATM::ResultsInfo
|
||||
import DataFlow::PathGraph
|
||||
|
||||
from
|
||||
DataFlow::Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink, float score,
|
||||
string scoreString
|
||||
where
|
||||
cfg.hasFlowPath(source, sink) and
|
||||
not isFlowLikelyInBaseQuery(source.getNode(), sink.getNode()) and
|
||||
score = getScoreForFlow(source.getNode(), sink.getNode()) and
|
||||
scoreString = getScoreStringForFlow(source.getNode(), sink.getNode())
|
||||
select sink.getNode(), source, sink,
|
||||
"[Score = " + scoreString + "] This may be a js/xss-through-dom result depending on $@ " +
|
||||
getAdditionalAlertInfo(source.getNode(), sink.getNode()), source.getNode(),
|
||||
"a user-provided value", score
|
||||
Reference in New Issue
Block a user