Merge branch 'main' into format

This commit is contained in:
Geoffrey White
2023-01-04 18:00:59 +00:00
84 changed files with 1944 additions and 1113 deletions

View File

@@ -4,6 +4,10 @@ version: 1.22.1
column_kind: "utf16"
extra_env_vars:
DOTNET_GENERATE_ASPNET_CERTIFICATE: "false"
github_api_languages:
- C#
scc_languages:
- C#
file_types:
- name: cs
display_name: C# sources

View File

@@ -1,4 +1,4 @@
all: extractor ql/lib/go.dbscheme install-deps
all: extractor ql/lib/go.dbscheme
ifeq ($(OS),Windows_NT)
EXE = .exe
@@ -36,9 +36,6 @@ autoformat:
check-formatting:
test -z "$$(find . -path '**/vendor' -prune -or -type f -iname '*.go' ! -empty -print0 | xargs -0 grep -L "//\s*autoformat-ignore" | xargs gofmt -l)"
install-deps:
bash scripts/install-deps.sh $(CODEQL_LOCK_MODE)
ifeq ($(QHELP_OUT_DIR),)
# If not otherwise specified, compile qhelp to markdown in place
QHELP_OUT_DIR := ql/src
@@ -75,7 +72,7 @@ tools-win64: $(addsuffix .exe,$(addprefix tools/win64/,$(BINARIES)))
$(addsuffix .exe,$(addprefix tools/win64/,$(BINARIES))):
env GOOS=windows GOARCH=amd64 go build -mod=vendor -o $@ ./extractor/cli/$(basename $(@F))
.PHONY: extractor-common extractor extractor-full install-deps
.PHONY: extractor-common extractor extractor-full
extractor-common: codeql-extractor.yml LICENSE ql/lib/go.dbscheme \
tools/tokenizer.jar $(CODEQL_TOOLS)
rm -rf $(EXTRACTOR_PACK_OUT)

View File

