Skip to content

Commit b885249

Browse files
committed
Add a boosted version of XssThroughDOM
1 parent e2e3667 commit b885249

File tree

3 files changed

+116
-0
lines changed

3 files changed

+116
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
/**
2+
* For internal use only.
3+
*
4+
* A taint-tracking configuration for reasoning about XSS through the DOM.
5+
* Defines shared code used by the XSS Through DOM boosted query.
6+
*/
7+
8+
private import semmle.javascript.heuristics.SyntacticHeuristics
9+
private import semmle.javascript.security.dataflow.DomBasedXssCustomizations
10+
private import semmle.javascript.dataflow.InferredTypes
11+
private import semmle.javascript.security.dataflow.XssThroughDomCustomizations::XssThroughDom as XssThroughDom
12+
private import semmle.javascript.security.dataflow.UnsafeJQueryPluginCustomizations::UnsafeJQueryPlugin as UnsafeJQuery
13+
import AdaptiveThreatModeling
14+
15+
class XssThroughDomAtmConfig extends AtmConfig {
16+
XssThroughDomAtmConfig() { this = "XssThroughDomAtmConfig" }
17+
18+
override predicate isKnownSource(DataFlow::Node source) {
19+
source instanceof XssThroughDom::Source
20+
}
21+
22+
override EndpointType getASinkEndpointType() { result instanceof XssSinkType }
23+
24+
override predicate isSanitizer(DataFlow::Node node) {
25+
super.isSanitizer(node) or
26+
node instanceof DomBasedXss::Sanitizer
27+
}
28+
29+
override predicate isSanitizerGuard(TaintTracking::SanitizerGuardNode guard) {
30+
guard instanceof TypeTestGuard or
31+
guard instanceof UnsafeJQuery::PropertyPresenceSanitizer or
32+
guard instanceof UnsafeJQuery::NumberGuard or
33+
guard instanceof PrefixStringSanitizer or
34+
guard instanceof QuoteGuard or
35+
guard instanceof ContainsHtmlGuard
36+
}
37+
38+
override predicate isSanitizerEdge(DataFlow::Node pred, DataFlow::Node succ) {
39+
DomBasedXss::isOptionallySanitizedEdge(pred, succ)
40+
}
41+
}
42+
43+
/**
44+
* A test of form `typeof x === "something"`, preventing `x` from being a string in some cases.
45+
*
46+
* This sanitizer helps prune infeasible paths in type-overloaded functions.
47+
*/
48+
class TypeTestGuard extends TaintTracking::SanitizerGuardNode, DataFlow::ValueNode {
49+
override EqualityTest astNode;
50+
Expr operand;
51+
boolean polarity;
52+
53+
TypeTestGuard() {
54+
exists(TypeofTag tag | TaintTracking::isTypeofGuard(astNode, operand, tag) |
55+
// typeof x === "string" sanitizes `x` when it evaluates to false
56+
tag = "string" and
57+
polarity = astNode.getPolarity().booleanNot()
58+
or
59+
// typeof x === "object" sanitizes `x` when it evaluates to true
60+
tag != "string" and
61+
polarity = astNode.getPolarity()
62+
)
63+
}
64+
65+
override predicate sanitizes(boolean outcome, Expr e) {
66+
polarity = outcome and
67+
e = operand
68+
}
69+
}
70+
71+
private import semmle.javascript.security.dataflow.Xss::Shared as Shared
72+
73+
private class PrefixStringSanitizer extends TaintTracking::SanitizerGuardNode,
74+
DomBasedXss::PrefixStringSanitizer {
75+
PrefixStringSanitizer() { this = this }
76+
}
77+
78+
private class PrefixString extends DataFlow::FlowLabel, DomBasedXss::PrefixString {
79+
PrefixString() { this = this }
80+
}
81+
82+
private class QuoteGuard extends TaintTracking::SanitizerGuardNode, Shared::QuoteGuard {
83+
QuoteGuard() { this = this }
84+
}
85+
86+
private class ContainsHtmlGuard extends TaintTracking::SanitizerGuardNode, Shared::ContainsHtmlGuard {
87+
ContainsHtmlGuard() { this = this }
88+
}

javascript/ql/experimental/adaptivethreatmodeling/modelbuilding/extraction/ExtractEndpointMapping.ql

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import experimental.adaptivethreatmodeling.SqlInjectionATM as SqlInjectionAtm
88
import experimental.adaptivethreatmodeling.NosqlInjectionATM as NosqlInjectionAtm
99
import experimental.adaptivethreatmodeling.TaintedPathATM as TaintedPathAtm
1010
import experimental.adaptivethreatmodeling.XssATM as XssAtm
11+
import experimental.adaptivethreatmodeling.XssThroughDomATM as XssThroughDomAtm
1112
import experimental.adaptivethreatmodeling.AdaptiveThreatModeling
1213

1314
from string queryName, AtmConfig c, EndpointType e
@@ -23,6 +24,8 @@ where
2324
c instanceof TaintedPathAtm::TaintedPathAtmConfig
2425
or
2526
queryName = "Xss" and c instanceof XssAtm::DomBasedXssAtmConfig
27+
or
28+
queryName = "XssThroughDom" and c instanceof XssThroughDomAtm::XssThroughDomAtmConfig
2629
) and
2730
e = c.getASinkEndpointType()
2831
select queryName, e.getEncoding() as label
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
/**
2+
* For internal use only.
3+
*
4+
* @name DOM text reinterpreted as HTML (experimental)
5+
* @description Reinterpreting text from the DOM as HTML can lead
6+
* to a cross-site scripting vulnerability.
7+
* @kind path-problem
8+
* @scored
9+
* @problem.severity error
10+
* @security-severity 6.1
11+
* @id js/ml-powered/xss-through-dom
12+
* @tags experimental security
13+
* external/cwe/cwe-079 external/cwe/cwe-116
14+
*/
15+
16+
import javascript
17+
import ATM::ResultsInfo
18+
import DataFlow::PathGraph
19+
import experimental.adaptivethreatmodeling.XssThroughDomATM
20+
21+
from AtmConfig cfg, DataFlow::PathNode source, DataFlow::PathNode sink, float score
22+
where cfg.getAlerts(source, sink, score)
23+
select sink.getNode(), source, sink,
24+
"(Experimental) $@ may be reinterpreted as HTML without escaping meta-characters. Identified using machine learning.",
25+
source.getNode(), "DOM text", score

0 commit comments

Comments
 (0)