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

Skip to content

Commit 162a499

Browse files
committed
move the ReflectedXss sources/sinks into the Customizations file
1 parent 173e1d0 commit 162a499

3 files changed

Lines changed: 115 additions & 110 deletions

File tree

javascript/ql/lib/semmle/javascript/heuristics/AdditionalSinks.qll

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import javascript
88
private import SyntacticHeuristics
99
private import semmle.javascript.security.dataflow.CodeInjectionCustomizations
1010
private import semmle.javascript.security.dataflow.CommandInjectionCustomizations
11-
private import semmle.javascript.security.dataflow.Xss as Xss
11+
private import semmle.javascript.security.dataflow.ReflectedXssCustomizations
1212
private import semmle.javascript.security.dataflow.SqlInjectionCustomizations
1313
private import semmle.javascript.security.dataflow.NosqlInjectionCustomizations
1414
private import semmle.javascript.security.dataflow.TaintedPathCustomizations
@@ -40,7 +40,7 @@ private class HeuristicDomBasedXssSink extends HeuristicSink, DomBasedXss::Sink
4040
}
4141
}
4242

43-
private class HeuristicReflectedXssSink extends HeuristicSink, Xss::ReflectedXss::Sink {
43+
private class HeuristicReflectedXssSink extends HeuristicSink, ReflectedXss::Sink {
4444
HeuristicReflectedXssSink() {
4545
isAssignedToOrConcatenatedWith(this, "(?i)(html|innerhtml)") or
4646
isArgTo(this, "(?i)(html|render)") or

javascript/ql/lib/semmle/javascript/security/dataflow/ReflectedXssCustomizations.qll

Lines changed: 107 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,113 @@
66
import javascript
77

88
module ReflectedXss {
9-
import Xss::ReflectedXss
9+
private import Xss::Shared as Shared
10+
11+
/** A data flow source for reflected XSS vulnerabilities. */
12+
abstract class Source extends Shared::Source { }
13+
14+
/** A data flow sink for reflected XSS vulnerabilities. */
15+
abstract class Sink extends Shared::Sink { }
16+
17+
/** A sanitizer for reflected XSS vulnerabilities. */
18+
abstract class Sanitizer extends Shared::Sanitizer { }
19+
20+
/** A sanitizer guard for reflected XSS vulnerabilities. */
21+
abstract class SanitizerGuard extends Shared::SanitizerGuard { }
22+
23+
/**
24+
* An expression that is sent as part of an HTTP response, considered as an XSS sink.
25+
*
26+
* We exclude cases where the route handler sets either an unknown content type or
27+
* a content type that does not (case-insensitively) contain the string "html". This
28+
* is to prevent us from flagging plain-text or JSON responses as vulnerable.
29+
*/
30+
class HttpResponseSink extends Sink, DataFlow::ValueNode {
31+
override HTTP::ResponseSendArgument astNode;
32+
33+
HttpResponseSink() { not exists(getANonHtmlHeaderDefinition(astNode)) }
34+
}
35+
36+
/**
37+
* Gets a HeaderDefinition that defines a non-html content-type for `send`.
38+
*/
39+
HTTP::HeaderDefinition getANonHtmlHeaderDefinition(HTTP::ResponseSendArgument send) {
40+
exists(HTTP::RouteHandler h |
41+
send.getRouteHandler() = h and
42+
result = nonHtmlContentTypeHeader(h)
43+
|
44+
// The HeaderDefinition affects a response sent at `send`.
45+
headerAffects(result, send)
46+
)
47+
}
48+
49+
/**
50+
* Holds if `h` may send a response with a content type other than HTML.
51+
*/
52+
HTTP::HeaderDefinition nonHtmlContentTypeHeader(HTTP::RouteHandler h) {
53+
result = h.getAResponseHeader("content-type") and
54+
not exists(string tp | result.defines("content-type", tp) | tp.regexpMatch("(?i).*html.*"))
55+
}
56+
57+
/**
58+
* Holds if a header set in `header` is likely to affect a response sent at `sender`.
59+
*/
60+
predicate headerAffects(HTTP::HeaderDefinition header, HTTP::ResponseSendArgument sender) {
61+
sender.getRouteHandler() = header.getRouteHandler() and
62+
(
63+
// `sender` is affected by a dominating `header`.
64+
header.getBasicBlock().(ReachableBasicBlock).dominates(sender.getBasicBlock())
65+
or
66+
// There is no dominating header, and `header` is non-local.
67+
not isLocalHeaderDefinition(header) and
68+
not exists(HTTP::HeaderDefinition dominatingHeader |
69+
dominatingHeader.getBasicBlock().(ReachableBasicBlock).dominates(sender.getBasicBlock())
70+
)
71+
)
72+
}
73+
74+
/**
75+
* Holds if the HeaderDefinition `header` seems to be local.
76+
* A HeaderDefinition is local if it dominates exactly one `ResponseSendArgument`.
77+
*
78+
* Recognizes variants of:
79+
* ```
80+
* response.writeHead(500, ...);
81+
* response.end('Some error');
82+
* return;
83+
* ```
84+
*/
85+
predicate isLocalHeaderDefinition(HTTP::HeaderDefinition header) {
86+
exists(ReachableBasicBlock headerBlock | headerBlock = header.getBasicBlock() |
87+
1 =
88+
strictcount(HTTP::ResponseSendArgument sender |
89+
sender.getRouteHandler() = header.getRouteHandler() and
90+
header.getBasicBlock().(ReachableBasicBlock).dominates(sender.getBasicBlock())
91+
) and
92+
// doesn't dominate something that looks like a callback.
93+
not exists(Expr e | e instanceof Function | headerBlock.dominates(e.getBasicBlock()))
94+
)
95+
}
96+
97+
/**
98+
* A regexp replacement involving an HTML meta-character, viewed as a sanitizer for
99+
* XSS vulnerabilities.
100+
*
101+
* The XSS queries do not attempt to reason about correctness or completeness of sanitizers,
102+
* so any such replacement stops taint propagation.
103+
*/
104+
private class MetacharEscapeSanitizer extends Sanitizer, Shared::MetacharEscapeSanitizer { }
105+
106+
private class UriEncodingSanitizer extends Sanitizer, Shared::UriEncodingSanitizer { }
107+
108+
private class SerializeJavascriptSanitizer extends Sanitizer, Shared::SerializeJavascriptSanitizer {
109+
}
110+
111+
private class IsEscapedInSwitchSanitizer extends Sanitizer, Shared::IsEscapedInSwitchSanitizer { }
112+
113+
private class QuoteGuard extends SanitizerGuard, Shared::QuoteGuard { }
114+
115+
private class ContainsHtmlGuard extends SanitizerGuard, Shared::ContainsHtmlGuard { }
10116

11117
/** A third-party controllable request input, considered as a flow source for reflected XSS. */
12118
class ThirdPartyRequestInputAccessAsSource extends Source {

javascript/ql/lib/semmle/javascript/security/dataflow/Xss.qll

Lines changed: 6 additions & 107 deletions
Original file line numberDiff line numberDiff line change
@@ -154,113 +154,12 @@ deprecated module DomBasedXss {
154154
import DomBasedXssCustomizations::DomBasedXss
155155
}
156156

157-
/** Provides classes and predicates for the reflected XSS query. */
158-
module ReflectedXss {
159-
/** A data flow source for reflected XSS vulnerabilities. */
160-
abstract class Source extends Shared::Source { }
161-
162-
/** A data flow sink for reflected XSS vulnerabilities. */
163-
abstract class Sink extends Shared::Sink { }
164-
165-
/** A sanitizer for reflected XSS vulnerabilities. */
166-
abstract class Sanitizer extends Shared::Sanitizer { }
167-
168-
/** A sanitizer guard for reflected XSS vulnerabilities. */
169-
abstract class SanitizerGuard extends Shared::SanitizerGuard { }
170-
171-
/**
172-
* An expression that is sent as part of an HTTP response, considered as an XSS sink.
173-
*
174-
* We exclude cases where the route handler sets either an unknown content type or
175-
* a content type that does not (case-insensitively) contain the string "html". This
176-
* is to prevent us from flagging plain-text or JSON responses as vulnerable.
177-
*/
178-
class HttpResponseSink extends Sink, DataFlow::ValueNode {
179-
override HTTP::ResponseSendArgument astNode;
180-
181-
HttpResponseSink() { not exists(getANonHtmlHeaderDefinition(astNode)) }
182-
}
183-
184-
/**
185-
* Gets a HeaderDefinition that defines a non-html content-type for `send`.
186-
*/
187-
HTTP::HeaderDefinition getANonHtmlHeaderDefinition(HTTP::ResponseSendArgument send) {
188-
exists(HTTP::RouteHandler h |
189-
send.getRouteHandler() = h and
190-
result = nonHtmlContentTypeHeader(h)
191-
|
192-
// The HeaderDefinition affects a response sent at `send`.
193-
headerAffects(result, send)
194-
)
195-
}
196-
197-
/**
198-
* Holds if `h` may send a response with a content type other than HTML.
199-
*/
200-
HTTP::HeaderDefinition nonHtmlContentTypeHeader(HTTP::RouteHandler h) {
201-
result = h.getAResponseHeader("content-type") and
202-
not exists(string tp | result.defines("content-type", tp) | tp.regexpMatch("(?i).*html.*"))
203-
}
204-
205-
/**
206-
* Holds if a header set in `header` is likely to affect a response sent at `sender`.
207-
*/
208-
predicate headerAffects(HTTP::HeaderDefinition header, HTTP::ResponseSendArgument sender) {
209-
sender.getRouteHandler() = header.getRouteHandler() and
210-
(
211-
// `sender` is affected by a dominating `header`.
212-
header.getBasicBlock().(ReachableBasicBlock).dominates(sender.getBasicBlock())
213-
or
214-
// There is no dominating header, and `header` is non-local.
215-
not isLocalHeaderDefinition(header) and
216-
not exists(HTTP::HeaderDefinition dominatingHeader |
217-
dominatingHeader.getBasicBlock().(ReachableBasicBlock).dominates(sender.getBasicBlock())
218-
)
219-
)
220-
}
221-
222-
/**
223-
* Holds if the HeaderDefinition `header` seems to be local.
224-
* A HeaderDefinition is local if it dominates exactly one `ResponseSendArgument`.
225-
*
226-
* Recognizes variants of:
227-
* ```
228-
* response.writeHead(500, ...);
229-
* response.end('Some error');
230-
* return;
231-
* ```
232-
*/
233-
predicate isLocalHeaderDefinition(HTTP::HeaderDefinition header) {
234-
exists(ReachableBasicBlock headerBlock | headerBlock = header.getBasicBlock() |
235-
1 =
236-
strictcount(HTTP::ResponseSendArgument sender |
237-
sender.getRouteHandler() = header.getRouteHandler() and
238-
header.getBasicBlock().(ReachableBasicBlock).dominates(sender.getBasicBlock())
239-
) and
240-
// doesn't dominate something that looks like a callback.
241-
not exists(Expr e | e instanceof Function | headerBlock.dominates(e.getBasicBlock()))
242-
)
243-
}
244-
245-
/**
246-
* A regexp replacement involving an HTML meta-character, viewed as a sanitizer for
247-
* XSS vulnerabilities.
248-
*
249-
* The XSS queries do not attempt to reason about correctness or completeness of sanitizers,
250-
* so any such replacement stops taint propagation.
251-
*/
252-
private class MetacharEscapeSanitizer extends Sanitizer, Shared::MetacharEscapeSanitizer { }
253-
254-
private class UriEncodingSanitizer extends Sanitizer, Shared::UriEncodingSanitizer { }
255-
256-
private class SerializeJavascriptSanitizer extends Sanitizer, Shared::SerializeJavascriptSanitizer {
257-
}
258-
259-
private class IsEscapedInSwitchSanitizer extends Sanitizer, Shared::IsEscapedInSwitchSanitizer { }
260-
261-
private class QuoteGuard extends SanitizerGuard, Shared::QuoteGuard { }
262-
263-
private class ContainsHtmlGuard extends SanitizerGuard, Shared::ContainsHtmlGuard { }
157+
/**
158+
* DEPRECATED: Use the `DomBasedXssCustomizations.qll` file instead.
159+
* Provides classes and predicates for the reflected XSS query.
160+
*/
161+
deprecated module ReflectedXss {
162+
import ReflectedXssCustomizations::ReflectedXss
264163
}
265164

266165
/** Provides classes and predicates for the stored XSS query. */

0 commit comments

Comments
 (0)