зеркало из https://github.com/github/codeql.git
JS: add heuristic variants of queries that use RemoteFlowSource
This commit is contained in:
Родитель
2f84b21c7f
Коммит
442749bb7f
|
@ -0,0 +1,57 @@
|
|||
<!DOCTYPE qhelp PUBLIC
|
||||
"-//Semmle//qhelp//EN"
|
||||
"qhelp.dtd">
|
||||
<qhelp>
|
||||
<overview>
|
||||
<p>Using unsanitized untrusted data in an external API can cause a variety of security issues. This query reports
|
||||
external APIs that use untrusted data. The results are not filtered so that you can audit all examples. The query provides data for security reviews of the application and you can also use it to identify external APIs that should be modeled as either taint steps, or sinks for specific problems.</p>
|
||||
|
||||
<p>An external API is defined as a method call to a method that is not defined in the source code, not overridden
|
||||
in the source code, and is not modeled as a taint step in the default taint library. External APIs may be from the
|
||||
third-party dependencies or from internal dependencies. The query reports uses of
|
||||
untrusted data one of the arguments of external API call or in the return value from a callback passed to an external API.</p>
|
||||
|
||||
</overview>
|
||||
<recommendation>
|
||||
|
||||
<p>For each result:</p>
|
||||
|
||||
<ul>
|
||||
<li>If the result highlights a known sink, confirm that the result is reported by the relevant query, or
|
||||
that the result is a false positive because this data is sanitized.</li>
|
||||
<li>If the result highlights an unknown sink for a problem, then add modeling for the sink to the relevant query,
|
||||
and confirm that the result is either found, or is safe due to appropriate sanitization.</li>
|
||||
<li>If the result represents a call to an external API that transfers taint, add the appropriate modeling, and
|
||||
re-run the query to determine what new results have appeared due to this additional modeling.</li>
|
||||
</ul>
|
||||
|
||||
<p>Otherwise, the result is likely uninteresting. Custom versions of this query can extend the <code>SafeExternalAPIMethod</code>
|
||||
class to exclude known safe external APIs from future analysis.</p>
|
||||
|
||||
</recommendation>
|
||||
<example>
|
||||
|
||||
<p>In this first example, a query parameter is read from the <code>req</code> parameter and then ultimately used in a call to the
|
||||
<code>res.send</code> external API:</p>
|
||||
|
||||
<sample src="ExternalAPISinkExample.js" />
|
||||
|
||||
<p>This is a reflected XSS sink. The XSS query should therefore be reviewed to confirm that this sink is appropriately modeled,
|
||||
and if it is, to confirm that the query reports this particular result, or that the result is a false positive due to
|
||||
some existing sanitization.</p>
|
||||
|
||||
<p>In this second example, again a query parameter is read from <code>req</code>.</p>
|
||||
|
||||
<sample src="ExternalAPITaintStepExample.js" />
|
||||
|
||||
<p>If the query reported the call to <code>path.join</code> on line 4, this would suggest that this external API is
|
||||
not currently modeled as a taint step in the taint tracking library. The next step would be to model this as a taint step, then
|
||||
re-run the query to determine what additional results might be found. In this example, it seems the result of the
|
||||
<code>path.join</code> will be used as a file path, leading to a path traversal vulnerability.</p>
|
||||
|
||||
<p>Note that both examples are correctly handled by the standard taint tracking library and security queries.</p>
|
||||
</example>
|
||||
<references>
|
||||
|
||||
</references>
|
||||
</qhelp>
|
|
@ -1,57 +1,6 @@
|
|||
<!DOCTYPE qhelp PUBLIC
|
||||
"-//Semmle//qhelp//EN"
|
||||
"qhelp.dtd">
|
||||
"-//Semmle//qhelp//EN"
|
||||
"qhelp.dtd">
|
||||
<qhelp>
|
||||
<overview>
|
||||
<p>Using unsanitized untrusted data in an external API can cause a variety of security issues. This query reports
|
||||
external APIs that use untrusted data. The results are not filtered so that you can audit all examples. The query provides data for security reviews of the application and you can also use it to identify external APIs that should be modeled as either taint steps, or sinks for specific problems.</p>
|
||||
|
||||
<p>An external API is defined as a method call to a method that is not defined in the source code, not overridden
|
||||
in the source code, and is not modeled as a taint step in the default taint library. External APIs may be from the
|
||||
third-party dependencies or from internal dependencies. The query reports uses of
|
||||
untrusted data one of the arguments of external API call or in the return value from a callback passed to an external API.</p>
|
||||
|
||||
</overview>
|
||||
<recommendation>
|
||||
|
||||
<p>For each result:</p>
|
||||
|
||||
<ul>
|
||||
<li>If the result highlights a known sink, confirm that the result is reported by the relevant query, or
|
||||
that the result is a false positive because this data is sanitized.</li>
|
||||
<li>If the result highlights an unknown sink for a problem, then add modeling for the sink to the relevant query,
|
||||
and confirm that the result is either found, or is safe due to appropriate sanitization.</li>
|
||||
<li>If the result represents a call to an external API that transfers taint, add the appropriate modeling, and
|
||||
re-run the query to determine what new results have appeared due to this additional modeling.</li>
|
||||
</ul>
|
||||
|
||||
<p>Otherwise, the result is likely uninteresting. Custom versions of this query can extend the <code>SafeExternalAPIMethod</code>
|
||||
class to exclude known safe external APIs from future analysis.</p>
|
||||
|
||||
</recommendation>
|
||||
<example>
|
||||
|
||||
<p>In this first example, a query parameter is read from the <code>req</code> parameter and then ultimately used in a call to the
|
||||
<code>res.send</code> external API:</p>
|
||||
|
||||
<sample src="ExternalAPISinkExample.js" />
|
||||
|
||||
<p>This is a reflected XSS sink. The XSS query should therefore be reviewed to confirm that this sink is appropriately modeled,
|
||||
and if it is, to confirm that the query reports this particular result, or that the result is a false positive due to
|
||||
some existing sanitization.</p>
|
||||
|
||||
<p>In this second example, again a query parameter is read from <code>req</code>.</p>
|
||||
|
||||
<sample src="ExternalAPITaintStepExample.js" />
|
||||
|
||||
<p>If the query reported the call to <code>path.join</code> on line 4, this would suggest that this external API is
|
||||
not currently modeled as a taint step in the taint tracking library. The next step would be to model this as a taint step, then
|
||||
re-run the query to determine what additional results might be found. In this example, it seems the result of the
|
||||
<code>path.join</code> will be used as a file path, leading to a path traversal vulnerability.</p>
|
||||
|
||||
<p>Note that both examples are correctly handled by the standard taint tracking library and security queries.</p>
|
||||
</example>
|
||||
<references>
|
||||
|
||||
</references>
|
||||
<include src="UntrustedDataToExternalAPI.inc.qhelp" />
|
||||
</qhelp>
|
|
@ -0,0 +1,44 @@
|
|||
<!DOCTYPE qhelp PUBLIC
|
||||
"-//Semmle//qhelp//EN"
|
||||
"qhelp.dtd">
|
||||
<qhelp>
|
||||
<overview>
|
||||
<p>Code that passes user input directly to
|
||||
<code>require('child_process').exec</code>, or some other library
|
||||
routine that executes a command, allows the user to execute malicious
|
||||
code.</p>
|
||||
|
||||
</overview>
|
||||
<recommendation>
|
||||
|
||||
<p>If possible, use hard-coded string literals to specify the command to run
|
||||
or library to load. Instead of passing the user input directly to the
|
||||
process or library function, examine the user input and then choose
|
||||
among hard-coded string literals.</p>
|
||||
|
||||
<p>If the applicable libraries or commands cannot be determined at
|
||||
compile time, then add code to verify that the user input string is
|
||||
safe before using it.</p>
|
||||
|
||||
</recommendation>
|
||||
<example>
|
||||
|
||||
<p>The following example shows code that takes a shell script that can be changed
|
||||
maliciously by a user, and passes it straight to <code>child_process.exec</code>
|
||||
without examining it first.</p>
|
||||
|
||||
<sample src="examples/command-injection.js" />
|
||||
|
||||
</example>
|
||||
<references>
|
||||
|
||||
<li>
|
||||
OWASP:
|
||||
<a href="https://www.owasp.org/index.php/Command_Injection">Command Injection</a>.
|
||||
</li>
|
||||
|
||||
<!-- LocalWords: CWE untrusted unsanitized Runtime
|
||||
-->
|
||||
|
||||
</references>
|
||||
</qhelp>
|
|
@ -1,44 +1,6 @@
|
|||
<!DOCTYPE qhelp PUBLIC
|
||||
"-//Semmle//qhelp//EN"
|
||||
"qhelp.dtd">
|
||||
"-//Semmle//qhelp//EN"
|
||||
"qhelp.dtd">
|
||||
<qhelp>
|
||||
<overview>
|
||||
<p>Code that passes user input directly to
|
||||
<code>require('child_process').exec</code>, or some other library
|
||||
routine that executes a command, allows the user to execute malicious
|
||||
code.</p>
|
||||
|
||||
</overview>
|
||||
<recommendation>
|
||||
|
||||
<p>If possible, use hard-coded string literals to specify the command to run
|
||||
or library to load. Instead of passing the user input directly to the
|
||||
process or library function, examine the user input and then choose
|
||||
among hard-coded string literals.</p>
|
||||
|
||||
<p>If the applicable libraries or commands cannot be determined at
|
||||
compile time, then add code to verify that the user input string is
|
||||
safe before using it.</p>
|
||||
|
||||
</recommendation>
|
||||
<example>
|
||||
|
||||
<p>The following example shows code that takes a shell script that can be changed
|
||||
maliciously by a user, and passes it straight to <code>child_process.exec</code>
|
||||
without examining it first.</p>
|
||||
|
||||
<sample src="examples/command-injection.js" />
|
||||
|
||||
</example>
|
||||
<references>
|
||||
|
||||
<li>
|
||||
OWASP:
|
||||
<a href="https://www.owasp.org/index.php/Command_Injection">Command Injection</a>.
|
||||
</li>
|
||||
|
||||
<!-- LocalWords: CWE untrusted unsanitized Runtime
|
||||
-->
|
||||
|
||||
</references>
|
||||
<include src="CommandInjection.inc.qhelp" />
|
||||
</qhelp>
|
|
@ -0,0 +1,57 @@
|
|||
<!DOCTYPE qhelp PUBLIC
|
||||
"-//Semmle//qhelp//EN"
|
||||
"qhelp.dtd">
|
||||
<qhelp>
|
||||
|
||||
<overview>
|
||||
<p>
|
||||
Directly writing user input (for example, a URL query parameter) to a webpage
|
||||
without properly sanitizing the input first, allows for a cross-site scripting vulnerability.
|
||||
</p>
|
||||
<p>
|
||||
This kind of vulnerability is also called <i>DOM-based</i> cross-site scripting, to distinguish
|
||||
it from other types of cross-site scripting.
|
||||
</p>
|
||||
</overview>
|
||||
|
||||
<recommendation>
|
||||
<p>
|
||||
To guard against cross-site scripting, consider using contextual output encoding/escaping before
|
||||
writing user input to the page, or one of the other solutions that are mentioned in the
|
||||
references.
|
||||
</p>
|
||||
</recommendation>
|
||||
|
||||
<example>
|
||||
<p>
|
||||
The following example shows part of the page URL being written directly to the document,
|
||||
leaving the website vulnerable to cross-site scripting.
|
||||
</p>
|
||||
<sample src="examples/Xss.js" />
|
||||
</example>
|
||||
|
||||
<references>
|
||||
<li>
|
||||
OWASP:
|
||||
<a href="https://cheatsheetseries.owasp.org/cheatsheets/DOM_based_XSS_Prevention_Cheat_Sheet.html">DOM based
|
||||
XSS Prevention Cheat Sheet</a>.
|
||||
</li>
|
||||
<li>
|
||||
OWASP:
|
||||
<a href="https://cheatsheetseries.owasp.org/cheatsheets/Cross_Site_Scripting_Prevention_Cheat_Sheet.html">XSS
|
||||
(Cross Site Scripting) Prevention Cheat Sheet</a>.
|
||||
</li>
|
||||
<li>
|
||||
OWASP
|
||||
<a href="https://www.owasp.org/index.php/DOM_Based_XSS">DOM Based XSS</a>.
|
||||
</li>
|
||||
<li>
|
||||
OWASP
|
||||
<a href="https://www.owasp.org/index.php/Types_of_Cross-Site_Scripting">Types of Cross-Site
|
||||
Scripting</a>.
|
||||
</li>
|
||||
<li>
|
||||
Wikipedia: <a href="http://en.wikipedia.org/wiki/Cross-site_scripting">Cross-site scripting</a>.
|
||||
</li>
|
||||
</references>
|
||||
</qhelp>
|
|
@ -1,57 +1,6 @@
|
|||
<!DOCTYPE qhelp PUBLIC
|
||||
"-//Semmle//qhelp//EN"
|
||||
"qhelp.dtd">
|
||||
"-//Semmle//qhelp//EN"
|
||||
"qhelp.dtd">
|
||||
<qhelp>
|
||||
|
||||
<overview>
|
||||
<p>
|
||||
Directly writing user input (for example, a URL query parameter) to a webpage
|
||||
without properly sanitizing the input first, allows for a cross-site scripting vulnerability.
|
||||
</p>
|
||||
<p>
|
||||
This kind of vulnerability is also called <i>DOM-based</i> cross-site scripting, to distinguish
|
||||
it from other types of cross-site scripting.
|
||||
</p>
|
||||
</overview>
|
||||
|
||||
<recommendation>
|
||||
<p>
|
||||
To guard against cross-site scripting, consider using contextual output encoding/escaping before
|
||||
writing user input to the page, or one of the other solutions that are mentioned in the
|
||||
references.
|
||||
</p>
|
||||
</recommendation>
|
||||
|
||||
<example>
|
||||
<p>
|
||||
The following example shows part of the page URL being written directly to the document,
|
||||
leaving the website vulnerable to cross-site scripting.
|
||||
</p>
|
||||
<sample src="examples/Xss.js" />
|
||||
</example>
|
||||
|
||||
<references>
|
||||
<li>
|
||||
OWASP:
|
||||
<a href="https://cheatsheetseries.owasp.org/cheatsheets/DOM_based_XSS_Prevention_Cheat_Sheet.html">DOM based
|
||||
XSS Prevention Cheat Sheet</a>.
|
||||
</li>
|
||||
<li>
|
||||
OWASP:
|
||||
<a href="https://cheatsheetseries.owasp.org/cheatsheets/Cross_Site_Scripting_Prevention_Cheat_Sheet.html">XSS
|
||||
(Cross Site Scripting) Prevention Cheat Sheet</a>.
|
||||
</li>
|
||||
<li>
|
||||
OWASP
|
||||
<a href="https://www.owasp.org/index.php/DOM_Based_XSS">DOM Based XSS</a>.
|
||||
</li>
|
||||
<li>
|
||||
OWASP
|
||||
<a href="https://www.owasp.org/index.php/Types_of_Cross-Site_Scripting">Types of Cross-Site
|
||||
Scripting</a>.
|
||||
</li>
|
||||
<li>
|
||||
Wikipedia: <a href="http://en.wikipedia.org/wiki/Cross-site_scripting">Cross-site scripting</a>.
|
||||
</li>
|
||||
</references>
|
||||
<include src="Xss.inc.qhelp" />
|
||||
</qhelp>
|
|
@ -0,0 +1,62 @@
|
|||
<!DOCTYPE qhelp PUBLIC
|
||||
"-//Semmle//qhelp//EN"
|
||||
"qhelp.dtd">
|
||||
<qhelp>
|
||||
|
||||
<overview>
|
||||
<p>
|
||||
If a database query (such as a SQL or NoSQL query) is built from
|
||||
user-provided data without sufficient sanitization, a malicious user
|
||||
may be able to run malicious database queries.
|
||||
</p>
|
||||
</overview>
|
||||
|
||||
<recommendation>
|
||||
<p>
|
||||
Most database connector libraries offer a way of safely
|
||||
embedding untrusted data into a query by means of query parameters
|
||||
or prepared statements.
|
||||
</p>
|
||||
<p>
|
||||
For NoSQL queries, make use of an operator like MongoDB's <code>$eq</code>
|
||||
to ensure that untrusted data is interpreted as a literal value and not as
|
||||
a query object.
|
||||
</p>
|
||||
</recommendation>
|
||||
|
||||
<example>
|
||||
<p>
|
||||
In the following example, assume the function <code>handler</code> is
|
||||
an HTTP request handler in a web application, whose parameter
|
||||
<code>req</code> contains the request object.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The handler constructs two copies of the same SQL query involving
|
||||
user input taken from the request object, once unsafely using
|
||||
string concatenation, and once safely using query parameters.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
In the first case, the query string <code>query1</code> is built by
|
||||
directly concatenating a user-supplied request parameter with some
|
||||
string literals. The parameter may include quote characters, so this
|
||||
code is vulnerable to a SQL injection attack.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
In the second case, the parameter is embedded into the query string
|
||||
<code>query2</code> using query parameters. In this example, we use
|
||||
the API offered by the <code>pg</code> Postgres database connector
|
||||
library, but other libraries offer similar features. This version is
|
||||
immune to injection attacks.
|
||||
</p>
|
||||
|
||||
<sample src="examples/SqlInjection.js" />
|
||||
</example>
|
||||
|
||||
<references>
|
||||
<li>Wikipedia: <a href="https://en.wikipedia.org/wiki/SQL_injection">SQL injection</a>.</li>
|
||||
<li>MongoDB: <a href="https://docs.mongodb.com/manual/reference/operator/query/eq">$eq operator</a>.</li>
|
||||
</references>
|
||||
</qhelp>
|
|
@ -1,62 +1,6 @@
|
|||
<!DOCTYPE qhelp PUBLIC
|
||||
"-//Semmle//qhelp//EN"
|
||||
"qhelp.dtd">
|
||||
"-//Semmle//qhelp//EN"
|
||||
"qhelp.dtd">
|
||||
<qhelp>
|
||||
|
||||
<overview>
|
||||
<p>
|
||||
If a database query (such as a SQL or NoSQL query) is built from
|
||||
user-provided data without sufficient sanitization, a malicious user
|
||||
may be able to run malicious database queries.
|
||||
</p>
|
||||
</overview>
|
||||
|
||||
<recommendation>
|
||||
<p>
|
||||
Most database connector libraries offer a way of safely
|
||||
embedding untrusted data into a query by means of query parameters
|
||||
or prepared statements.
|
||||
</p>
|
||||
<p>
|
||||
For NoSQL queries, make use of an operator like MongoDB's <code>$eq</code>
|
||||
to ensure that untrusted data is interpreted as a literal value and not as
|
||||
a query object.
|
||||
</p>
|
||||
</recommendation>
|
||||
|
||||
<example>
|
||||
<p>
|
||||
In the following example, assume the function <code>handler</code> is
|
||||
an HTTP request handler in a web application, whose parameter
|
||||
<code>req</code> contains the request object.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The handler constructs two copies of the same SQL query involving
|
||||
user input taken from the request object, once unsafely using
|
||||
string concatenation, and once safely using query parameters.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
In the first case, the query string <code>query1</code> is built by
|
||||
directly concatenating a user-supplied request parameter with some
|
||||
string literals. The parameter may include quote characters, so this
|
||||
code is vulnerable to a SQL injection attack.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
In the second case, the parameter is embedded into the query string
|
||||
<code>query2</code> using query parameters. In this example, we use
|
||||
the API offered by the <code>pg</code> Postgres database connector
|
||||
library, but other libraries offer similar features. This version is
|
||||
immune to injection attacks.
|
||||
</p>
|
||||
|
||||
<sample src="examples/SqlInjection.js" />
|
||||
</example>
|
||||
|
||||
<references>
|
||||
<li>Wikipedia: <a href="https://en.wikipedia.org/wiki/SQL_injection">SQL injection</a>.</li>
|
||||
<li>MongoDB: <a href="https://docs.mongodb.com/manual/reference/operator/query/eq">$eq operator</a>.</li>
|
||||
</references>
|
||||
<include src="SqlInjection.inc.qhelp" />
|
||||
</qhelp>
|
|
@ -0,0 +1,63 @@
|
|||
<!DOCTYPE qhelp PUBLIC
|
||||
"-//Semmle//qhelp//EN"
|
||||
"qhelp.dtd">
|
||||
<qhelp>
|
||||
|
||||
<overview>
|
||||
<p>
|
||||
Directly evaluating user input (for example, an HTTP request parameter) as code without properly
|
||||
sanitizing the input first allows an attacker arbitrary code execution. This can occur when user
|
||||
input is treated as JavaScript, or passed to a framework which interprets it as an expression to be
|
||||
evaluated. Examples include AngularJS expressions or JQuery selectors.
|
||||
</p>
|
||||
</overview>
|
||||
|
||||
<recommendation>
|
||||
<p>
|
||||
Avoid including user input in any expression which may be dynamically evaluated. If user input must
|
||||
be included, use context-specific escaping before
|
||||
including it. It is important that the correct escaping is used for the type of evaluation that will
|
||||
occur.
|
||||
</p>
|
||||
</recommendation>
|
||||
|
||||
<example>
|
||||
<p>
|
||||
The following example shows part of the page URL being evaluated as JavaScript code. This allows an
|
||||
attacker to provide JavaScript within the URL. If an attacker can persuade a user to click on a link
|
||||
to such a URL, the attacker can evaluate arbitrary JavaScript in the browser of the user to,
|
||||
for example, steal cookies containing session information.
|
||||
</p>
|
||||
|
||||
<sample src="examples/CodeInjection.js" />
|
||||
|
||||
<p>
|
||||
The following example shows a Pug template being constructed from user input, allowing attackers to run
|
||||
arbitrary code via a payload such as <code>#{global.process.exit(1)}</code>.
|
||||
</p>
|
||||
|
||||
<sample src="examples/ServerSideTemplateInjection.js" />
|
||||
|
||||
<p>
|
||||
Below is an example of how to use a template engine without any risk of template injection.
|
||||
The user input is included via an interpolation expression <code>#{username}</code> whose value is provided
|
||||
as an option to the template, instead of being part of the template string itself:
|
||||
</p>
|
||||
|
||||
<sample src="examples/ServerSideTemplateInjectionSafe.js" />
|
||||
</example>
|
||||
|
||||
<references>
|
||||
<li>
|
||||
OWASP:
|
||||
<a href="https://www.owasp.org/index.php/Code_Injection">Code Injection</a>.
|
||||
</li>
|
||||
<li>
|
||||
Wikipedia: <a href="https://en.wikipedia.org/wiki/Code_injection">Code Injection</a>.
|
||||
</li>
|
||||
<li>
|
||||
PortSwigger Research Blog:
|
||||
<a href="https://portswigger.net/research/server-side-template-injection">Server-Side Template Injection</a>.
|
||||
</li>
|
||||
</references>
|
||||
</qhelp>
|
|
@ -1,63 +1,6 @@
|
|||
<!DOCTYPE qhelp PUBLIC
|
||||
"-//Semmle//qhelp//EN"
|
||||
"qhelp.dtd">
|
||||
"-//Semmle//qhelp//EN"
|
||||
"qhelp.dtd">
|
||||
<qhelp>
|
||||
|
||||
<overview>
|
||||
<p>
|
||||
Directly evaluating user input (for example, an HTTP request parameter) as code without properly
|
||||
sanitizing the input first allows an attacker arbitrary code execution. This can occur when user
|
||||
input is treated as JavaScript, or passed to a framework which interprets it as an expression to be
|
||||
evaluated. Examples include AngularJS expressions or JQuery selectors.
|
||||
</p>
|
||||
</overview>
|
||||
|
||||
<recommendation>
|
||||
<p>
|
||||
Avoid including user input in any expression which may be dynamically evaluated. If user input must
|
||||
be included, use context-specific escaping before
|
||||
including it. It is important that the correct escaping is used for the type of evaluation that will
|
||||
occur.
|
||||
</p>
|
||||
</recommendation>
|
||||
|
||||
<example>
|
||||
<p>
|
||||
The following example shows part of the page URL being evaluated as JavaScript code. This allows an
|
||||
attacker to provide JavaScript within the URL. If an attacker can persuade a user to click on a link
|
||||
to such a URL, the attacker can evaluate arbitrary JavaScript in the browser of the user to,
|
||||
for example, steal cookies containing session information.
|
||||
</p>
|
||||
|
||||
<sample src="examples/CodeInjection.js" />
|
||||
|
||||
<p>
|
||||
The following example shows a Pug template being constructed from user input, allowing attackers to run
|
||||
arbitrary code via a payload such as <code>#{global.process.exit(1)}</code>.
|
||||
</p>
|
||||
|
||||
<sample src="examples/ServerSideTemplateInjection.js" />
|
||||
|
||||
<p>
|
||||
Below is an example of how to use a template engine without any risk of template injection.
|
||||
The user input is included via an interpolation expression <code>#{username}</code> whose value is provided
|
||||
as an option to the template, instead of being part of the template string itself:
|
||||
</p>
|
||||
|
||||
<sample src="examples/ServerSideTemplateInjectionSafe.js" />
|
||||
</example>
|
||||
|
||||
<references>
|
||||
<li>
|
||||
OWASP:
|
||||
<a href="https://www.owasp.org/index.php/Code_Injection">Code Injection</a>.
|
||||
</li>
|
||||
<li>
|
||||
Wikipedia: <a href="https://en.wikipedia.org/wiki/Code_injection">Code Injection</a>.
|
||||
</li>
|
||||
<li>
|
||||
PortSwigger Research Blog:
|
||||
<a href="https://portswigger.net/research/server-side-template-injection">Server-Side Template Injection</a>.
|
||||
</li>
|
||||
</references>
|
||||
<include src="CodeInjection.inc.qhelp" />
|
||||
</qhelp>
|
|
@ -0,0 +1,47 @@
|
|||
<!DOCTYPE qhelp PUBLIC
|
||||
"-//Semmle//qhelp//EN"
|
||||
"qhelp.dtd">
|
||||
<qhelp>
|
||||
|
||||
<overview>
|
||||
|
||||
<p>If unsanitized user input is written to a log entry, a malicious user may be able to forge new log entries.</p>
|
||||
|
||||
<p>Forgery can occur if a user provides some input with characters that are interpreted
|
||||
when the log output is displayed. If the log is displayed as a plain text file, then new
|
||||
line characters can be used by a malicious user. If the log is displayed as HTML, then
|
||||
arbitrary HTML may be included to spoof log entries.</p>
|
||||
</overview>
|
||||
|
||||
<recommendation>
|
||||
<p>
|
||||
User input should be suitably sanitized before it is logged.
|
||||
</p>
|
||||
<p>
|
||||
If the log entries are in plain text then line breaks should be removed from user input, using
|
||||
<code>String.prototype.replace</code> or similar. Care should also be taken that user input is clearly marked
|
||||
in log entries.
|
||||
</p>
|
||||
<p>
|
||||
For log entries that will be displayed in HTML, user input should be HTML-encoded before being logged, to prevent forgery and
|
||||
other forms of HTML injection.
|
||||
</p>
|
||||
|
||||
</recommendation>
|
||||
|
||||
<example>
|
||||
<p>In the first example, a username, provided by the user, is logged using `console.info`. In
|
||||
the first case, it is logged without any sanitization. In the second case, the username is used to build an error that is logged using `console.error`.
|
||||
If a malicious user provides `username=Guest%0a[INFO]+User:+Admin%0a` as a username parameter,
|
||||
the log entry will be splitted in two different lines, where the second line will be `[INFO]+User:+Admin`.
|
||||
</p>
|
||||
<sample src="examples/logInjectionBad.js" />
|
||||
|
||||
<p> In the second example, <code>String.prototype.replace</code> is used to ensure no line endings are present in the user input.</p>
|
||||
<sample src="examples/logInjectionGood.js" />
|
||||
</example>
|
||||
|
||||
<references>
|
||||
<li>OWASP: <a href="https://www.owasp.org/index.php/Log_Injection">Log Injection</a>.</li>
|
||||
</references>
|
||||
</qhelp>
|
|
@ -1,47 +1,6 @@
|
|||
<!DOCTYPE qhelp PUBLIC
|
||||
"-//Semmle//qhelp//EN"
|
||||
"qhelp.dtd">
|
||||
"-//Semmle//qhelp//EN"
|
||||
"qhelp.dtd">
|
||||
<qhelp>
|
||||
|
||||
<overview>
|
||||
|
||||
<p>If unsanitized user input is written to a log entry, a malicious user may be able to forge new log entries.</p>
|
||||
|
||||
<p>Forgery can occur if a user provides some input with characters that are interpreted
|
||||
when the log output is displayed. If the log is displayed as a plain text file, then new
|
||||
line characters can be used by a malicious user. If the log is displayed as HTML, then
|
||||
arbitrary HTML may be included to spoof log entries.</p>
|
||||
</overview>
|
||||
|
||||
<recommendation>
|
||||
<p>
|
||||
User input should be suitably sanitized before it is logged.
|
||||
</p>
|
||||
<p>
|
||||
If the log entries are in plain text then line breaks should be removed from user input, using
|
||||
<code>String.prototype.replace</code> or similar. Care should also be taken that user input is clearly marked
|
||||
in log entries.
|
||||
</p>
|
||||
<p>
|
||||
For log entries that will be displayed in HTML, user input should be HTML-encoded before being logged, to prevent forgery and
|
||||
other forms of HTML injection.
|
||||
</p>
|
||||
|
||||
</recommendation>
|
||||
|
||||
<example>
|
||||
<p>In the first example, a username, provided by the user, is logged using `console.info`. In
|
||||
the first case, it is logged without any sanitization. In the second case, the username is used to build an error that is logged using `console.error`.
|
||||
If a malicious user provides `username=Guest%0a[INFO]+User:+Admin%0a` as a username parameter,
|
||||
the log entry will be splitted in two different lines, where the second line will be `[INFO]+User:+Admin`.
|
||||
</p>
|
||||
<sample src="examples/logInjectionBad.js" />
|
||||
|
||||
<p> In the second example, <code>String.prototype.replace</code> is used to ensure no line endings are present in the user input.</p>
|
||||
<sample src="examples/logInjectionGood.js" />
|
||||
</example>
|
||||
|
||||
<references>
|
||||
<li>OWASP: <a href="https://www.owasp.org/index.php/Log_Injection">Log Injection</a>.</li>
|
||||
</references>
|
||||
<include src="LogInjection.inc.qhelp" />
|
||||
</qhelp>
|
|
@ -0,0 +1,46 @@
|
|||
<!DOCTYPE qhelp PUBLIC
|
||||
"-//Semmle//qhelp//EN"
|
||||
"qhelp.dtd">
|
||||
<qhelp>
|
||||
|
||||
<overview>
|
||||
<p>
|
||||
Functions like the Node.js standard library function <code>util.format</code> accept a
|
||||
format string that is used to format the remaining arguments by providing inline format
|
||||
specifiers. If the format string contains unsanitized input from an untrusted source,
|
||||
then that string may contain unexpected format specifiers that cause garbled output.
|
||||
</p>
|
||||
</overview>
|
||||
|
||||
<recommendation>
|
||||
<p>
|
||||
Either sanitize the input before including it in the format string, or use a
|
||||
<code>%s</code> specifier in the format string, and pass the untrusted data as corresponding
|
||||
argument.
|
||||
</p>
|
||||
</recommendation>
|
||||
|
||||
<example>
|
||||
<p>
|
||||
The following program snippet logs information about an unauthorized access attempt. The
|
||||
log message includes the user name, and the user's IP address is passed as an additional
|
||||
argument to <code>console.log</code> to be appended to the message:
|
||||
</p>
|
||||
<sample src="examples/TaintedFormatStringBad.js"/>
|
||||
<p>
|
||||
However, if a malicious user provides <code>%d</code> as their user name, <code>console.log</code>
|
||||
will instead attempt to format the <code>ip</code> argument as a number. Since IP addresses are
|
||||
not valid numbers, the result of this conversion is <code>NaN</code>. The resulting log message
|
||||
will read "Unauthorized access attempt by NaN", missing all the information that it was trying to
|
||||
log in the first place.
|
||||
</p>
|
||||
<p>
|
||||
Instead, the user name should be included using the <code>%s</code> specifier:
|
||||
</p>
|
||||
<sample src="examples/TaintedFormatStringGood.js"/>
|
||||
</example>
|
||||
|
||||
<references>
|
||||
<li>Node.js Documentation: <a href="https://nodejs.org/api/util.html#util_util_format_format_args">util.format</a>.</li>
|
||||
</references>
|
||||
</qhelp>
|
|
@ -1,46 +1,6 @@
|
|||
<!DOCTYPE qhelp PUBLIC
|
||||
"-//Semmle//qhelp//EN"
|
||||
"qhelp.dtd">
|
||||
"-//Semmle//qhelp//EN"
|
||||
"qhelp.dtd">
|
||||
<qhelp>
|
||||
|
||||
<overview>
|
||||
<p>
|
||||
Functions like the Node.js standard library function <code>util.format</code> accept a
|
||||
format string that is used to format the remaining arguments by providing inline format
|
||||
specifiers. If the format string contains unsanitized input from an untrusted source,
|
||||
then that string may contain unexpected format specifiers that cause garbled output.
|
||||
</p>
|
||||
</overview>
|
||||
|
||||
<recommendation>
|
||||
<p>
|
||||
Either sanitize the input before including it in the format string, or use a
|
||||
<code>%s</code> specifier in the format string, and pass the untrusted data as corresponding
|
||||
argument.
|
||||
</p>
|
||||
</recommendation>
|
||||
|
||||
<example>
|
||||
<p>
|
||||
The following program snippet logs information about an unauthorized access attempt. The
|
||||
log message includes the user name, and the user's IP address is passed as an additional
|
||||
argument to <code>console.log</code> to be appended to the message:
|
||||
</p>
|
||||
<sample src="examples/TaintedFormatStringBad.js"/>
|
||||
<p>
|
||||
However, if a malicious user provides <code>%d</code> as their user name, <code>console.log</code>
|
||||
will instead attempt to format the <code>ip</code> argument as a number. Since IP addresses are
|
||||
not valid numbers, the result of this conversion is <code>NaN</code>. The resulting log message
|
||||
will read "Unauthorized access attempt by NaN", missing all the information that it was trying to
|
||||
log in the first place.
|
||||
</p>
|
||||
<p>
|
||||
Instead, the user name should be included using the <code>%s</code> specifier:
|
||||
</p>
|
||||
<sample src="examples/TaintedFormatStringGood.js"/>
|
||||
</example>
|
||||
|
||||
<references>
|
||||
<li>Node.js Documentation: <a href="https://nodejs.org/api/util.html#util_util_format_format_args">util.format</a>.</li>
|
||||
</references>
|
||||
<include src="TaintedFormatString.inc.qhelp" />
|
||||
</qhelp>
|
|
@ -0,0 +1,85 @@
|
|||
<!DOCTYPE qhelp PUBLIC
|
||||
"-//Semmle//qhelp//EN"
|
||||
"qhelp.dtd">
|
||||
<qhelp>
|
||||
|
||||
<overview>
|
||||
<p>
|
||||
|
||||
A server can send the
|
||||
<code>"Access-Control-Allow-Credentials"</code> CORS header to control
|
||||
when a browser may send user credentials in Cross-Origin HTTP
|
||||
requests.
|
||||
|
||||
</p>
|
||||
<p>
|
||||
|
||||
When the <code>Access-Control-Allow-Credentials</code> header
|
||||
is <code>"true"</code>, the <code>Access-Control-Allow-Origin</code>
|
||||
header must have a value different from <code>"*"</code> in order to
|
||||
make browsers accept the header. Therefore, to allow multiple origins
|
||||
for Cross-Origin requests with credentials, the server must
|
||||
dynamically compute the value of the
|
||||
<code>"Access-Control-Allow-Origin"</code> header. Computing this
|
||||
header value from information in the request to the server can
|
||||
therefore potentially allow an attacker to control the origins that
|
||||
the browser sends credentials to.
|
||||
|
||||
</p>
|
||||
|
||||
|
||||
|
||||
</overview>
|
||||
|
||||
<recommendation>
|
||||
<p>
|
||||
|
||||
When the <code>Access-Control-Allow-Credentials</code> header
|
||||
value is <code>"true"</code>, a dynamic computation of the
|
||||
<code>Access-Control-Allow-Origin</code> header must involve
|
||||
sanitization if it relies on user-controlled input.
|
||||
|
||||
|
||||
</p>
|
||||
<p>
|
||||
|
||||
Since the <code>"null"</code> origin is easy to obtain for an
|
||||
attacker, it is never safe to use <code>"null"</code> as the value of
|
||||
the <code>Access-Control-Allow-Origin</code> header when the
|
||||
<code>Access-Control-Allow-Credentials</code> header value is
|
||||
<code>"true"</code>.
|
||||
|
||||
</p>
|
||||
</recommendation>
|
||||
|
||||
<example>
|
||||
<p>
|
||||
|
||||
In the example below, the server allows the browser to send
|
||||
user credentials in a Cross-Origin request. The request header
|
||||
<code>origins</code> controls the allowed origins for such a
|
||||
Cross-Origin request.
|
||||
|
||||
</p>
|
||||
|
||||
<sample src="examples/CorsMisconfigurationForCredentials.js"/>
|
||||
|
||||
<p>
|
||||
|
||||
This is not secure, since an attacker can choose the value of
|
||||
the <code>origin</code> request header to make the browser send
|
||||
credentials to their own server. The use of a whitelist containing
|
||||
allowed origins for the Cross-Origin request fixes the issue:
|
||||
|
||||
</p>
|
||||
|
||||
<sample src="examples/CorsMisconfigurationForCredentials_fixed.js"/>
|
||||
</example>
|
||||
|
||||
<references>
|
||||
<li>Mozilla Developer Network: <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Origin">CORS, Access-Control-Allow-Origin</a>.</li>
|
||||
<li>Mozilla Developer Network: <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Credentials">CORS, Access-Control-Allow-Credentials</a>.</li>
|
||||
<li>PortSwigger: <a href="http://blog.portswigger.net/2016/10/exploiting-cors-misconfigurations-for.html">Exploiting CORS Misconfigurations for Bitcoins and Bounties</a></li>
|
||||
<li>W3C: <a href="https://w3c.github.io/webappsec-cors-for-developers/#resources">CORS for developers, Advice for Resource Owners</a></li>
|
||||
</references>
|
||||
</qhelp>
|
|
@ -2,84 +2,5 @@
|
|||
"-//Semmle//qhelp//EN"
|
||||
"qhelp.dtd">
|
||||
<qhelp>
|
||||
|
||||
<overview>
|
||||
<p>
|
||||
|
||||
A server can send the
|
||||
<code>"Access-Control-Allow-Credentials"</code> CORS header to control
|
||||
when a browser may send user credentials in Cross-Origin HTTP
|
||||
requests.
|
||||
|
||||
</p>
|
||||
<p>
|
||||
|
||||
When the <code>Access-Control-Allow-Credentials</code> header
|
||||
is <code>"true"</code>, the <code>Access-Control-Allow-Origin</code>
|
||||
header must have a value different from <code>"*"</code> in order to
|
||||
make browsers accept the header. Therefore, to allow multiple origins
|
||||
for Cross-Origin requests with credentials, the server must
|
||||
dynamically compute the value of the
|
||||
<code>"Access-Control-Allow-Origin"</code> header. Computing this
|
||||
header value from information in the request to the server can
|
||||
therefore potentially allow an attacker to control the origins that
|
||||
the browser sends credentials to.
|
||||
|
||||
</p>
|
||||
|
||||
|
||||
|
||||
</overview>
|
||||
|
||||
<recommendation>
|
||||
<p>
|
||||
|
||||
When the <code>Access-Control-Allow-Credentials</code> header
|
||||
value is <code>"true"</code>, a dynamic computation of the
|
||||
<code>Access-Control-Allow-Origin</code> header must involve
|
||||
sanitization if it relies on user-controlled input.
|
||||
|
||||
|
||||
</p>
|
||||
<p>
|
||||
|
||||
Since the <code>"null"</code> origin is easy to obtain for an
|
||||
attacker, it is never safe to use <code>"null"</code> as the value of
|
||||
the <code>Access-Control-Allow-Origin</code> header when the
|
||||
<code>Access-Control-Allow-Credentials</code> header value is
|
||||
<code>"true"</code>.
|
||||
|
||||
</p>
|
||||
</recommendation>
|
||||
|
||||
<example>
|
||||
<p>
|
||||
|
||||
In the example below, the server allows the browser to send
|
||||
user credentials in a Cross-Origin request. The request header
|
||||
<code>origins</code> controls the allowed origins for such a
|
||||
Cross-Origin request.
|
||||
|
||||
</p>
|
||||
|
||||
<sample src="examples/CorsMisconfigurationForCredentials.js"/>
|
||||
|
||||
<p>
|
||||
|
||||
This is not secure, since an attacker can choose the value of
|
||||
the <code>origin</code> request header to make the browser send
|
||||
credentials to their own server. The use of a whitelist containing
|
||||
allowed origins for the Cross-Origin request fixes the issue:
|
||||
|
||||
</p>
|
||||
|
||||
<sample src="examples/CorsMisconfigurationForCredentials_fixed.js"/>
|
||||
</example>
|
||||
|
||||
<references>
|
||||
<li>Mozilla Developer Network: <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Origin">CORS, Access-Control-Allow-Origin</a>.</li>
|
||||
<li>Mozilla Developer Network: <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Credentials">CORS, Access-Control-Allow-Credentials</a>.</li>
|
||||
<li>PortSwigger: <a href="http://blog.portswigger.net/2016/10/exploiting-cors-misconfigurations-for.html">Exploiting CORS Misconfigurations for Bitcoins and Bounties</a></li>
|
||||
<li>W3C: <a href="https://w3c.github.io/webappsec-cors-for-developers/#resources">CORS for developers, Advice for Resource Owners</a></li>
|
||||
</references>
|
||||
<include src="CorsMisconfigurationForCredentials.inc.qhelp" />
|
||||
</qhelp>
|
|
@ -0,0 +1,87 @@
|
|||
<!DOCTYPE qhelp PUBLIC
|
||||
"-//Semmle//qhelp//EN"
|
||||
"qhelp.dtd">
|
||||
<qhelp>
|
||||
|
||||
<overview>
|
||||
<p>
|
||||
Dynamically computing object property names from untrusted input
|
||||
may have multiple undesired consequences. For example,
|
||||
if the property access is used as part of a write, an
|
||||
attacker may overwrite vital properties of objects, such as
|
||||
<code>__proto__</code>. This attack is known as <i>prototype
|
||||
pollution attack</i> and may serve as a vehicle for denial-of-service
|
||||
attacks. A similar attack vector, is to replace the
|
||||
<code>toString</code> property of an object with a primitive.
|
||||
Whenever <code>toString</code> is then called on that object, either
|
||||
explicitly or implicitly as part of a type coercion, an exception
|
||||
will be raised.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Moreover, if the name of an HTTP header is user-controlled,
|
||||
an attacker may exploit this to overwrite security-critical headers
|
||||
such as <code>Access-Control-Allow-Origin</code> or
|
||||
<code>Content-Security-Policy</code>.
|
||||
</p>
|
||||
</overview>
|
||||
|
||||
<recommendation>
|
||||
<p>
|
||||
The most common case in which prototype pollution vulnerabilities arise
|
||||
is when JavaScript objects are used for implementing map data
|
||||
structures. This case should be avoided whenever possible by using the
|
||||
ECMAScript 2015 <code>Map</code> instead. When this is not possible, an
|
||||
alternative fix is to prepend untrusted input with a marker character
|
||||
such as <code>$</code>, before using it in properties accesses. In this way,
|
||||
the attacker does not have access to built-in properties which do not
|
||||
start with the chosen character.
|
||||
</p>
|
||||
<p>
|
||||
When using user input as part of a header name, a sanitization
|
||||
step should be performed on the input to ensure that the name does not
|
||||
clash with existing header names such as
|
||||
<code>Content-Security-Policy</code>.
|
||||
</p>
|
||||
</recommendation>
|
||||
|
||||
<example>
|
||||
<p>
|
||||
In the example below, the dynamically computed property
|
||||
<code>prop</code> is accessed on <code>myObj</code> using a
|
||||
user-controlled value.
|
||||
</p>
|
||||
|
||||
<sample src="examples/RemotePropertyInjection.js"/>
|
||||
|
||||
<p>
|
||||
This is not secure since an attacker may exploit this code to
|
||||
overwrite the property <code>__proto__</code> with an empty function.
|
||||
If this happens, the concatenation in the <code>console.log</code>
|
||||
argument will fail with a confusing message such as
|
||||
"Function.prototype.toString is not generic". If the application does
|
||||
not properly handle this error, this scenario may result in a serious
|
||||
denial-of-service attack. The fix is to prepend the user-controlled
|
||||
string with a marker character such as <code>$</code> which will
|
||||
prevent arbitrary property names from being overwritten.
|
||||
</p>
|
||||
|
||||
<sample src="examples/RemotePropertyInjection_fixed.js"/>
|
||||
</example>
|
||||
|
||||
<references>
|
||||
<li>Prototype pollution attacks:
|
||||
<a href="https://github.com/electron/electron/pull/9287">electron</a>,
|
||||
<a href="https://hackerone.com/reports/310443">lodash</a>,
|
||||
<a href="https://npmjs.com/advisories/566">hoek</a>.
|
||||
</li>
|
||||
<li> Penetration testing report:
|
||||
<a href="http://seclists.org/pen-test/2009/Mar/67">
|
||||
header name injection attack</a>
|
||||
</li>
|
||||
<li> npm blog post:
|
||||
<a href="https://github.com/nodesecurity/eslint-plugin-security/blob/3c7522ca1be800353513282867a1034c795d9eb4/docs/the-dangers-of-square-bracket-notation.md">
|
||||
dangers of square bracket notation</a>
|
||||
</li>
|
||||
</references>
|
||||
</qhelp>
|
|
@ -2,86 +2,5 @@
|
|||
"-//Semmle//qhelp//EN"
|
||||
"qhelp.dtd">
|
||||
<qhelp>
|
||||
|
||||
<overview>
|
||||
<p>
|
||||
Dynamically computing object property names from untrusted input
|
||||
may have multiple undesired consequences. For example,
|
||||
if the property access is used as part of a write, an
|
||||
attacker may overwrite vital properties of objects, such as
|
||||
<code>__proto__</code>. This attack is known as <i>prototype
|
||||
pollution attack</i> and may serve as a vehicle for denial-of-service
|
||||
attacks. A similar attack vector, is to replace the
|
||||
<code>toString</code> property of an object with a primitive.
|
||||
Whenever <code>toString</code> is then called on that object, either
|
||||
explicitly or implicitly as part of a type coercion, an exception
|
||||
will be raised.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Moreover, if the name of an HTTP header is user-controlled,
|
||||
an attacker may exploit this to overwrite security-critical headers
|
||||
such as <code>Access-Control-Allow-Origin</code> or
|
||||
<code>Content-Security-Policy</code>.
|
||||
</p>
|
||||
</overview>
|
||||
|
||||
<recommendation>
|
||||
<p>
|
||||
The most common case in which prototype pollution vulnerabilities arise
|
||||
is when JavaScript objects are used for implementing map data
|
||||
structures. This case should be avoided whenever possible by using the
|
||||
ECMAScript 2015 <code>Map</code> instead. When this is not possible, an
|
||||
alternative fix is to prepend untrusted input with a marker character
|
||||
such as <code>$</code>, before using it in properties accesses. In this way,
|
||||
the attacker does not have access to built-in properties which do not
|
||||
start with the chosen character.
|
||||
</p>
|
||||
<p>
|
||||
When using user input as part of a header name, a sanitization
|
||||
step should be performed on the input to ensure that the name does not
|
||||
clash with existing header names such as
|
||||
<code>Content-Security-Policy</code>.
|
||||
</p>
|
||||
</recommendation>
|
||||
|
||||
<example>
|
||||
<p>
|
||||
In the example below, the dynamically computed property
|
||||
<code>prop</code> is accessed on <code>myObj</code> using a
|
||||
user-controlled value.
|
||||
</p>
|
||||
|
||||
<sample src="examples/RemotePropertyInjection.js"/>
|
||||
|
||||
<p>
|
||||
This is not secure since an attacker may exploit this code to
|
||||
overwrite the property <code>__proto__</code> with an empty function.
|
||||
If this happens, the concatenation in the <code>console.log</code>
|
||||
argument will fail with a confusing message such as
|
||||
"Function.prototype.toString is not generic". If the application does
|
||||
not properly handle this error, this scenario may result in a serious
|
||||
denial-of-service attack. The fix is to prepend the user-controlled
|
||||
string with a marker character such as <code>$</code> which will
|
||||
prevent arbitrary property names from being overwritten.
|
||||
</p>
|
||||
|
||||
<sample src="examples/RemotePropertyInjection_fixed.js"/>
|
||||
</example>
|
||||
|
||||
<references>
|
||||
<li>Prototype pollution attacks:
|
||||
<a href="https://github.com/electron/electron/pull/9287">electron</a>,
|
||||
<a href="https://hackerone.com/reports/310443">lodash</a>,
|
||||
<a href="https://npmjs.com/advisories/566">hoek</a>.
|
||||
</li>
|
||||
<li> Penetration testing report:
|
||||
<a href="http://seclists.org/pen-test/2009/Mar/67">
|
||||
header name injection attack</a>
|
||||
</li>
|
||||
<li> npm blog post:
|
||||
<a href="https://github.com/nodesecurity/eslint-plugin-security/blob/3c7522ca1be800353513282867a1034c795d9eb4/docs/the-dangers-of-square-bracket-notation.md">
|
||||
dangers of square bracket notation</a>
|
||||
</li>
|
||||
</references>
|
||||
<include src="RemotePropertyInjection.inc.qhelp" />
|
||||
</qhelp>
|
|
@ -0,0 +1,52 @@
|
|||
<!DOCTYPE qhelp PUBLIC "-//Semmle//qhelp//EN" "qhelp.dtd">
|
||||
<qhelp>
|
||||
|
||||
<overview>
|
||||
<p>
|
||||
Deserializing untrusted data using any deserialization framework that
|
||||
allows the construction of arbitrary functions is easily exploitable
|
||||
and, in many cases, allows an attacker to execute arbitrary code.
|
||||
</p>
|
||||
</overview>
|
||||
|
||||
<recommendation>
|
||||
<p>
|
||||
Avoid deserialization of untrusted data if at all possible. If the
|
||||
architecture permits it, then use formats like JSON or XML that cannot
|
||||
represent functions. When using YAML or other formats that support the
|
||||
serialization and deserialization of functions, ensure that the parser
|
||||
is configured to disable deserialization of arbitrary functions.
|
||||
</p>
|
||||
</recommendation>
|
||||
|
||||
<example>
|
||||
<p>
|
||||
The following example calls the <code>load</code> function of the popular
|
||||
<code>js-yaml</code> package on data that comes from an HTTP request and
|
||||
hence is inherently unsafe.
|
||||
</p>
|
||||
<sample src="examples/UnsafeDeserializationBad.js"/>
|
||||
<p>
|
||||
Using the <code>safeLoad</code> function instead (which does not deserialize
|
||||
YAML-encoded functions) removes the vulnerability.
|
||||
</p>
|
||||
<sample src="examples/UnsafeDeserializationGood.js" />
|
||||
</example>
|
||||
|
||||
<references>
|
||||
|
||||
<li>
|
||||
OWASP vulnerability description:
|
||||
<a href="https://www.owasp.org/index.php/Deserialization_of_untrusted_data">Deserialization of untrusted data</a>.
|
||||
</li>
|
||||
<li>
|
||||
OWASP guidance on deserializing objects:
|
||||
<a href="https://cheatsheetseries.owasp.org/cheatsheets/Deserialization_Cheat_Sheet.html">Deserialization Cheat Sheet</a>.
|
||||
</li>
|
||||
<li>
|
||||
Neal Poole:
|
||||
<a href="https://nealpoole.com/blog/2013/06/code-execution-via-yaml-in-js-yaml-nodejs-module/">Code Execution via YAML in JS-YAML Node.js Module</a>.
|
||||
</li>
|
||||
</references>
|
||||
|
||||
</qhelp>
|
|
@ -1,52 +1,6 @@
|
|||
<!DOCTYPE qhelp PUBLIC "-//Semmle//qhelp//EN" "qhelp.dtd">
|
||||
<!DOCTYPE qhelp PUBLIC
|
||||
"-//Semmle//qhelp//EN"
|
||||
"qhelp.dtd">
|
||||
<qhelp>
|
||||
|
||||
<overview>
|
||||
<p>
|
||||
Deserializing untrusted data using any deserialization framework that
|
||||
allows the construction of arbitrary functions is easily exploitable
|
||||
and, in many cases, allows an attacker to execute arbitrary code.
|
||||
</p>
|
||||
</overview>
|
||||
|
||||
<recommendation>
|
||||
<p>
|
||||
Avoid deserialization of untrusted data if at all possible. If the
|
||||
architecture permits it, then use formats like JSON or XML that cannot
|
||||
represent functions. When using YAML or other formats that support the
|
||||
serialization and deserialization of functions, ensure that the parser
|
||||
is configured to disable deserialization of arbitrary functions.
|
||||
</p>
|
||||
</recommendation>
|
||||
|
||||
<example>
|
||||
<p>
|
||||
The following example calls the <code>load</code> function of the popular
|
||||
<code>js-yaml</code> package on data that comes from an HTTP request and
|
||||
hence is inherently unsafe.
|
||||
</p>
|
||||
<sample src="examples/UnsafeDeserializationBad.js"/>
|
||||
<p>
|
||||
Using the <code>safeLoad</code> function instead (which does not deserialize
|
||||
YAML-encoded functions) removes the vulnerability.
|
||||
</p>
|
||||
<sample src="examples/UnsafeDeserializationGood.js" />
|
||||
</example>
|
||||
|
||||
<references>
|
||||
|
||||
<li>
|
||||
OWASP vulnerability description:
|
||||
<a href="https://www.owasp.org/index.php/Deserialization_of_untrusted_data">Deserialization of untrusted data</a>.
|
||||
</li>
|
||||
<li>
|
||||
OWASP guidance on deserializing objects:
|
||||
<a href="https://cheatsheetseries.owasp.org/cheatsheets/Deserialization_Cheat_Sheet.html">Deserialization Cheat Sheet</a>.
|
||||
</li>
|
||||
<li>
|
||||
Neal Poole:
|
||||
<a href="https://nealpoole.com/blog/2013/06/code-execution-via-yaml-in-js-yaml-nodejs-module/">Code Execution via YAML in JS-YAML Node.js Module</a>.
|
||||
</li>
|
||||
</references>
|
||||
|
||||
<include src="UnsafeDeserialization.inc.qhelp" />
|
||||
</qhelp>
|
|
@ -0,0 +1,57 @@
|
|||
<!DOCTYPE qhelp PUBLIC "-//Semmle//qhelp//EN" "qhelp.dtd">
|
||||
<qhelp>
|
||||
|
||||
<overview>
|
||||
<p>
|
||||
Parsing untrusted XML files with a weakly configured XML parser may lead to an
|
||||
XML External Entity (XXE) attack. This type of attack uses external entity references
|
||||
to access arbitrary files on a system, carry out denial-of-service (DoS) attacks, or server-side
|
||||
request forgery. Even when the result of parsing is not returned to the user, DoS attacks are still possible
|
||||
and out-of-band data retrieval techniques may allow attackers to steal sensitive data.
|
||||
</p>
|
||||
</overview>
|
||||
|
||||
<recommendation>
|
||||
<p>
|
||||
The easiest way to prevent XXE attacks is to disable external entity handling when
|
||||
parsing untrusted data. How this is done depends on the library being used. Note that some
|
||||
libraries, such as recent versions of <code>libxml</code>, disable entity expansion by default,
|
||||
so unless you have explicitly enabled entity expansion, no further action needs to be taken.
|
||||
</p>
|
||||
</recommendation>
|
||||
|
||||
<example>
|
||||
<p>
|
||||
The following example uses the <code>libxml</code> XML parser to parse a string <code>xmlSrc</code>.
|
||||
If that string is from an untrusted source, this code may be vulnerable to an XXE attack, since
|
||||
the parser is invoked with the <code>noent</code> option set to <code>true</code>:
|
||||
</p>
|
||||
<sample src="examples/Xxe.js"/>
|
||||
|
||||
<p>
|
||||
To guard against XXE attacks, the <code>noent</code> option should be omitted or set to
|
||||
<code>false</code>. This means that no entity expansion is undertaken at all, not even for standard
|
||||
internal entities such as <code>&amp;</code> or <code>&gt;</code>. If desired, these
|
||||
entities can be expanded in a separate step using utility functions provided by libraries such
|
||||
as <a href="http://underscorejs.org/#unescape">underscore</a>,
|
||||
<a href="https://lodash.com/docs/4.17.15#unescape">lodash</a> or
|
||||
<a href="https://github.com/mathiasbynens/he">he</a>.
|
||||
</p>
|
||||
<sample src="examples/XxeGood.js"/>
|
||||
</example>
|
||||
|
||||
<references>
|
||||
<li>
|
||||
OWASP:
|
||||
<a href="https://www.owasp.org/index.php/XML_External_Entity_(XXE)_Processing">XML External Entity (XXE) Processing</a>.
|
||||
</li>
|
||||
<li>
|
||||
Timothy Morgen:
|
||||
<a href="https://research.nccgroup.com/2014/05/19/xml-schema-dtd-and-entity-attacks-a-compendium-of-known-techniques/">XML Schema, DTD, and Entity Attacks</a>.
|
||||
</li>
|
||||
<li>
|
||||
Timur Yunusov, Alexey Osipov:
|
||||
<a href="https://www.slideshare.net/qqlan/bh-ready-v4">XML Out-Of-Band Data Retrieval</a>.
|
||||
</li>
|
||||
</references>
|
||||
</qhelp>
|
|
@ -1,57 +1,6 @@
|
|||
<!DOCTYPE qhelp PUBLIC "-//Semmle//qhelp//EN" "qhelp.dtd">
|
||||
<!DOCTYPE qhelp PUBLIC
|
||||
"-//Semmle//qhelp//EN"
|
||||
"qhelp.dtd">
|
||||
<qhelp>
|
||||
|
||||
<overview>
|
||||
<p>
|
||||
Parsing untrusted XML files with a weakly configured XML parser may lead to an
|
||||
XML External Entity (XXE) attack. This type of attack uses external entity references
|
||||
to access arbitrary files on a system, carry out denial-of-service (DoS) attacks, or server-side
|
||||
request forgery. Even when the result of parsing is not returned to the user, DoS attacks are still possible
|
||||
and out-of-band data retrieval techniques may allow attackers to steal sensitive data.
|
||||
</p>
|
||||
</overview>
|
||||
|
||||
<recommendation>
|
||||
<p>
|
||||
The easiest way to prevent XXE attacks is to disable external entity handling when
|
||||
parsing untrusted data. How this is done depends on the library being used. Note that some
|
||||
libraries, such as recent versions of <code>libxml</code>, disable entity expansion by default,
|
||||
so unless you have explicitly enabled entity expansion, no further action needs to be taken.
|
||||
</p>
|
||||
</recommendation>
|
||||
|
||||
<example>
|
||||
<p>
|
||||
The following example uses the <code>libxml</code> XML parser to parse a string <code>xmlSrc</code>.
|
||||
If that string is from an untrusted source, this code may be vulnerable to an XXE attack, since
|
||||
the parser is invoked with the <code>noent</code> option set to <code>true</code>:
|
||||
</p>
|
||||
<sample src="examples/Xxe.js"/>
|
||||
|
||||
<p>
|
||||
To guard against XXE attacks, the <code>noent</code> option should be omitted or set to
|
||||
<code>false</code>. This means that no entity expansion is undertaken at all, not even for standard
|
||||
internal entities such as <code>&amp;</code> or <code>&gt;</code>. If desired, these
|
||||
entities can be expanded in a separate step using utility functions provided by libraries such
|
||||
as <a href="http://underscorejs.org/#unescape">underscore</a>,
|
||||
<a href="https://lodash.com/docs/4.17.15#unescape">lodash</a> or
|
||||
<a href="https://github.com/mathiasbynens/he">he</a>.
|
||||
</p>
|
||||
<sample src="examples/XxeGood.js"/>
|
||||
</example>
|
||||
|
||||
<references>
|
||||
<li>
|
||||
OWASP:
|
||||
<a href="https://www.owasp.org/index.php/XML_External_Entity_(XXE)_Processing">XML External Entity (XXE) Processing</a>.
|
||||
</li>
|
||||
<li>
|
||||
Timothy Morgen:
|
||||
<a href="https://research.nccgroup.com/2014/05/19/xml-schema-dtd-and-entity-attacks-a-compendium-of-known-techniques/">XML Schema, DTD, and Entity Attacks</a>.
|
||||
</li>
|
||||
<li>
|
||||
Timur Yunusov, Alexey Osipov:
|
||||
<a href="https://www.slideshare.net/qqlan/bh-ready-v4">XML Out-Of-Band Data Retrieval</a>.
|
||||
</li>
|
||||
</references>
|
||||
<include src="Xxe.inc.qhelp" />
|
||||
</qhelp>
|
|
@ -0,0 +1,40 @@
|
|||
<!DOCTYPE qhelp PUBLIC
|
||||
"-//Semmle//qhelp//EN"
|
||||
"qhelp.dtd">
|
||||
<qhelp>
|
||||
<overview>
|
||||
<p>
|
||||
If an XPath expression is built using string concatenation, and the components of the concatenation
|
||||
include user input, it makes it very easy for a user to create a malicious XPath expression.
|
||||
</p>
|
||||
</overview>
|
||||
|
||||
<recommendation>
|
||||
<p>
|
||||
If user input must be included in an XPath expression, either sanitize the data or use variable
|
||||
references to safely embed it without altering the structure of the expression.
|
||||
</p>
|
||||
</recommendation>
|
||||
|
||||
<example>
|
||||
<p>
|
||||
In this example, the code accepts a user name specified by the user, and uses this
|
||||
unvalidated and unsanitized value in an XPath expression constructed using the <code>xpath</code>
|
||||
package. This is vulnerable to the user providing special characters or string sequences
|
||||
that change the meaning of the XPath expression to search for different values.
|
||||
</p>
|
||||
<sample src="examples/XpathInjectionBad.js" />
|
||||
|
||||
<p>
|
||||
Instead, embed the user input using the variable replacement mechanism offered
|
||||
by <code>xpath</code>:
|
||||
</p>
|
||||
<sample src="examples/XpathInjectionGood.js" />
|
||||
</example>
|
||||
|
||||
<references>
|
||||
<li>OWASP: <a href="https://owasp.org/www-project-web-security-testing-guide/latest/4-Web_Application_Security_Testing/07-Input_Validation_Testing/09-Testing_for_XPath_Injection">Testing for XPath Injection</a>.</li>
|
||||
<li>OWASP: <a href="https://www.owasp.org/index.php/XPATH_Injection">XPath Injection</a>.</li>
|
||||
<li>npm: <a href="https://www.npmjs.com/package/xpath">xpath</a>.</li>
|
||||
</references>
|
||||
</qhelp>
|
|
@ -1,40 +1,6 @@
|
|||
<!DOCTYPE qhelp PUBLIC
|
||||
"-//Semmle//qhelp//EN"
|
||||
"qhelp.dtd">
|
||||
"-//Semmle//qhelp//EN"
|
||||
"qhelp.dtd">
|
||||
<qhelp>
|
||||
<overview>
|
||||
<p>
|
||||
If an XPath expression is built using string concatenation, and the components of the concatenation
|
||||
include user input, it makes it very easy for a user to create a malicious XPath expression.
|
||||
</p>
|
||||
</overview>
|
||||
|
||||
<recommendation>
|
||||
<p>
|
||||
If user input must be included in an XPath expression, either sanitize the data or use variable
|
||||
references to safely embed it without altering the structure of the expression.
|
||||
</p>
|
||||
</recommendation>
|
||||
|
||||
<example>
|
||||
<p>
|
||||
In this example, the code accepts a user name specified by the user, and uses this
|
||||
unvalidated and unsanitized value in an XPath expression constructed using the <code>xpath</code>
|
||||
package. This is vulnerable to the user providing special characters or string sequences
|
||||
that change the meaning of the XPath expression to search for different values.
|
||||
</p>
|
||||
<sample src="examples/XpathInjectionBad.js" />
|
||||
|
||||
<p>
|
||||
Instead, embed the user input using the variable replacement mechanism offered
|
||||
by <code>xpath</code>:
|
||||
</p>
|
||||
<sample src="examples/XpathInjectionGood.js" />
|
||||
</example>
|
||||
|
||||
<references>
|
||||
<li>OWASP: <a href="https://owasp.org/www-project-web-security-testing-guide/latest/4-Web_Application_Security_Testing/07-Input_Validation_Testing/09-Testing_for_XPath_Injection">Testing for XPath Injection</a>.</li>
|
||||
<li>OWASP: <a href="https://www.owasp.org/index.php/XPATH_Injection">XPath Injection</a>.</li>
|
||||
<li>npm: <a href="https://www.npmjs.com/package/xpath">xpath</a>.</li>
|
||||
</references>
|
||||
<include src="XpathInjection.inc.qhelp" />
|
||||
</qhelp>
|
|
@ -0,0 +1,48 @@
|
|||
<!DOCTYPE qhelp PUBLIC
|
||||
"-//Semmle//qhelp//EN"
|
||||
"qhelp.dtd">
|
||||
<qhelp>
|
||||
|
||||
<overview>
|
||||
<p>
|
||||
Constructing a regular expression with unsanitized user input is dangerous as a malicious user may
|
||||
be able to modify the meaning of the expression. In particular, such a user may be able to provide
|
||||
a regular expression fragment that takes exponential time in the worst case, and use that to
|
||||
perform a Denial of Service attack.
|
||||
</p>
|
||||
</overview>
|
||||
|
||||
<recommendation>
|
||||
<p>
|
||||
Before embedding user input into a regular expression, use a sanitization function such as
|
||||
lodash's <code>_.escapeRegExp</code> to escape meta-characters that have special meaning.
|
||||
</p>
|
||||
</recommendation>
|
||||
|
||||
<example>
|
||||
<p>
|
||||
The following example shows a HTTP request parameter that is used to construct a regular expression
|
||||
without sanitizing it first:
|
||||
</p>
|
||||
<sample src="examples/RegExpInjection.js" />
|
||||
<p>
|
||||
Instead, the request parameter should be sanitized first, for example using the function
|
||||
<code>_.escapeRegExp</code> from the lodash package. This ensures that the user cannot insert
|
||||
characters which have a special meaning in regular expressions.
|
||||
</p>
|
||||
<sample src="examples/RegExpInjectionGood.js" />
|
||||
</example>
|
||||
|
||||
<references>
|
||||
<li>
|
||||
OWASP:
|
||||
<a href="https://www.owasp.org/index.php/Regular_expression_Denial_of_Service_-_ReDoS">Regular expression Denial of Service - ReDoS</a>.
|
||||
</li>
|
||||
<li>
|
||||
Wikipedia: <a href="https://en.wikipedia.org/wiki/ReDoS">ReDoS</a>.
|
||||
</li>
|
||||
<li>
|
||||
npm: <a href="https://www.npmjs.com/package/lodash">lodash</a>.
|
||||
</li>
|
||||
</references>
|
||||
</qhelp>
|
|
@ -1,48 +1,6 @@
|
|||
<!DOCTYPE qhelp PUBLIC
|
||||
"-//Semmle//qhelp//EN"
|
||||
"qhelp.dtd">
|
||||
"-//Semmle//qhelp//EN"
|
||||
"qhelp.dtd">
|
||||
<qhelp>
|
||||
|
||||
<overview>
|
||||
<p>
|
||||
Constructing a regular expression with unsanitized user input is dangerous as a malicious user may
|
||||
be able to modify the meaning of the expression. In particular, such a user may be able to provide
|
||||
a regular expression fragment that takes exponential time in the worst case, and use that to
|
||||
perform a Denial of Service attack.
|
||||
</p>
|
||||
</overview>
|
||||
|
||||
<recommendation>
|
||||
<p>
|
||||
Before embedding user input into a regular expression, use a sanitization function such as
|
||||
lodash's <code>_.escapeRegExp</code> to escape meta-characters that have special meaning.
|
||||
</p>
|
||||
</recommendation>
|
||||
|
||||
<example>
|
||||
<p>
|
||||
The following example shows a HTTP request parameter that is used to construct a regular expression
|
||||
without sanitizing it first:
|
||||
</p>
|
||||
<sample src="examples/RegExpInjection.js" />
|
||||
<p>
|
||||
Instead, the request parameter should be sanitized first, for example using the function
|
||||
<code>_.escapeRegExp</code> from the lodash package. This ensures that the user cannot insert
|
||||
characters which have a special meaning in regular expressions.
|
||||
</p>
|
||||
<sample src="examples/RegExpInjectionGood.js" />
|
||||
</example>
|
||||
|
||||
<references>
|
||||
<li>
|
||||
OWASP:
|
||||
<a href="https://www.owasp.org/index.php/Regular_expression_Denial_of_Service_-_ReDoS">Regular expression Denial of Service - ReDoS</a>.
|
||||
</li>
|
||||
<li>
|
||||
Wikipedia: <a href="https://en.wikipedia.org/wiki/ReDoS">ReDoS</a>.
|
||||
</li>
|
||||
<li>
|
||||
npm: <a href="https://www.npmjs.com/package/lodash">lodash</a>.
|
||||
</li>
|
||||
</references>
|
||||
<include src="RegExpInjection.inc.qhelp" />
|
||||
</qhelp>
|
|
@ -0,0 +1,115 @@
|
|||
<!DOCTYPE qhelp PUBLIC
|
||||
"-//Semmle//qhelp//EN"
|
||||
"qhelp.dtd">
|
||||
<qhelp>
|
||||
|
||||
<overview>
|
||||
|
||||
<p>
|
||||
|
||||
Applications are constrained by how many resources they can make use
|
||||
of. Failing to respect these constraints may cause the application to
|
||||
be unresponsive or crash. It is therefore problematic if attackers
|
||||
can control the sizes or lifetimes of allocated objects.
|
||||
|
||||
</p>
|
||||
|
||||
</overview>
|
||||
|
||||
<recommendation>
|
||||
|
||||
<p>
|
||||
|
||||
Ensure that attackers can not control object sizes and their
|
||||
lifetimes. If object sizes and lifetimes must be controlled by
|
||||
external parties, ensure you restrict the object sizes and lifetimes so that
|
||||
they are within acceptable ranges.
|
||||
|
||||
</p>
|
||||
|
||||
</recommendation>
|
||||
|
||||
<example>
|
||||
|
||||
<p>
|
||||
|
||||
The following example allocates a buffer with a user-controlled
|
||||
size.
|
||||
|
||||
</p>
|
||||
|
||||
<sample src="examples/ResourceExhaustion_buffer.js" />
|
||||
|
||||
<p>
|
||||
|
||||
This is problematic since an attacker can choose a size
|
||||
that makes the application run out of memory. Even worse, in older
|
||||
versions of Node.js, this could leak confidential memory.
|
||||
|
||||
To prevent such attacks, limit the buffer size:
|
||||
|
||||
</p>
|
||||
|
||||
<sample src="examples/ResourceExhaustion_buffer_fixed.js" />
|
||||
|
||||
</example>
|
||||
|
||||
<example>
|
||||
|
||||
<p>
|
||||
|
||||
As another example, consider an application that allocates an
|
||||
array with a user-controlled size, and then fills it with values:
|
||||
|
||||
</p>
|
||||
|
||||
<sample src="examples/ResourceExhaustion_array.js" />
|
||||
|
||||
<p>
|
||||
The allocation of the array itself is not problematic since arrays are
|
||||
allocated sparsely, but the subsequent filling of the array will take
|
||||
a long time, causing the application to be unresponsive, or even run
|
||||
out of memory.
|
||||
|
||||
Again, a limit on the size will prevent the attack:
|
||||
|
||||
</p>
|
||||
|
||||
<sample src="examples/ResourceExhaustion_array_fixed.js" />
|
||||
|
||||
</example>
|
||||
|
||||
<example>
|
||||
|
||||
<p>
|
||||
|
||||
Finally, the following example lets a user choose a delay after
|
||||
which a function is executed:
|
||||
|
||||
</p>
|
||||
|
||||
<sample src="examples/ResourceExhaustion_timeout.js" />
|
||||
|
||||
<p>
|
||||
|
||||
This is problematic because a large delay essentially makes the
|
||||
application wait indefinitely before executing the function. Repeated
|
||||
registrations of such delays will therefore use up all of the memory
|
||||
in the application.
|
||||
|
||||
A limit on the delay will prevent the attack:
|
||||
|
||||
</p>
|
||||
|
||||
<sample src="examples/ResourceExhaustion_timeout_fixed.js" />
|
||||
|
||||
|
||||
</example>
|
||||
|
||||
<references>
|
||||
<li>
|
||||
Wikipedia: <a href="https://en.wikipedia.org/wiki/Denial-of-service_attack">Denial-of-service attack</a>.
|
||||
</li>
|
||||
</references>
|
||||
|
||||
</qhelp>
|
|
@ -2,114 +2,5 @@
|
|||
"-//Semmle//qhelp//EN"
|
||||
"qhelp.dtd">
|
||||
<qhelp>
|
||||
|
||||
<overview>
|
||||
|
||||
<p>
|
||||
|
||||
Applications are constrained by how many resources they can make use
|
||||
of. Failing to respect these constraints may cause the application to
|
||||
be unresponsive or crash. It is therefore problematic if attackers
|
||||
can control the sizes or lifetimes of allocated objects.
|
||||
|
||||
</p>
|
||||
|
||||
</overview>
|
||||
|
||||
<recommendation>
|
||||
|
||||
<p>
|
||||
|
||||
Ensure that attackers can not control object sizes and their
|
||||
lifetimes. If object sizes and lifetimes must be controlled by
|
||||
external parties, ensure you restrict the object sizes and lifetimes so that
|
||||
they are within acceptable ranges.
|
||||
|
||||
</p>
|
||||
|
||||
</recommendation>
|
||||
|
||||
<example>
|
||||
|
||||
<p>
|
||||
|
||||
The following example allocates a buffer with a user-controlled
|
||||
size.
|
||||
|
||||
</p>
|
||||
|
||||
<sample src="examples/ResourceExhaustion_buffer.js" />
|
||||
|
||||
<p>
|
||||
|
||||
This is problematic since an attacker can choose a size
|
||||
that makes the application run out of memory. Even worse, in older
|
||||
versions of Node.js, this could leak confidential memory.
|
||||
|
||||
To prevent such attacks, limit the buffer size:
|
||||
|
||||
</p>
|
||||
|
||||
<sample src="examples/ResourceExhaustion_buffer_fixed.js" />
|
||||
|
||||
</example>
|
||||
|
||||
<example>
|
||||
|
||||
<p>
|
||||
|
||||
As another example, consider an application that allocates an
|
||||
array with a user-controlled size, and then fills it with values:
|
||||
|
||||
</p>
|
||||
|
||||
<sample src="examples/ResourceExhaustion_array.js" />
|
||||
|
||||
<p>
|
||||
The allocation of the array itself is not problematic since arrays are
|
||||
allocated sparsely, but the subsequent filling of the array will take
|
||||
a long time, causing the application to be unresponsive, or even run
|
||||
out of memory.
|
||||
|
||||
Again, a limit on the size will prevent the attack:
|
||||
|
||||
</p>
|
||||
|
||||
<sample src="examples/ResourceExhaustion_array_fixed.js" />
|
||||
|
||||
</example>
|
||||
|
||||
<example>
|
||||
|
||||
<p>
|
||||
|
||||
Finally, the following example lets a user choose a delay after
|
||||
which a function is executed:
|
||||
|
||||
</p>
|
||||
|
||||
<sample src="examples/ResourceExhaustion_timeout.js" />
|
||||
|
||||
<p>
|
||||
|
||||
This is problematic because a large delay essentially makes the
|
||||
application wait indefinitely before executing the function. Repeated
|
||||
registrations of such delays will therefore use up all of the memory
|
||||
in the application.
|
||||
|
||||
A limit on the delay will prevent the attack:
|
||||
|
||||
</p>
|
||||
|
||||
<sample src="examples/ResourceExhaustion_timeout_fixed.js" />
|
||||
|
||||
|
||||
</example>
|
||||
|
||||
<references>
|
||||
<li>
|
||||
Wikipedia: <a href="https://en.wikipedia.org/wiki/Denial-of-service_attack">Denial-of-service attack</a>.
|
||||
</li>
|
||||
</references>
|
||||
|
||||
<include src="ResourceExhaustion.inc.qhelp" />
|
||||
</qhelp>
|
|
@ -0,0 +1,60 @@
|
|||
<!DOCTYPE qhelp PUBLIC "-//Semmle//qhelp//EN" "qhelp.dtd">
|
||||
<qhelp>
|
||||
|
||||
<overview>
|
||||
<p>
|
||||
Parsing untrusted XML files with a weakly configured XML parser may be vulnerable to
|
||||
denial-of-service (DoS) attacks exploiting uncontrolled internal entity expansion.
|
||||
</p>
|
||||
<p>
|
||||
In XML, so-called <i>internal entities</i> are a mechanism for introducing an abbreviation
|
||||
for a piece of text or part of a document. When a parser that has been configured
|
||||
to expand entities encounters a reference to an internal entity, it replaces the entity
|
||||
by the data it represents. The replacement text may itself contain other entity references,
|
||||
which are expanded recursively. This means that entity expansion can increase document size
|
||||
dramatically.
|
||||
</p>
|
||||
<p>
|
||||
If untrusted XML is parsed with entity expansion enabled, a malicious attacker could
|
||||
submit a document that contains very deeply nested entity definitions, causing the parser
|
||||
to take a very long time or use large amounts of memory. This is sometimes called an
|
||||
<i>XML bomb</i> attack.
|
||||
</p>
|
||||
</overview>
|
||||
|
||||
<recommendation>
|
||||
<p>
|
||||
The safest way to prevent XML bomb attacks is to disable entity expansion when parsing untrusted
|
||||
data. How this is done depends on the library being used. Note that some libraries, such as
|
||||
recent versions of <code>libxmljs</code> (though not its SAX parser API), disable entity expansion
|
||||
by default, so unless you have explicitly enabled entity expansion, no further action is needed.
|
||||
</p>
|
||||
</recommendation>
|
||||
|
||||
<example>
|
||||
<p>
|
||||
The following example uses the XML parser provided by the <code>node-expat</code> package to
|
||||
parse a string <code>xmlSrc</code>. If that string is from an untrusted source, this code may be
|
||||
vulnerable to a DoS attack, since <code>node-expat</code> expands internal entities by default:
|
||||
</p>
|
||||
<sample src="examples/XmlBomb.js"/>
|
||||
|
||||
<p>
|
||||
At the time of writing, <code>node-expat</code> does not provide a way of controlling entity
|
||||
expansion, but the example could be rewritten to use the <code>sax</code> package instead,
|
||||
which only expands standard entities such as <code>&amp;</code>:
|
||||
</p>
|
||||
<sample src="examples/XmlBombGood.js"/>
|
||||
</example>
|
||||
|
||||
<references>
|
||||
<li>
|
||||
Wikipedia:
|
||||
<a href="https://en.wikipedia.org/wiki/Billion_laughs">Billion Laughs</a>.
|
||||
</li>
|
||||
<li>
|
||||
Bryan Sullivan:
|
||||
<a href="https://msdn.microsoft.com/en-us/magazine/ee335713.aspx">Security Briefs - XML Denial of Service Attacks and Defenses</a>.
|
||||
</li>
|
||||
</references>
|
||||
</qhelp>
|
|
@ -1,60 +1,6 @@
|
|||
<!DOCTYPE qhelp PUBLIC "-//Semmle//qhelp//EN" "qhelp.dtd">
|
||||
<!DOCTYPE qhelp PUBLIC
|
||||
"-//Semmle//qhelp//EN"
|
||||
"qhelp.dtd">
|
||||
<qhelp>
|
||||
|
||||
<overview>
|
||||
<p>
|
||||
Parsing untrusted XML files with a weakly configured XML parser may be vulnerable to
|
||||
denial-of-service (DoS) attacks exploiting uncontrolled internal entity expansion.
|
||||
</p>
|
||||
<p>
|
||||
In XML, so-called <i>internal entities</i> are a mechanism for introducing an abbreviation
|
||||
for a piece of text or part of a document. When a parser that has been configured
|
||||
to expand entities encounters a reference to an internal entity, it replaces the entity
|
||||
by the data it represents. The replacement text may itself contain other entity references,
|
||||
which are expanded recursively. This means that entity expansion can increase document size
|
||||
dramatically.
|
||||
</p>
|
||||
<p>
|
||||
If untrusted XML is parsed with entity expansion enabled, a malicious attacker could
|
||||
submit a document that contains very deeply nested entity definitions, causing the parser
|
||||
to take a very long time or use large amounts of memory. This is sometimes called an
|
||||
<i>XML bomb</i> attack.
|
||||
</p>
|
||||
</overview>
|
||||
|
||||
<recommendation>
|
||||
<p>
|
||||
The safest way to prevent XML bomb attacks is to disable entity expansion when parsing untrusted
|
||||
data. How this is done depends on the library being used. Note that some libraries, such as
|
||||
recent versions of <code>libxmljs</code> (though not its SAX parser API), disable entity expansion
|
||||
by default, so unless you have explicitly enabled entity expansion, no further action is needed.
|
||||
</p>
|
||||
</recommendation>
|
||||
|
||||
<example>
|
||||
<p>
|
||||
The following example uses the XML parser provided by the <code>node-expat</code> package to
|
||||
parse a string <code>xmlSrc</code>. If that string is from an untrusted source, this code may be
|
||||
vulnerable to a DoS attack, since <code>node-expat</code> expands internal entities by default:
|
||||
</p>
|
||||
<sample src="examples/XmlBomb.js"/>
|
||||
|
||||
<p>
|
||||
At the time of writing, <code>node-expat</code> does not provide a way of controlling entity
|
||||
expansion, but the example could be rewritten to use the <code>sax</code> package instead,
|
||||
which only expands standard entities such as <code>&amp;</code>:
|
||||
</p>
|
||||
<sample src="examples/XmlBombGood.js"/>
|
||||
</example>
|
||||
|
||||
<references>
|
||||
<li>
|
||||
Wikipedia:
|
||||
<a href="https://en.wikipedia.org/wiki/Billion_laughs">Billion Laughs</a>.
|
||||
</li>
|
||||
<li>
|
||||
Bryan Sullivan:
|
||||
<a href="https://msdn.microsoft.com/en-us/magazine/ee335713.aspx">Security Briefs - XML Denial of Service Attacks and Defenses</a>.
|
||||
</li>
|
||||
</references>
|
||||
<include src="XmlBomb.inc.qhelp" />
|
||||
</qhelp>
|
|
@ -0,0 +1,27 @@
|
|||
<!DOCTYPE qhelp PUBLIC
|
||||
"-//Semmle//qhelp//EN"
|
||||
"qhelp.dtd">
|
||||
<qhelp>
|
||||
<overview>
|
||||
<p>
|
||||
|
||||
Using user-controlled data in a permissions check may
|
||||
allow a user to gain unauthorized access to protected functionality or
|
||||
data.
|
||||
|
||||
</p>
|
||||
|
||||
</overview>
|
||||
|
||||
<recommendation>
|
||||
<include src="recommendation.inc.qhelp" />
|
||||
</recommendation>
|
||||
|
||||
<example>
|
||||
<include src="example.inc.qhelp" />
|
||||
</example>
|
||||
|
||||
<references>
|
||||
|
||||
</references>
|
||||
</qhelp>
|
|
@ -2,26 +2,5 @@
|
|||
"-//Semmle//qhelp//EN"
|
||||
"qhelp.dtd">
|
||||
<qhelp>
|
||||
<overview>
|
||||
<p>
|
||||
|
||||
Using user-controlled data in a permissions check may
|
||||
allow a user to gain unauthorized access to protected functionality or
|
||||
data.
|
||||
|
||||
</p>
|
||||
|
||||
</overview>
|
||||
|
||||
<recommendation>
|
||||
<include src="recommendation.inc.qhelp" />
|
||||
</recommendation>
|
||||
|
||||
<example>
|
||||
<include src="example.inc.qhelp" />
|
||||
</example>
|
||||
|
||||
<references>
|
||||
|
||||
</references>
|
||||
<include src="ConditionalBypass.inc.qhelp" />
|
||||
</qhelp>
|
|
@ -0,0 +1,62 @@
|
|||
<!DOCTYPE qhelp PUBLIC
|
||||
"-//Semmle//qhelp//EN"
|
||||
"qhelp.dtd">
|
||||
<qhelp>
|
||||
|
||||
<overview>
|
||||
<p>
|
||||
Most JavaScript objects inherit the properties of the built-in <code>Object.prototype</code> object.
|
||||
Prototype pollution is a type of vulnerability in which an attacker is able to modify <code>Object.prototype</code>.
|
||||
Since most objects inherit from the compromised <code>Object.prototype</code> object, the attacker can use this
|
||||
to tamper with the application logic, and often escalate to remote code execution or cross-site scripting.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
One way to cause prototype pollution is by modifying an object obtained via a user-controlled property name.
|
||||
Most objects have a special <code>__proto__</code> property that refers to <code>Object.prototype</code>.
|
||||
An attacker can abuse this special property to trick the application into performing unintended modifications
|
||||
of <code>Object.prototype</code>.
|
||||
</p>
|
||||
</overview>
|
||||
|
||||
<recommendation>
|
||||
<p>
|
||||
Use an associative data structure that is resilient to untrusted key values, such as a <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map">Map</a>.
|
||||
In some cases, a prototype-less object created with <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/create">Object.create(null)</a>
|
||||
may be preferable.
|
||||
</p>
|
||||
<p>
|
||||
Alternatively, restrict the computed property name so it can't clash with a built-in property, either by
|
||||
prefixing it with a constant string, or by rejecting inputs that don't conform to the expected format.
|
||||
</p>
|
||||
</recommendation>
|
||||
|
||||
<example>
|
||||
<p>
|
||||
In the example below, the untrusted value <code>req.params.id</code> is used as the property name
|
||||
<code>req.session.todos[id]</code>. If a malicious user passes in the ID value <code>__proto__</code>,
|
||||
the variable <code>todo</code> will then refer to <code>Object.prototype</code>.
|
||||
Finally, the modification of <code>todo</code> then allows the attacker to inject arbitrary properties
|
||||
onto <code>Object.prototype</code>.
|
||||
</p>
|
||||
|
||||
<sample src="examples/PrototypePollutingAssignment.js"/>
|
||||
|
||||
<p>
|
||||
One way to fix this is to use <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map">Map</a> objects to associate key/value pairs
|
||||
instead of regular objects, as shown below:
|
||||
</p>
|
||||
|
||||
<sample src="examples/PrototypePollutingAssignmentFixed.js"/>
|
||||
|
||||
</example>
|
||||
|
||||
<references>
|
||||
<li>MDN:
|
||||
<a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/proto">Object.prototype.__proto__</a>
|
||||
</li>
|
||||
<li>MDN:
|
||||
<a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map">Map</a>
|
||||
</li>
|
||||
</references>
|
||||
</qhelp>
|
|
@ -2,61 +2,5 @@
|
|||
"-//Semmle//qhelp//EN"
|
||||
"qhelp.dtd">
|
||||
<qhelp>
|
||||
|
||||
<overview>
|
||||
<p>
|
||||
Most JavaScript objects inherit the properties of the built-in <code>Object.prototype</code> object.
|
||||
Prototype pollution is a type of vulnerability in which an attacker is able to modify <code>Object.prototype</code>.
|
||||
Since most objects inherit from the compromised <code>Object.prototype</code> object, the attacker can use this
|
||||
to tamper with the application logic, and often escalate to remote code execution or cross-site scripting.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
One way to cause prototype pollution is by modifying an object obtained via a user-controlled property name.
|
||||
Most objects have a special <code>__proto__</code> property that refers to <code>Object.prototype</code>.
|
||||
An attacker can abuse this special property to trick the application into performing unintended modifications
|
||||
of <code>Object.prototype</code>.
|
||||
</p>
|
||||
</overview>
|
||||
|
||||
<recommendation>
|
||||
<p>
|
||||
Use an associative data structure that is resilient to untrusted key values, such as a <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map">Map</a>.
|
||||
In some cases, a prototype-less object created with <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/create">Object.create(null)</a>
|
||||
may be preferable.
|
||||
</p>
|
||||
<p>
|
||||
Alternatively, restrict the computed property name so it can't clash with a built-in property, either by
|
||||
prefixing it with a constant string, or by rejecting inputs that don't conform to the expected format.
|
||||
</p>
|
||||
</recommendation>
|
||||
|
||||
<example>
|
||||
<p>
|
||||
In the example below, the untrusted value <code>req.params.id</code> is used as the property name
|
||||
<code>req.session.todos[id]</code>. If a malicious user passes in the ID value <code>__proto__</code>,
|
||||
the variable <code>todo</code> will then refer to <code>Object.prototype</code>.
|
||||
Finally, the modification of <code>todo</code> then allows the attacker to inject arbitrary properties
|
||||
onto <code>Object.prototype</code>.
|
||||
</p>
|
||||
|
||||
<sample src="examples/PrototypePollutingAssignment.js"/>
|
||||
|
||||
<p>
|
||||
One way to fix this is to use <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map">Map</a> objects to associate key/value pairs
|
||||
instead of regular objects, as shown below:
|
||||
</p>
|
||||
|
||||
<sample src="examples/PrototypePollutingAssignmentFixed.js"/>
|
||||
|
||||
</example>
|
||||
|
||||
<references>
|
||||
<li>MDN:
|
||||
<a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/proto">Object.prototype.__proto__</a>
|
||||
</li>
|
||||
<li>MDN:
|
||||
<a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map">Map</a>
|
||||
</li>
|
||||
</references>
|
||||
<include src="PrototypePollutingAssignment.inc.qhelp" />
|
||||
</qhelp>
|
|
@ -0,0 +1,6 @@
|
|||
<!DOCTYPE qhelp PUBLIC
|
||||
"-//Semmle//qhelp//EN"
|
||||
"qhelp.dtd">
|
||||
<qhelp>
|
||||
<include src="../../../../../../Security/CWE-020/UntrustedDataToExternalAPI.inc.qhelp" />
|
||||
</qhelp>
|
|
@ -0,0 +1,22 @@
|
|||
/**
|
||||
* @name Untrusted data passed to external API with additional heuristic sources
|
||||
* @description Data provided remotely is used in this external API without sanitization, which could be a security risk.
|
||||
* @id js/untrusted-data-to-external-api-more-sources
|
||||
* @kind path-problem
|
||||
* @precision low
|
||||
* @problem.severity error
|
||||
* @security-severity 7.8
|
||||
* @tags experimental
|
||||
* security external/cwe/cwe-20
|
||||
*/
|
||||
|
||||
import javascript
|
||||
import semmle.javascript.security.dataflow.ExternalAPIUsedWithUntrustedDataQuery
|
||||
import DataFlow::PathGraph
|
||||
import semmle.javascript.heuristics.AdditionalSources
|
||||
|
||||
from Configuration config, DataFlow::PathNode source, DataFlow::PathNode sink
|
||||
where config.hasFlowPath(source, sink) and source.getNode() instanceof HeuristicSource
|
||||
select sink, source, sink,
|
||||
"Call to " + sink.getNode().(Sink).getApiName() + " with untrusted data from $@.", source,
|
||||
source.toString()
|
|
@ -0,0 +1,6 @@
|
|||
<!DOCTYPE qhelp PUBLIC
|
||||
"-//Semmle//qhelp//EN"
|
||||
"qhelp.dtd">
|
||||
<qhelp>
|
||||
<include src="../../../../../../Security/CWE-078/CommandInjection.inc.qhelp" />
|
||||
</qhelp>
|
|
@ -0,0 +1,35 @@
|
|||
/**
|
||||
* @name Uncontrolled command line with additional heuristic sources
|
||||
* @description Using externally controlled strings in a command line may allow a malicious
|
||||
* user to change the meaning of the command.
|
||||
* @kind path-problem
|
||||
* @problem.severity error
|
||||
* @security-severity 9.8
|
||||
* @precision high
|
||||
* @id js/command-line-injection-more-sources
|
||||
* @tags experimental
|
||||
* correctness
|
||||
* security
|
||||
* external/cwe/cwe-078
|
||||
* external/cwe/cwe-088
|
||||
*/
|
||||
|
||||
import javascript
|
||||
import semmle.javascript.security.dataflow.CommandInjectionQuery
|
||||
import DataFlow::PathGraph
|
||||
import semmle.javascript.heuristics.AdditionalSources
|
||||
|
||||
from
|
||||
Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink, DataFlow::Node highlight,
|
||||
Source sourceNode
|
||||
where
|
||||
cfg.hasFlowPath(source, sink) and
|
||||
(
|
||||
if cfg.isSinkWithHighlight(sink.getNode(), _)
|
||||
then cfg.isSinkWithHighlight(sink.getNode(), highlight)
|
||||
else highlight = sink.getNode()
|
||||
) and
|
||||
sourceNode = source.getNode() and
|
||||
source.getNode() instanceof HeuristicSource
|
||||
select highlight, source, sink, "This command line depends on a $@.", source.getNode(),
|
||||
"user-provided value"
|
|
@ -0,0 +1,6 @@
|
|||
<!DOCTYPE qhelp PUBLIC
|
||||
"-//Semmle//qhelp//EN"
|
||||
"qhelp.dtd">
|
||||
<qhelp>
|
||||
<include src="../../../../../../Security/CWE-079/Xss.inc.qhelp" />
|
||||
</qhelp>
|
|
@ -0,0 +1,25 @@
|
|||
/**
|
||||
* @name Client-side cross-site scripting with additional heuristic sources
|
||||
* @description Writing user input directly to the DOM allows for
|
||||
* a cross-site scripting vulnerability.
|
||||
* @kind path-problem
|
||||
* @problem.severity error
|
||||
* @security-severity 6.1
|
||||
* @precision high
|
||||
* @id js/xss-more-sources
|
||||
* @tags experimental
|
||||
* security
|
||||
* external/cwe/cwe-079
|
||||
* external/cwe/cwe-116
|
||||
*/
|
||||
|
||||
import javascript
|
||||
import semmle.javascript.security.dataflow.DomBasedXssQuery
|
||||
import DataFlow::PathGraph
|
||||
import semmle.javascript.heuristics.AdditionalSources
|
||||
|
||||
from DataFlow::Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink
|
||||
where cfg.hasFlowPath(source, sink) and source.getNode() instanceof HeuristicSource
|
||||
select sink.getNode(), source, sink,
|
||||
sink.getNode().(Sink).getVulnerabilityKind() + " vulnerability due to $@.", source.getNode(),
|
||||
"user-provided value"
|
|
@ -0,0 +1,6 @@
|
|||
<!DOCTYPE qhelp PUBLIC
|
||||
"-//Semmle//qhelp//EN"
|
||||
"qhelp.dtd">
|
||||
<qhelp>
|
||||
<include src="../../../../../../Security/CWE-089/SqlInjection.inc.qhelp" />
|
||||
</qhelp>
|
|
@ -0,0 +1,32 @@
|
|||
/**
|
||||
* @name Database query built from user-controlled sources with additional heuristic sources
|
||||
* @description Building a database query from user-controlled sources is vulnerable to insertion of
|
||||
* malicious code by the user.
|
||||
* @kind path-problem
|
||||
* @problem.severity error
|
||||
* @security-severity 8.8
|
||||
* @precision high
|
||||
* @id js/sql-injection-more-sources
|
||||
* @tags experimental
|
||||
* security
|
||||
* external/cwe/cwe-089
|
||||
* external/cwe/cwe-090
|
||||
* external/cwe/cwe-943
|
||||
*/
|
||||
|
||||
import javascript
|
||||
import semmle.javascript.security.dataflow.SqlInjectionQuery as SqlInjection
|
||||
import semmle.javascript.security.dataflow.NosqlInjectionQuery as NosqlInjection
|
||||
import DataFlow::PathGraph
|
||||
import semmle.javascript.heuristics.AdditionalSources
|
||||
|
||||
from DataFlow::Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink
|
||||
where
|
||||
(
|
||||
cfg instanceof SqlInjection::Configuration or
|
||||
cfg instanceof NosqlInjection::Configuration
|
||||
) and
|
||||
cfg.hasFlowPath(source, sink) and
|
||||
source.getNode() instanceof HeuristicSource
|
||||
select sink.getNode(), source, sink, "This query depends on a $@.", source.getNode(),
|
||||
"user-provided value"
|
|
@ -0,0 +1,6 @@
|
|||
<!DOCTYPE qhelp PUBLIC
|
||||
"-//Semmle//qhelp//EN"
|
||||
"qhelp.dtd">
|
||||
<qhelp>
|
||||
<include src="../../../../../../Security/CWE-094/CodeInjection.inc.qhelp" />
|
||||
</qhelp>
|
|
@ -0,0 +1,26 @@
|
|||
/**
|
||||
* @name Code injection with additional heuristic sources
|
||||
* @description Interpreting unsanitized user input as code allows a malicious user arbitrary
|
||||
* code execution.
|
||||
* @kind path-problem
|
||||
* @problem.severity error
|
||||
* @security-severity 9.3
|
||||
* @precision high
|
||||
* @id js/code-injection-more-sources
|
||||
* @tags experimental
|
||||
* security
|
||||
* external/cwe/cwe-094
|
||||
* external/cwe/cwe-095
|
||||
* external/cwe/cwe-079
|
||||
* external/cwe/cwe-116
|
||||
*/
|
||||
|
||||
import javascript
|
||||
import semmle.javascript.security.dataflow.CodeInjectionQuery
|
||||
import DataFlow::PathGraph
|
||||
import semmle.javascript.heuristics.AdditionalSources
|
||||
|
||||
from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink
|
||||
where cfg.hasFlowPath(source, sink) and source.getNode() instanceof HeuristicSource
|
||||
select sink.getNode(), source, sink, sink.getNode().(Sink).getMessagePrefix() + " depends on a $@.",
|
||||
source.getNode(), "user-provided value"
|
|
@ -0,0 +1,6 @@
|
|||
<!DOCTYPE qhelp PUBLIC
|
||||
"-//Semmle//qhelp//EN"
|
||||
"qhelp.dtd">
|
||||
<qhelp>
|
||||
<include src="../../../../../../Security/CWE-117/LogInjection.inc.qhelp" />
|
||||
</qhelp>
|
|
@ -0,0 +1,23 @@
|
|||
/**
|
||||
* @name Log injection with additional heuristic sources
|
||||
* @description Building log entries from user-controlled sources is vulnerable to
|
||||
* insertion of forged log entries by a malicious user.
|
||||
* @kind path-problem
|
||||
* @problem.severity error
|
||||
* @security-severity 7.8
|
||||
* @precision medium
|
||||
* @id js/log-injection-more-sources
|
||||
* @tags experimental
|
||||
* security
|
||||
* external/cwe/cwe-117
|
||||
*/
|
||||
|
||||
import javascript
|
||||
import DataFlow::PathGraph
|
||||
import semmle.javascript.security.dataflow.LogInjectionQuery
|
||||
import semmle.javascript.heuristics.AdditionalSources
|
||||
|
||||
from LogInjectionConfiguration config, DataFlow::PathNode source, DataFlow::PathNode sink
|
||||
where config.hasFlowPath(source, sink) and source.getNode() instanceof HeuristicSource
|
||||
select sink.getNode(), source, sink, "Log entry depends on a $@.", source.getNode(),
|
||||
"user-provided value"
|
|
@ -0,0 +1,6 @@
|
|||
<!DOCTYPE qhelp PUBLIC
|
||||
"-//Semmle//qhelp//EN"
|
||||
"qhelp.dtd">
|
||||
<qhelp>
|
||||
<include src="../../../../../../Security/CWE-134/TaintedFormatString.inc.qhelp" />
|
||||
</qhelp>
|
|
@ -0,0 +1,22 @@
|
|||
/**
|
||||
* @name Use of externally-controlled format string with additional heuristic sources
|
||||
* @description Using external input in format strings can lead to garbled output.
|
||||
* @kind path-problem
|
||||
* @problem.severity warning
|
||||
* @security-severity 7.3
|
||||
* @precision high
|
||||
* @id js/tainted-format-string-more-sources
|
||||
* @tags experimental
|
||||
* security
|
||||
* external/cwe/cwe-134
|
||||
*/
|
||||
|
||||
import javascript
|
||||
import semmle.javascript.security.dataflow.TaintedFormatStringQuery
|
||||
import DataFlow::PathGraph
|
||||
import semmle.javascript.heuristics.AdditionalSources
|
||||
|
||||
from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink
|
||||
where cfg.hasFlowPath(source, sink) and source.getNode() instanceof HeuristicSource
|
||||
select sink.getNode(), source, sink, "Format string depends on a $@.", source.getNode(),
|
||||
"user-provided value"
|
|
@ -0,0 +1,6 @@
|
|||
<!DOCTYPE qhelp PUBLIC
|
||||
"-//Semmle//qhelp//EN"
|
||||
"qhelp.dtd">
|
||||
<qhelp>
|
||||
<include src="../../../../../../Security/CWE-346/CorsMisconfigurationForCredentials.inc.qhelp" />
|
||||
</qhelp>
|
|
@ -0,0 +1,25 @@
|
|||
/**
|
||||
* @name CORS misconfiguration for credentials transfer with additional heuristic sources
|
||||
* @description Misconfiguration of CORS HTTP headers allows for leaks of secret credentials.
|
||||
* @kind path-problem
|
||||
* @problem.severity error
|
||||
* @security-severity 7.5
|
||||
* @precision high
|
||||
* @id js/cors-misconfiguration-for-credentials-more-sources
|
||||
* @tags experimental
|
||||
* security
|
||||
* external/cwe/cwe-346
|
||||
* external/cwe/cwe-639
|
||||
* external/cwe/cwe-942
|
||||
*/
|
||||
|
||||
import javascript
|
||||
import semmle.javascript.security.dataflow.CorsMisconfigurationForCredentialsQuery
|
||||
import DataFlow::PathGraph
|
||||
import semmle.javascript.heuristics.AdditionalSources
|
||||
|
||||
from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink
|
||||
where cfg.hasFlowPath(source, sink) and source.getNode() instanceof HeuristicSource
|
||||
select sink.getNode(), source, sink, "$@ leak vulnerability due to a $@.",
|
||||
sink.getNode().(Sink).getCredentialsHeader(), "Credential", source.getNode(),
|
||||
"misconfigured CORS header value"
|
|
@ -0,0 +1,6 @@
|
|||
<!DOCTYPE qhelp PUBLIC
|
||||
"-//Semmle//qhelp//EN"
|
||||
"qhelp.dtd">
|
||||
<qhelp>
|
||||
<include src="../../../../../../Security/CWE-400/RemotePropertyInjection.inc.qhelp" />
|
||||
</qhelp>
|
|
@ -0,0 +1,24 @@
|
|||
/**
|
||||
* @name Remote property injection with additional heuristic sources
|
||||
* @description Allowing writes to arbitrary properties of an object may lead to
|
||||
* denial-of-service attacks.
|
||||
* @kind path-problem
|
||||
* @problem.severity warning
|
||||
* @security-severity 7.5
|
||||
* @precision medium
|
||||
* @id js/remote-property-injection-more-sources
|
||||
* @tags experimental
|
||||
* security
|
||||
* external/cwe/cwe-250
|
||||
* external/cwe/cwe-400
|
||||
*/
|
||||
|
||||
import javascript
|
||||
import semmle.javascript.security.dataflow.RemotePropertyInjectionQuery
|
||||
import DataFlow::PathGraph
|
||||
import semmle.javascript.heuristics.AdditionalSources
|
||||
|
||||
from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink
|
||||
where cfg.hasFlowPath(source, sink) and source.getNode() instanceof HeuristicSource
|
||||
select sink.getNode(), source, sink, sink.getNode().(Sink).getMessage() + " depends on a $@.",
|
||||
source.getNode(), "user-provided value"
|
|
@ -0,0 +1,6 @@
|
|||
<!DOCTYPE qhelp PUBLIC
|
||||
"-//Semmle//qhelp//EN"
|
||||
"qhelp.dtd">
|
||||
<qhelp>
|
||||
<include src="../../../../../../Security/CWE-502/UnsafeDeserialization.inc.qhelp" />
|
||||
</qhelp>
|
|
@ -0,0 +1,23 @@
|
|||
/**
|
||||
* @name Deserialization of user-controlled data with additional heuristic sources
|
||||
* @description Deserializing user-controlled data may allow attackers to
|
||||
* execute arbitrary code.
|
||||
* @kind path-problem
|
||||
* @problem.severity warning
|
||||
* @security-severity 9.8
|
||||
* @precision high
|
||||
* @id js/unsafe-deserialization-more-sources
|
||||
* @tags experimental
|
||||
* security
|
||||
* external/cwe/cwe-502
|
||||
*/
|
||||
|
||||
import javascript
|
||||
import semmle.javascript.security.dataflow.UnsafeDeserializationQuery
|
||||
import DataFlow::PathGraph
|
||||
import semmle.javascript.heuristics.AdditionalSources
|
||||
|
||||
from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink
|
||||
where cfg.hasFlowPath(source, sink) and source.getNode() instanceof HeuristicSource
|
||||
select sink.getNode(), source, sink, "Unsafe deserialization depends on a $@.", source.getNode(),
|
||||
"user-provided value"
|
|
@ -0,0 +1,6 @@
|
|||
<!DOCTYPE qhelp PUBLIC
|
||||
"-//Semmle//qhelp//EN"
|
||||
"qhelp.dtd">
|
||||
<qhelp>
|
||||
<include src="../../../../../../Security/CWE-611/Xxe.inc.qhelp" />
|
||||
</qhelp>
|
|
@ -0,0 +1,25 @@
|
|||
/**
|
||||
* @name XML external entity expansion with additional heuristic sources
|
||||
* @description Parsing user input as an XML document with external
|
||||
* entity expansion is vulnerable to XXE attacks.
|
||||
* @kind path-problem
|
||||
* @problem.severity error
|
||||
* @security-severity 9.1
|
||||
* @precision high
|
||||
* @id js/xxe-more-sources
|
||||
* @tags experimental
|
||||
* security
|
||||
* external/cwe/cwe-611
|
||||
* external/cwe/cwe-827
|
||||
*/
|
||||
|
||||
import javascript
|
||||
import semmle.javascript.security.dataflow.XxeQuery
|
||||
import DataFlow::PathGraph
|
||||
import semmle.javascript.heuristics.AdditionalSources
|
||||
|
||||
from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink
|
||||
where cfg.hasFlowPath(source, sink) and source.getNode() instanceof HeuristicSource
|
||||
select sink.getNode(), source, sink,
|
||||
"XML parsing depends on a $@ without guarding against external entity expansion.",
|
||||
source.getNode(), "user-provided value"
|
|
@ -0,0 +1,6 @@
|
|||
<!DOCTYPE qhelp PUBLIC
|
||||
"-//Semmle//qhelp//EN"
|
||||
"qhelp.dtd">
|
||||
<qhelp>
|
||||
<include src="../../../../../../Security/CWE-643/XpathInjection.inc.qhelp" />
|
||||
</qhelp>
|
|
@ -0,0 +1,23 @@
|
|||
/**
|
||||
* @name XPath injection with additional heuristic sources
|
||||
* @description Building an XPath expression from user-controlled sources is vulnerable to insertion of
|
||||
* malicious code by the user.
|
||||
* @kind path-problem
|
||||
* @problem.severity error
|
||||
* @security-severity 9.8
|
||||
* @precision high
|
||||
* @id js/xpath-injection-more-sources
|
||||
* @tags experimental
|
||||
* security
|
||||
* external/cwe/cwe-643
|
||||
*/
|
||||
|
||||
import javascript
|
||||
import semmle.javascript.security.dataflow.XpathInjectionQuery
|
||||
import DataFlow::PathGraph
|
||||
import semmle.javascript.heuristics.AdditionalSources
|
||||
|
||||
from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink
|
||||
where cfg.hasFlowPath(source, sink) and source.getNode() instanceof HeuristicSource
|
||||
select sink.getNode(), source, sink, "XPath expression depends on a $@.", source.getNode(),
|
||||
"user-provided value"
|
|
@ -0,0 +1,6 @@
|
|||
<!DOCTYPE qhelp PUBLIC
|
||||
"-//Semmle//qhelp//EN"
|
||||
"qhelp.dtd">
|
||||
<qhelp>
|
||||
<include src="../../../../../../Security/CWE-730/RegExpInjection.inc.qhelp" />
|
||||
</qhelp>
|
|
@ -0,0 +1,25 @@
|
|||
/**
|
||||
* @name Regular expression injection with additional heuristic sources
|
||||
* @description User input should not be used in regular expressions without first being escaped,
|
||||
* otherwise a malicious user may be able to inject an expression that could require
|
||||
* exponential time on certain inputs.
|
||||
* @kind path-problem
|
||||
* @problem.severity error
|
||||
* @security-severity 7.5
|
||||
* @precision high
|
||||
* @id js/regex-injection-more-sources
|
||||
* @tags experimental
|
||||
* security
|
||||
* external/cwe/cwe-730
|
||||
* external/cwe/cwe-400
|
||||
*/
|
||||
|
||||
import javascript
|
||||
import semmle.javascript.security.dataflow.RegExpInjectionQuery
|
||||
import DataFlow::PathGraph
|
||||
import semmle.javascript.heuristics.AdditionalSources
|
||||
|
||||
from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink
|
||||
where cfg.hasFlowPath(source, sink) and source.getNode() instanceof HeuristicSource
|
||||
select sink.getNode(), source, sink, "This regular expression is constructed from a $@.",
|
||||
source.getNode(), "user-provided value"
|
|
@ -0,0 +1,6 @@
|
|||
<!DOCTYPE qhelp PUBLIC
|
||||
"-//Semmle//qhelp//EN"
|
||||
"qhelp.dtd">
|
||||
<qhelp>
|
||||
<include src="../../../../../../Security/CWE-770/ResourceExhaustion.inc.qhelp" />
|
||||
</qhelp>
|
|
@ -0,0 +1,24 @@
|
|||
/**
|
||||
* @name Resource exhaustion with additional heuristic sources
|
||||
* @description Allocating objects or timers with user-controlled
|
||||
* sizes or durations can cause resource exhaustion.
|
||||
* @kind path-problem
|
||||
* @problem.severity warning
|
||||
* @security-severity 7.5
|
||||
* @id js/resource-exhaustion-more-sources
|
||||
* @precision high
|
||||
* @tags experimental
|
||||
* security
|
||||
* external/cwe/cwe-400
|
||||
* external/cwe/cwe-770
|
||||
*/
|
||||
|
||||
import javascript
|
||||
import DataFlow::PathGraph
|
||||
import semmle.javascript.security.dataflow.ResourceExhaustionQuery
|
||||
import semmle.javascript.heuristics.AdditionalSources
|
||||
|
||||
from Configuration dataflow, DataFlow::PathNode source, DataFlow::PathNode sink
|
||||
where dataflow.hasFlowPath(source, sink) and source.getNode() instanceof HeuristicSource
|
||||
select sink, source, sink, sink.getNode().(Sink).getProblemDescription() + " from a $@.", source,
|
||||
"user-provided value"
|
|
@ -0,0 +1,6 @@
|
|||
<!DOCTYPE qhelp PUBLIC
|
||||
"-//Semmle//qhelp//EN"
|
||||
"qhelp.dtd">
|
||||
<qhelp>
|
||||
<include src="../../../../../../Security/CWE-776/XmlBomb.inc.qhelp" />
|
||||
</qhelp>
|
|
@ -0,0 +1,25 @@
|
|||
/**
|
||||
* @name XML internal entity expansion with additional heuristic sources
|
||||
* @description Parsing user input as an XML document with arbitrary internal
|
||||
* entity expansion is vulnerable to denial-of-service attacks.
|
||||
* @kind path-problem
|
||||
* @problem.severity warning
|
||||
* @security-severity 7.5
|
||||
* @precision high
|
||||
* @id js/xml-bomb-more-sources
|
||||
* @tags experimental
|
||||
* security
|
||||
* external/cwe/cwe-776
|
||||
* external/cwe/cwe-400
|
||||
*/
|
||||
|
||||
import javascript
|
||||
import semmle.javascript.security.dataflow.XmlBombQuery
|
||||
import DataFlow::PathGraph
|
||||
import semmle.javascript.heuristics.AdditionalSources
|
||||
|
||||
from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink
|
||||
where cfg.hasFlowPath(source, sink) and source.getNode() instanceof HeuristicSource
|
||||
select sink.getNode(), source, sink,
|
||||
"XML parsing depends on a $@ without guarding against uncontrolled entity expansion.",
|
||||
source.getNode(), "user-provided value"
|
|
@ -0,0 +1,6 @@
|
|||
<!DOCTYPE qhelp PUBLIC
|
||||
"-//Semmle//qhelp//EN"
|
||||
"qhelp.dtd">
|
||||
<qhelp>
|
||||
<include src="../../../../../../Security/CWE-807/ConditionalBypass.inc.qhelp" />
|
||||
</qhelp>
|
|
@ -0,0 +1,120 @@
|
|||
/**
|
||||
* @name User-controlled bypass of security check with additional heuristic sources
|
||||
* @description Conditions that the user controls are not suited for making security-related decisions.
|
||||
* @kind path-problem
|
||||
* @problem.severity error
|
||||
* @security-severity 7.8
|
||||
* @precision medium
|
||||
* @id js/user-controlled-bypass-more-sources
|
||||
* @tags experimental
|
||||
* security
|
||||
* external/cwe/cwe-807
|
||||
* external/cwe/cwe-290
|
||||
*/
|
||||
|
||||
import javascript
|
||||
import semmle.javascript.security.dataflow.ConditionalBypassQuery
|
||||
import DataFlow::PathGraph
|
||||
|
||||
/**
|
||||
* Holds if the value of `nd` flows into `guard`.
|
||||
*/
|
||||
predicate flowsToGuardExpr(DataFlow::Node nd, SensitiveActionGuardConditional guard) {
|
||||
nd = guard or
|
||||
flowsToGuardExpr(nd.getASuccessor(), guard)
|
||||
}
|
||||
|
||||
/**
|
||||
* A comparison that guards a sensitive action, e.g. the comparison in:
|
||||
* `var ok = x == y; if (ok) login()`.
|
||||
*/
|
||||
class SensitiveActionGuardComparison extends Comparison {
|
||||
SensitiveActionGuardConditional guard;
|
||||
|
||||
SensitiveActionGuardComparison() { flowsToGuardExpr(DataFlow::valueNode(this), guard) }
|
||||
|
||||
/**
|
||||
* Gets the guard that uses this comparison.
|
||||
*/
|
||||
SensitiveActionGuardConditional getGuard() { result = guard }
|
||||
}
|
||||
|
||||
/**
|
||||
* An intermediary sink to enable reuse of the taint configuration.
|
||||
* This sink should not be presented to the client of this query.
|
||||
*/
|
||||
class SensitiveActionGuardComparisonOperand extends Sink {
|
||||
SensitiveActionGuardComparison comparison;
|
||||
|
||||
SensitiveActionGuardComparisonOperand() { asExpr() = comparison.getAnOperand() }
|
||||
|
||||
override SensitiveAction getAction() { result = comparison.getGuard().getAction() }
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `sink` guards `action`, and `source` taints `sink`.
|
||||
*
|
||||
* If flow from `source` taints `sink`, then an attacker can
|
||||
* control if `action` should be executed or not.
|
||||
*/
|
||||
predicate isTaintedGuardForSensitiveAction(
|
||||
DataFlow::PathNode sink, DataFlow::PathNode source, SensitiveAction action
|
||||
) {
|
||||
action = sink.getNode().(Sink).getAction() and
|
||||
// exclude the intermediary sink
|
||||
not sink.getNode() instanceof SensitiveActionGuardComparisonOperand and
|
||||
exists(Configuration cfg |
|
||||
// ordinary taint tracking to a guard
|
||||
cfg.hasFlowPath(source, sink)
|
||||
or
|
||||
// taint tracking to both operands of a guard comparison
|
||||
exists(
|
||||
SensitiveActionGuardComparison cmp, DataFlow::PathNode lSource, DataFlow::PathNode rSource,
|
||||
DataFlow::PathNode lSink, DataFlow::PathNode rSink
|
||||
|
|
||||
sink.getNode() = cmp.getGuard() and
|
||||
cfg.hasFlowPath(lSource, lSink) and
|
||||
lSink.getNode() = DataFlow::valueNode(cmp.getLeftOperand()) and
|
||||
cfg.hasFlowPath(rSource, rSink) and
|
||||
rSink.getNode() = DataFlow::valueNode(cmp.getRightOperand())
|
||||
|
|
||||
source = lSource or
|
||||
source = rSource
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `e` effectively guards access to `action` by returning or throwing early.
|
||||
*
|
||||
* Example: `if (e) return; action(x)`.
|
||||
*/
|
||||
predicate isEarlyAbortGuard(DataFlow::PathNode e, SensitiveAction action) {
|
||||
exists(IfStmt guard |
|
||||
// `e` is in the condition of an if-statement ...
|
||||
e.getNode().(Sink).asExpr().getParentExpr*() = guard.getCondition() and
|
||||
// ... where the then-branch always throws or returns
|
||||
exists(Stmt abort |
|
||||
abort instanceof ThrowStmt or
|
||||
abort instanceof ReturnStmt
|
||||
|
|
||||
abort.nestedIn(guard) and
|
||||
abort.getBasicBlock().(ReachableBasicBlock).postDominates(guard.getThen().getBasicBlock())
|
||||
) and
|
||||
// ... and the else-branch does not exist
|
||||
not exists(guard.getElse())
|
||||
|
|
||||
// ... and `action` is outside the if-statement
|
||||
not action.asExpr().getEnclosingStmt().nestedIn(guard)
|
||||
)
|
||||
}
|
||||
|
||||
import semmle.javascript.heuristics.AdditionalSources
|
||||
|
||||
from DataFlow::PathNode source, DataFlow::PathNode sink, SensitiveAction action
|
||||
where
|
||||
isTaintedGuardForSensitiveAction(sink, source, action) and
|
||||
not isEarlyAbortGuard(sink, action) and
|
||||
source.getNode() instanceof HeuristicSource
|
||||
select sink.getNode(), source, sink, "This condition guards a sensitive $@, but a $@ controls it.",
|
||||
action, "action", source.getNode(), "user-provided value"
|
|
@ -0,0 +1,6 @@
|
|||
<!DOCTYPE qhelp PUBLIC
|
||||
"-//Semmle//qhelp//EN"
|
||||
"qhelp.dtd">
|
||||
<qhelp>
|
||||
<include src="../../../../../../Security/CWE-915/PrototypePollutingAssignment.inc.qhelp" />
|
||||
</qhelp>
|
|
@ -0,0 +1,30 @@
|
|||
/**
|
||||
* @name Prototype-polluting assignment with additional heuristic sources
|
||||
* @description Modifying an object obtained via a user-controlled property name may
|
||||
* lead to accidental mutation of the built-in Object prototype,
|
||||
* and possibly escalate to remote code execution or cross-site scripting.
|
||||
* @kind path-problem
|
||||
* @problem.severity warning
|
||||
* @security-severity 6.1
|
||||
* @precision high
|
||||
* @id js/prototype-polluting-assignment-more-sources
|
||||
* @tags experimental
|
||||
* security
|
||||
* external/cwe/cwe-078
|
||||
* external/cwe/cwe-079
|
||||
* external/cwe/cwe-094
|
||||
* external/cwe/cwe-400
|
||||
* external/cwe/cwe-471
|
||||
* external/cwe/cwe-915
|
||||
*/
|
||||
|
||||
import javascript
|
||||
import semmle.javascript.security.dataflow.PrototypePollutingAssignmentQuery
|
||||
import DataFlow::PathGraph
|
||||
import semmle.javascript.heuristics.AdditionalSources
|
||||
|
||||
from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink
|
||||
where cfg.hasFlowPath(source, sink) and source.getNode() instanceof HeuristicSource
|
||||
select sink, source, sink,
|
||||
"This assignment may alter Object.prototype if a malicious '__proto__' string is injected from $@.",
|
||||
source.getNode(), source.getNode().(Source).describe()
|
Загрузка…
Ссылка в новой задаче