Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit d1087d4

Browse files
committed
move sources from XssThroughDom into a customizations file
1 parent 18225fa commit d1087d4

2 files changed

Lines changed: 100 additions & 85 deletions

File tree

javascript/ql/src/semmle/javascript/security/dataflow/XssThroughDom.qll

Lines changed: 1 addition & 85 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@ private import semmle.javascript.dataflow.InferredTypes
1111
*/
1212
module XssThroughDom {
1313
import Xss::XssThroughDom
14+
private import XssThroughDomCustomizations::XssThroughDom
1415
private import semmle.javascript.security.dataflow.Xss::DomBasedXss as DomBasedXss
15-
private import semmle.javascript.dataflow.InferredTypes
1616
private import semmle.javascript.security.dataflow.UnsafeJQueryPluginCustomizations::UnsafeJQueryPlugin as UnsafeJQuery
1717

1818
/**
@@ -40,88 +40,4 @@ module XssThroughDom {
4040
DomBasedXss::isOptionallySanitizedEdge(pred, succ)
4141
}
4242
}
43-
44-
/**
45-
* Gets an attribute name that could store user-controlled data.
46-
*
47-
* Attributes such as "id", "href", and "src" are often used as input to HTML.
48-
* However, they are either rarely controlable by a user, or already a sink for other XSS vulnerabilities.
49-
* Such attributes are therefore ignored.
50-
*/
51-
bindingset[result]
52-
string unsafeAttributeName() {
53-
result.regexpMatch("data-.*") or
54-
result.regexpMatch("aria-.*") or
55-
result = ["name", "value", "title", "alt"]
56-
}
57-
58-
/**
59-
* A source for text from the DOM from a JQuery method call.
60-
*/
61-
class JQueryTextSource extends Source, JQuery::MethodCall {
62-
JQueryTextSource() {
63-
(
64-
this.getMethodName() = ["text", "val"] and this.getNumArgument() = 0
65-
or
66-
this.getMethodName() = "attr" and
67-
this.getNumArgument() = 1 and
68-
forex(InferredType t | t = this.getArgument(0).analyze().getAType() | t = TTString()) and
69-
this.getArgument(0).mayHaveStringValue(unsafeAttributeName())
70-
) and
71-
// looks like a $("<p>" + ... ) source, which is benign for this query.
72-
not exists(DataFlow::Node prefix |
73-
DomBasedXss::isPrefixOfJQueryHtmlString(this.getReceiver()
74-
.(DataFlow::CallNode)
75-
.getAnArgument(), prefix)
76-
|
77-
prefix.getStringValue().regexpMatch("\\s*<.*")
78-
)
79-
}
80-
}
81-
82-
/**
83-
* A source for text from the DOM from a DOM property read or call to `getAttribute()`.
84-
*/
85-
class DOMTextSource extends Source {
86-
DOMTextSource() {
87-
exists(DataFlow::PropRead read | read = this |
88-
read.getBase().getALocalSource() = DOM::domValueRef() and
89-
read.mayHavePropertyName(["innerText", "textContent", "value", "name"])
90-
)
91-
or
92-
exists(DataFlow::MethodCallNode mcn | mcn = this |
93-
mcn.getReceiver().getALocalSource() = DOM::domValueRef() and
94-
mcn.getMethodName() = "getAttribute" and
95-
mcn.getArgument(0).mayHaveStringValue(unsafeAttributeName())
96-
)
97-
}
98-
}
99-
100-
/**
101-
* A test of form `typeof x === "something"`, preventing `x` from being a string in some cases.
102-
*
103-
* This sanitizer helps prune infeasible paths in type-overloaded functions.
104-
*/
105-
class TypeTestGuard extends TaintTracking::SanitizerGuardNode, DataFlow::ValueNode {
106-
override EqualityTest astNode;
107-
Expr operand;
108-
boolean polarity;
109-
110-
TypeTestGuard() {
111-
exists(TypeofTag tag | TaintTracking::isTypeofGuard(astNode, operand, tag) |
112-
// typeof x === "string" sanitizes `x` when it evaluates to false
113-
tag = "string" and
114-
polarity = astNode.getPolarity().booleanNot()
115-
or
116-
// typeof x === "object" sanitizes `x` when it evaluates to true
117-
tag != "string" and
118-
polarity = astNode.getPolarity()
119-
)
120-
}
121-
122-
override predicate sanitizes(boolean outcome, Expr e) {
123-
polarity = outcome and
124-
e = operand
125-
}
126-
}
12743
}
Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
/**
2+
* Provides default sources for reasoning about
3+
* cross-site scripting vulnerabilities through the DOM.
4+
*/
5+
6+
import javascript
7+
8+
/**
9+
* Sources for cross-site scripting vulnerabilities through the DOM.
10+
*/
11+
module XssThroughDom {
12+
import Xss::XssThroughDom
13+
private import semmle.javascript.dataflow.InferredTypes
14+
private import semmle.javascript.security.dataflow.Xss::DomBasedXss as DomBasedXss
15+
16+
/**
17+
* Gets an attribute name that could store user-controlled data.
18+
*
19+
* Attributes such as "id", "href", and "src" are often used as input to HTML.
20+
* However, they are either rarely controlable by a user, or already a sink for other XSS vulnerabilities.
21+
* Such attributes are therefore ignored.
22+
*/
23+
bindingset[result]
24+
string unsafeAttributeName() {
25+
result.regexpMatch("data-.*") or
26+
result.regexpMatch("aria-.*") or
27+
result = ["name", "value", "title", "alt"]
28+
}
29+
30+
/**
31+
* A source for text from the DOM from a JQuery method call.
32+
*/
33+
class JQueryTextSource extends Source, JQuery::MethodCall {
34+
JQueryTextSource() {
35+
(
36+
this.getMethodName() = ["text", "val"] and this.getNumArgument() = 0
37+
or
38+
this.getMethodName() = "attr" and
39+
this.getNumArgument() = 1 and
40+
forex(InferredType t | t = this.getArgument(0).analyze().getAType() | t = TTString()) and
41+
this.getArgument(0).mayHaveStringValue(unsafeAttributeName())
42+
) and
43+
// looks like a $("<p>" + ... ) source, which is benign for this query.
44+
not exists(DataFlow::Node prefix |
45+
DomBasedXss::isPrefixOfJQueryHtmlString(this.getReceiver()
46+
.(DataFlow::CallNode)
47+
.getAnArgument(), prefix)
48+
|
49+
prefix.getStringValue().regexpMatch("\\s*<.*")
50+
)
51+
}
52+
}
53+
54+
/**
55+
* A source for text from the DOM from a DOM property read or call to `getAttribute()`.
56+
*/
57+
class DOMTextSource extends Source {
58+
DOMTextSource() {
59+
exists(DataFlow::PropRead read | read = this |
60+
read.getBase().getALocalSource() = DOM::domValueRef() and
61+
read.mayHavePropertyName(["innerText", "textContent", "value", "name"])
62+
)
63+
or
64+
exists(DataFlow::MethodCallNode mcn | mcn = this |
65+
mcn.getReceiver().getALocalSource() = DOM::domValueRef() and
66+
mcn.getMethodName() = "getAttribute" and
67+
mcn.getArgument(0).mayHaveStringValue(unsafeAttributeName())
68+
)
69+
}
70+
}
71+
72+
/**
73+
* A test of form `typeof x === "something"`, preventing `x` from being a string in some cases.
74+
*
75+
* This sanitizer helps prune infeasible paths in type-overloaded functions.
76+
*/
77+
class TypeTestGuard extends TaintTracking::SanitizerGuardNode, DataFlow::ValueNode {
78+
override EqualityTest astNode;
79+
Expr operand;
80+
boolean polarity;
81+
82+
TypeTestGuard() {
83+
exists(TypeofTag tag | TaintTracking::isTypeofGuard(astNode, operand, tag) |
84+
// typeof x === "string" sanitizes `x` when it evaluates to false
85+
tag = "string" and
86+
polarity = astNode.getPolarity().booleanNot()
87+
or
88+
// typeof x === "object" sanitizes `x` when it evaluates to true
89+
tag != "string" and
90+
polarity = astNode.getPolarity()
91+
)
92+
}
93+
94+
override predicate sanitizes(boolean outcome, Expr e) {
95+
polarity = outcome and
96+
e = operand
97+
}
98+
}
99+
}

0 commit comments

Comments
 (0)