@@ -9,17 +9,6 @@ It contains two major components:
- static analysis libraries and queries written in [CodeQL](https://codeql.github.com/docs/) that can be
used to analyze such a database to find coding mistakes or security vulnerabilities.
## Installation
Clone this repository.
Run `scripts/install-deps.sh`. This will ensure that the necessary external CodeQL packs are
downloaded to your machine. You will need to re-run this script whenever you pull new commits from
the repo.
If you want to use the CodeQL extension for Visual Studio Code, import this repository into your VS
Code workspace.
## Usage
To analyze a Go codebase, either use the [CodeQL command-line

View File

@@ -6,6 +6,10 @@ pull_request_triggers:
- "**/glide.yaml"
- "**/Gopkg.toml"
column_kind: "utf8"
github_api_languages:
- Go
scc_languages:
- Go
file_types:
- name: go
display_name: Go

View File

@@ -0,0 +1,4 @@
---
category: minorAnalysis
---
* The predicate `getNumParameter` on `FuncTypeExpr` has been changed to actually give the number of parameters. It previously gave the number of parameter declarations. `getNumParameterDecl` has been introduced to preserve this functionality.

View File

@@ -194,24 +194,27 @@ class DeclParent extends @declparent, AstNode {
}
/**
* An AST node whose children include fields.
* An AST node whose children include field declarations.
*
* A field declaration can be in a struct, a function (for parameter or result
* variables), or an interface (in which case it is a method or embedding spec).
*/
class FieldParent extends @fieldparent, AstNode {
/**
* Gets the `i`th field of this node.
* Gets the `i`th field declaration of this node.
*
* Note that the precise indices of fields are considered an implementation detail
* and are subject to change without notice.
* Note that the precise indices of field declarations are considered an
* implementation detail and are subject to change without notice.
*/
FieldBase getField(int i) { fields(result, this, i) }
/**
* Gets a child field of this node in the AST.
* Gets a child field declaration of this node in the AST.
*/
FieldBase getAField() { result = this.getField(_) }
/**
* Gets the number of child fields of this node.
* Gets the number of child field declarations of this node.
*/
int getNumFields() { result = count(this.getAField()) }
}

View File

@@ -416,8 +416,35 @@ class AliasSpec extends @aliasspec, TypeSpec { }
class TypeDefSpec extends @typedefspec, TypeSpec { }
/**
* A field declaration, of a struct, a function (in which case this is a parameter or result variable),
* or an interface (in which case this is a method or embedding spec).
* A field declaration, in a struct, a function (for parameter or result
* variables), or an interface (in which case this is a method or embedding
* spec).
*
* Examples:
*
* ```go
* Name string `json:"name"`
* s string
* x, y int
* p *Point
* Close() error
* io.Reader
* ~int | float32
* ```
* as in the following code:
* ```go
* struct {
* io.Reader
* Name string `json:"name"`
* x, y int
* }
* func (p *Point) f(s string) (x, y int) { }
* type MyInterface interface {
* Close() error
* io.Reader
* ~int32 | float32
* }
* ```
*/
class FieldBase extends @field, ExprParent {
/**
@@ -433,6 +460,22 @@ class FieldBase extends @field, ExprParent {
/**
* A field declaration in a struct type.
*
* Examples:
*
* ```go
* Name string `json:"name"`
* x, y int
* ```
*
* as in the following code:
*
* ```go
* struct {
* Name string `json:"name"`
* x, y int
* }
* ```
*/
class FieldDecl extends FieldBase, Documentable, ExprParent {
StructTypeExpr st;
@@ -464,6 +507,20 @@ class FieldDecl extends FieldBase, Documentable, ExprParent {
/**
* An embedded field declaration in a struct.
*
* Examples:
*
* ```go
* io.Reader
* ```
*
* as in the following code:
*
* ```go
* struct {
* io.Reader
* }
* ```
*/
class EmbeddedFieldDecl extends FieldDecl {
EmbeddedFieldDecl() { not exists(this.getNameExpr(_)) }
@@ -473,6 +530,20 @@ class EmbeddedFieldDecl extends FieldDecl {
/**
* A function parameter or result variable declaration.
*
* Examples:
*
* ```go
* s string
* x, y int
* ```
*
* as in the following code:
*
* ```go
* func f(s string, x, y int) { }
* func g() (s string, x, y int){ return }
* ```
*/
class ParameterOrResultDecl extends FieldBase, Documentable, ExprParent {
int rawIndex;
@@ -507,6 +578,19 @@ class ParameterOrResultDecl extends FieldBase, Documentable, ExprParent {
/**
* A parameter declaration.
*
* Examples:
*
* ```go
* s string
* x, y int
* ```
*
* as in the following code:
*
* ```go
* func f(s string, x, y int) { }
* ```
*/
class ParameterDecl extends ParameterOrResultDecl {
ParameterDecl() { rawIndex >= 0 }
@@ -524,6 +608,20 @@ class ParameterDecl extends ParameterOrResultDecl {
/**
* A receiver declaration in a function declaration.
*
* Examples:
*
* ```go
* p *Point
* r io.Reader
* ```
*
* as in the following code:
*
* ```go
* func (p *Point) f() { }
* func (r io.Reader) g() { }
* ```
*/
class ReceiverDecl extends FieldBase, Documentable, ExprParent {
FuncDecl fd;
@@ -547,6 +645,22 @@ class ReceiverDecl extends FieldBase, Documentable, ExprParent {
/**
* A result variable declaration.
*
* Examples:
*
* ```go
* error
* r io.Reader
* x, y int
* ```
*
* as in the following code:
*
* ```go
* func f(error) { return nil }
* func g(r io.Reader) { return nil }
* func h(x, y int) { return }
* ```
*/
class ResultVariableDecl extends ParameterOrResultDecl {
ResultVariableDecl() { rawIndex < 0 }
@@ -564,6 +678,22 @@ class ResultVariableDecl extends ParameterOrResultDecl {
/**
* A type parameter declaration in a type specification.
*
* Examples:
*
* ```go
* S, T comparable
* U any
* K ~int32 | float32
* _ any
* ```
*
* as in the following code:
*
* ```go
* type GenericStruct[S, T comparable, U any, K ~int32 | float32, _ any] struct { }
* func GenericFunction[S, T comparable, U any, K ~int32 | float32, _ any]() {}
* ```
*/
class TypeParamDecl extends @typeparamdecl, Documentable, ExprParent {
TypeParamDecl() { typeparamdecls(this, _, _) }
@@ -615,6 +745,24 @@ class TypeParamDecl extends @typeparamdecl, Documentable, ExprParent {
/**
* A method or embedding specification in an interface type expression.
*
* Examples:
*
* ```go
* Close() error
* io.Reader
* ~int32 | float32
* ```
*
* as in the following code:
*
* ```go
* type MyInterface interface {
* Close() error
* io.Reader
* ~int32 | float32
* }
* ```
*/
class InterfaceMemberSpec extends FieldBase, Documentable, ExprParent {
InterfaceTypeExpr ite;
@@ -636,6 +784,20 @@ class InterfaceMemberSpec extends FieldBase, Documentable, ExprParent {
/**
* A method specification in an interface.
*
* Examples:
*
* ```go
* Close() error
* ```
*
* as in the following code:
*
* ```go
* type MyInterface interface {
* Close() error
* }
* ```
*/
class MethodSpec extends InterfaceMemberSpec {
Expr name;
@@ -654,6 +816,22 @@ class MethodSpec extends InterfaceMemberSpec {
/**
* An embedding specification in an interface.
*
* Examples:
*
* ```go
* io.Reader
* ~int32 | float32
* ```
*
* as in the following code:
*
* ```go
* type MyInterface interface {
* io.Reader
* ~int32 | float32
* }
* ```
*/
class EmbeddingSpec extends InterfaceMemberSpec {
EmbeddingSpec() { not exists(this.getChildExpr(1)) }

View File

@@ -980,18 +980,36 @@ class StructTypeExpr extends @structtypeexpr, TypeExpr, FieldParent {
* Examples:
*
* ```go
* func(a, b int, c float32) (float32, bool)
* func(a int, b, c float32) (float32, bool)
* ```
*/
class FuncTypeExpr extends @functypeexpr, TypeExpr, ScopeNode, FieldParent {
/** Gets the `i`th parameter of this function type (0-based). */
ParameterDecl getParameterDecl(int i) { result = this.getField(i) and i >= 0 }
/** Gets a parameter of this function type. */
/**
* Gets a parameter declaration of this function type.
*
* For example, for `func(a int, b, c float32) (float32, bool)` the result is
* `a int` or `b, c float32`.
*/
ParameterDecl getAParameterDecl() { result = this.getParameterDecl(_) }
/** Gets the number of parameters of this function type. */
int getNumParameter() { result = count(this.getAParameterDecl()) }
/**
* Gets the number of parameter declarations of this function type.
*
* For example, for `func(a int, b, c float32) (float32, bool)` the result is 2:
* `a int` and `b, c float32`.
*/
int getNumParameterDecl() { result = count(this.getAParameterDecl()) }
/**
* Gets the number of parameters of this function type.
*
* For example, for `func(a int, b, c float32) (float32, bool)` the result is 3:
* `a`, `b` and `c`.
*/
int getNumParameter() { result = count(this.getAParameterDecl().getANameExpr()) }
/** Gets the `i`th result of this function type (0-based). */
ResultVariableDecl getResultDecl(int i) { result = this.getField(-(i + 1)) }
@@ -1011,9 +1029,9 @@ class FuncTypeExpr extends @functypeexpr, TypeExpr, ScopeNode, FieldParent {
/** Gets the `i`th child of this node, parameters first followed by results. */
override AstNode getUniquelyNumberedChild(int i) {
if i < this.getNumParameter()
if i < this.getNumParameterDecl()
then result = this.getParameterDecl(i)
else result = this.getResultDecl(i - this.getNumParameter())
else result = this.getResultDecl(i - this.getNumParameterDecl())
}
}

View File

@@ -1,22 +0,0 @@
#!/bin/bash
# Installs any necessary QL pack dependencies from the package registry.
# The optional argument must be a valid value for the `--mode` option to `codeql pack install`
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )"
GO_ROOT=$(dirname "$SCRIPT_DIR")
if [ $# -eq 0 ]; then
LOCK_MODE="use-lock"
elif [ $# -eq 1 ]; then
LOCK_MODE=$1
else
echo "Usage: install-deps.sh [<lock-mode>]"
echo " lock-mode: One of 'use-lock' (default), 'verify', 'update', or 'no-lock'"
exit 1
fi
for d in ql/lib ql/src ql/test ql/examples
do
codeql pack install --mode ${LOCK_MODE} "${GO_ROOT}/${d}"
done

View File

@@ -30,3 +30,96 @@ class Configuration extends TaintTracking::Configuration {
dst.asExpr().(Comparison).hasOperands(src.asExpr(), any(ConstantExpr c))
}
}
/**
* 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)
)
}

View File

@@ -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>

View File

@@ -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>
</qhelp>
<include src="UntrustedDataToExternalAPI.inc.qhelp" />
</qhelp>

View File

@@ -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>

View File

@@ -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>
</qhelp>
<include src="CommandInjection.inc.qhelp" />
</qhelp>

View File

@@ -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>

View File

@@ -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>
</qhelp>
<include src="Xss.inc.qhelp" />
</qhelp>

View File

@@ -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>

View File

@@ -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>
</qhelp>
<include src="SqlInjection.inc.qhelp" />
</qhelp>

View File

@@ -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>

View File

@@ -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>
</qhelp>
<include src="CodeInjection.inc.qhelp" />
</qhelp>

View File

@@ -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>

View File

@@ -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>
</qhelp>
<include src="LogInjection.inc.qhelp" />
</qhelp>

View File

@@ -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>

View File

@@ -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>
</qhelp>
<include src="TaintedFormatString.inc.qhelp" />
</qhelp>

View File

@@ -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>

View File

@@ -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>
</qhelp>
<include src="CorsMisconfigurationForCredentials.inc.qhelp" />
</qhelp>

View File

@@ -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>

View File

@@ -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>
</qhelp>
<include src="RemotePropertyInjection.inc.qhelp" />
</qhelp>

View File

@@ -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>

View File

@@ -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>
</qhelp>
<include src="UnsafeDeserialization.inc.qhelp" />
</qhelp>

View File

@@ -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;amp;</code> or <code>&amp;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>

View File

@@ -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;amp;</code> or <code>&amp;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>
<include src="Xxe.inc.qhelp" />
</qhelp>

View File

@@ -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>

View File

@@ -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>
</qhelp>
<include src="XpathInjection.inc.qhelp" />
</qhelp>

View File

@@ -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>

View File

@@ -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>
</qhelp>
<include src="RegExpInjection.inc.qhelp" />
</qhelp>

View File

@@ -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>

View File

@@ -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>
</qhelp>
<include src="ResourceExhaustion.inc.qhelp" />
</qhelp>

View File

@@ -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;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>

View File

@@ -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;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>
<include src="XmlBomb.inc.qhelp" />
</qhelp>

View File

@@ -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>

View File

@@ -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>
</qhelp>
<include src="ConditionalBypass.inc.qhelp" />
</qhelp>

View File

@@ -15,99 +15,6 @@ 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)
)
}
from DataFlow::PathNode source, DataFlow::PathNode sink, SensitiveAction action
where
isTaintedGuardForSensitiveAction(sink, source, action) and

View File

@@ -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>

View File

@@ -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>
</qhelp>
<include src="PrototypePollutingAssignment.inc.qhelp" />
</qhelp>

View File

@@ -0,0 +1,6 @@
<!DOCTYPE qhelp PUBLIC
"-//Semmle//qhelp//EN"
"qhelp.dtd">
<qhelp>
<include src="../../../../../../Security/CWE-020/UntrustedDataToExternalAPI.inc.qhelp" />
</qhelp>

View File

@@ -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()

View File

@@ -0,0 +1,6 @@
<!DOCTYPE qhelp PUBLIC
"-//Semmle//qhelp//EN"
"qhelp.dtd">
<qhelp>
<include src="../../../../../../Security/CWE-078/CommandInjection.inc.qhelp" />
</qhelp>

View File

@@ -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"

View File

@@ -0,0 +1,6 @@
<!DOCTYPE qhelp PUBLIC
"-//Semmle//qhelp//EN"
"qhelp.dtd">
<qhelp>
<include src="../../../../../../Security/CWE-079/Xss.inc.qhelp" />
</qhelp>

View File

@@ -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"

View File

@@ -0,0 +1,6 @@
<!DOCTYPE qhelp PUBLIC
"-//Semmle//qhelp//EN"
"qhelp.dtd">
<qhelp>
<include src="../../../../../../Security/CWE-089/SqlInjection.inc.qhelp" />
</qhelp>

View File

@@ -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"

View File

@@ -0,0 +1,6 @@
<!DOCTYPE qhelp PUBLIC
"-//Semmle//qhelp//EN"
"qhelp.dtd">
<qhelp>
<include src="../../../../../../Security/CWE-094/CodeInjection.inc.qhelp" />
</qhelp>

View File

@@ -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"

View File

@@ -0,0 +1,6 @@
<!DOCTYPE qhelp PUBLIC
"-//Semmle//qhelp//EN"
"qhelp.dtd">
<qhelp>
<include src="../../../../../../Security/CWE-117/LogInjection.inc.qhelp" />
</qhelp>

View File

@@ -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"

View File

@@ -0,0 +1,6 @@
<!DOCTYPE qhelp PUBLIC
"-//Semmle//qhelp//EN"
"qhelp.dtd">
<qhelp>
<include src="../../../../../../Security/CWE-134/TaintedFormatString.inc.qhelp" />
</qhelp>

View File

@@ -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"

View File

@@ -0,0 +1,6 @@
<!DOCTYPE qhelp PUBLIC
"-//Semmle//qhelp//EN"
"qhelp.dtd">
<qhelp>
<include src="../../../../../../Security/CWE-346/CorsMisconfigurationForCredentials.inc.qhelp" />
</qhelp>

View File

@@ -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"

View File

@@ -0,0 +1,6 @@
<!DOCTYPE qhelp PUBLIC
"-//Semmle//qhelp//EN"
"qhelp.dtd">
<qhelp>
<include src="../../../../../../Security/CWE-400/RemotePropertyInjection.inc.qhelp" />
</qhelp>

View File

@@ -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"

View File

@@ -0,0 +1,6 @@
<!DOCTYPE qhelp PUBLIC
"-//Semmle//qhelp//EN"
"qhelp.dtd">
<qhelp>
<include src="../../../../../../Security/CWE-502/UnsafeDeserialization.inc.qhelp" />
</qhelp>

View File

@@ -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"

View File

@@ -0,0 +1,6 @@
<!DOCTYPE qhelp PUBLIC
"-//Semmle//qhelp//EN"
"qhelp.dtd">
<qhelp>
<include src="../../../../../../Security/CWE-611/Xxe.inc.qhelp" />
</qhelp>

View File

@@ -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"

View File

@@ -0,0 +1,6 @@
<!DOCTYPE qhelp PUBLIC
"-//Semmle//qhelp//EN"
"qhelp.dtd">
<qhelp>
<include src="../../../../../../Security/CWE-643/XpathInjection.inc.qhelp" />
</qhelp>

View File

@@ -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"

View File

@@ -0,0 +1,6 @@
<!DOCTYPE qhelp PUBLIC
"-//Semmle//qhelp//EN"
"qhelp.dtd">
<qhelp>
<include src="../../../../../../Security/CWE-730/RegExpInjection.inc.qhelp" />
</qhelp>

View File

@@ -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"

View File

@@ -0,0 +1,6 @@
<!DOCTYPE qhelp PUBLIC
"-//Semmle//qhelp//EN"
"qhelp.dtd">
<qhelp>
<include src="../../../../../../Security/CWE-770/ResourceExhaustion.inc.qhelp" />
</qhelp>

View File

@@ -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"

View File

@@ -0,0 +1,6 @@
<!DOCTYPE qhelp PUBLIC
"-//Semmle//qhelp//EN"
"qhelp.dtd">
<qhelp>
<include src="../../../../../../Security/CWE-776/XmlBomb.inc.qhelp" />
</qhelp>

View File

@@ -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"

View File

@@ -0,0 +1,6 @@
<!DOCTYPE qhelp PUBLIC
"-//Semmle//qhelp//EN"
"qhelp.dtd">
<qhelp>
<include src="../../../../../../Security/CWE-807/ConditionalBypass.inc.qhelp" />
</qhelp>

View File

@@ -0,0 +1,26 @@
/**
* @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
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"

View File

@@ -0,0 +1,6 @@
<!DOCTYPE qhelp PUBLIC
"-//Semmle//qhelp//EN"
"qhelp.dtd">
<qhelp>
<include src="../../../../../../Security/CWE-915/PrototypePollutingAssignment.inc.qhelp" />
</qhelp>

View File

@@ -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()

View File

@@ -3,6 +3,10 @@ display_name: "QL"
version: 0.0.1
column_kind: "utf8"
legacy_qltest_extraction: true
github_api_languages:
- CodeQL
scc_languages:
- CodeQL
file_types:
- name: ql
display_name: QL query files

View File

@@ -209,6 +209,11 @@ class QueryDoc extends QLDoc {
result = this.getContents().regexpCapture("(?s).*@kind ([\\w-]+)\\s.*", 1)
}
/** Gets the @name for the query */
string getQueryName() {
result = this.getContents().regexpCapture("(?s).*@name ([\\w-\\s]+)(?=\\n).*", 1)
}
/** Gets the id part (without language) of the @id */
string getQueryId() {
result = this.getContents().regexpCapture("(?s).*@id (\\w+)/([\\w\\-]+)\\s.*", 2)

View File

@@ -3,6 +3,10 @@ display_name: "Ruby"
version: 0.1.0
column_kind: "utf8"
legacy_qltest_extraction: true
github_api_languages:
- Ruby
scc_languages:
- Ruby
file_types:
- name: ruby
display_name: Ruby files

View File

@@ -3,6 +3,10 @@ display_name: "Swift"
version: 0.0.1
column_kind: "utf8"
legacy_qltest_extraction: true
github_api_languages:
- Swift
scc_languages:
- Swift
file_types:
- name: swift
display_name: Swift files