From 52ca696ff440b4904ce756844d8c0d493e7dad4e Mon Sep 17 00:00:00 2001
From: Esben Sparre Andreasen
+
+ Sanitizing untrusted URLs is an important technique for
+ preventing attacks such as request forgeries and malicious
+ redirections. Usually, this is done by checking that the host of a URL
+ is in a set of allowed hosts.
+
+
+
+ If a regular expression implements such a check, it is
+ easy to accidentally make the check too permissive by not escaping the
+
+
+ Escape all meta-characters appropriately when constructing
+ regular expressions for security checks, pay special attention to the
+
+
+ The following example code checks that a URL redirection
+ will reach the
+
+ The check is however easy to bypass because the unescaped
+ . meta-characters appropriately.
+
+ Even if the check is not used in a security-critical
+ context, the incomplete check may still cause undesirable behaviors
+ when the check succeeds accidentally.
+
+ . meta-character.
+
+ example.com domain, or one of its
+ subdomains.
+
+ . allows for any character before
+ example.com, effectively allowing the redirect to go to
+ an attacker-controlled domain such as wwwXexample.com.
+
+ Address this vulnerability by escaping .
+ appropriately: let regex =/(www|beta|)\.example\.com/.
+
+
+
- If a regular expression implements such a check, it is
- easy to accidentally make the check too permissive by not escaping the
- . meta-characters appropriately.
+ If a regular expression implements such a check, it is
+ easy to accidentally make the check too permissive by not escaping the
+ . meta-characters appropriately.
- Even if the check is not used in a security-critical
- context, the incomplete check may still cause undesirable behaviors
- when the check succeeds accidentally.
+ Even if the check is not used in a security-critical
+ context, the incomplete check may still cause undesirable behaviors
+ when the check succeeds accidentally.
diff --git a/javascript/ql/src/Security/CWE-020/IncompleteUrlRegExp.ql b/javascript/ql/src/Security/CWE-020/IncompleteHostnameRegExp.ql
similarity index 74%
rename from javascript/ql/src/Security/CWE-020/IncompleteUrlRegExp.ql
rename to javascript/ql/src/Security/CWE-020/IncompleteHostnameRegExp.ql
index 262df1e199c..49344ee8fec 100644
--- a/javascript/ql/src/Security/CWE-020/IncompleteUrlRegExp.ql
+++ b/javascript/ql/src/Security/CWE-020/IncompleteHostnameRegExp.ql
@@ -1,10 +1,10 @@
/**
- * @name Incomplete URL regular expression
- * @description Using a regular expression that contains an 'any character' may match more URLs than expected.
+ * @name Incomplete regular expression for hostnames
+ * @description Matching a URL or hostname against a regular expression that contains an unescaped dot as part of the hostname might match more than expected.
* @kind problem
- * @problem.severity error
+ * @problem.severity warning
* @precision high
- * @id js/incomplete-url-regexp
+ * @id js/incomplete-hostname-regexp
* @tags correctness
* security
* external/cwe/cwe-20
@@ -12,13 +12,13 @@
import javascript
-module IncompleteUrlRegExpTracking {
+module IncompleteHostnameRegExpTracking {
/**
- * A taint tracking configuration for incomplete URL regular expressions sources.
+ * A taint tracking configuration for incomplete hostname regular expressions sources.
*/
class Configuration extends TaintTracking::Configuration {
- Configuration() { this = "IncompleteUrlRegExpTracking" }
+ Configuration() { this = "IncompleteHostnameRegExpTracking" }
override
predicate isSource(DataFlow::Node source) {
@@ -53,7 +53,7 @@ from Expr e, string pattern, string hostPart
where
(
e.(RegExpLiteral).getValue() = pattern or
- exists (IncompleteUrlRegExpTracking::Configuration cfg |
+ exists (IncompleteHostnameRegExpTracking::Configuration cfg |
cfg.hasFlow(e.flow(), _) and
e.mayHaveStringValue(pattern)
)
diff --git a/javascript/ql/src/Security/CWE-020/examples/IncompleteUrlRegExp.js b/javascript/ql/src/Security/CWE-020/examples/IncompleteHostnameRegExp.js
similarity index 100%
rename from javascript/ql/src/Security/CWE-020/examples/IncompleteUrlRegExp.js
rename to javascript/ql/src/Security/CWE-020/examples/IncompleteHostnameRegExp.js
diff --git a/javascript/ql/test/query-tests/Security/CWE-020/IncompleteHostnameRegExp.expected b/javascript/ql/test/query-tests/Security/CWE-020/IncompleteHostnameRegExp.expected
new file mode 100644
index 00000000000..cbb655c77ba
--- /dev/null
+++ b/javascript/ql/test/query-tests/Security/CWE-020/IncompleteHostnameRegExp.expected
@@ -0,0 +1,21 @@
+| tst-IncompleteHostnameRegExp.js:3:2:3:28 | /http:\\ ... le.com/ | This regular expression has an unescaped '.' before 'example.com', so it might match more hosts than expected. |
+| tst-IncompleteHostnameRegExp.js:5:2:5:28 | /http:\\ ... le.net/ | This regular expression has an unescaped '.' before 'example.net', so it might match more hosts than expected. |
+| tst-IncompleteHostnameRegExp.js:6:2:6:42 | /http:\\ ... b).com/ | This regular expression has an unescaped '.' before '(example-a\|example-b).com', so it might match more hosts than expected. |
+| tst-IncompleteHostnameRegExp.js:11:13:11:37 | "http:/ ... le.com" | This regular expression has an unescaped '.' before 'example.com', so it might match more hosts than expected. |
+| tst-IncompleteHostnameRegExp.js:12:10:12:34 | "http:/ ... le.com" | This regular expression has an unescaped '.' before 'example.com', so it might match more hosts than expected. |
+| tst-IncompleteHostnameRegExp.js:15:22:15:46 | "http:/ ... le.com" | This regular expression has an unescaped '.' before 'example.com', so it might match more hosts than expected. |
+| tst-IncompleteHostnameRegExp.js:17:13:17:31 | `test.example.com$` | This regular expression has an unescaped '.' before 'example.com', so it might match more hosts than expected. |
+| tst-IncompleteHostnameRegExp.js:17:14:17:30 | test.example.com$ | This regular expression has an unescaped '.' before 'example.com', so it might match more hosts than expected. |
+| tst-IncompleteHostnameRegExp.js:19:17:19:34 | 'test.example.com' | This regular expression has an unescaped '.' before 'example.com', so it might match more hosts than expected. |
+| tst-IncompleteHostnameRegExp.js:22:27:22:44 | 'test.example.com' | This regular expression has an unescaped '.' before 'example.com', so it might match more hosts than expected. |
+| tst-IncompleteHostnameRegExp.js:28:22:28:39 | 'test.example.com' | This regular expression has an unescaped '.' before 'example.com', so it might match more hosts than expected. |
+| tst-IncompleteHostnameRegExp.js:37:2:37:54 | /^(http ... =$\|\\/)/ | This regular expression has an unescaped '.' before ')?example.com', so it might match more hosts than expected. |
+| tst-IncompleteHostnameRegExp.js:38:2:38:44 | /^(http ... p\\/f\\// | This regular expression has an unescaped '.' before 'example.com', so it might match more hosts than expected. |
+| tst-IncompleteHostnameRegExp.js:39:2:39:34 | /\\(http ... m\\/\\)/g | This regular expression has an unescaped '.' before 'example.com', so it might match more hosts than expected. |
+| tst-IncompleteHostnameRegExp.js:40:2:40:29 | /https? ... le.com/ | This regular expression has an unescaped '.' before 'example.com', so it might match more hosts than expected. |
+| tst-IncompleteHostnameRegExp.js:41:13:41:68 | '^http: ... e\\.com' | This regular expression has an unescaped '.' before 'example.com', so it might match more hosts than expected. |
+| tst-IncompleteHostnameRegExp.js:41:41:41:68 | '^https ... e\\.com' | This regular expression has an unescaped '.' before 'example.com', so it might match more hosts than expected. |
+| tst-IncompleteHostnameRegExp.js:42:13:42:61 | 'http[s ... \\/(.+)' | This regular expression has an unescaped '.' before 'example.com', so it might match more hosts than expected. |
+| tst-IncompleteHostnameRegExp.js:43:2:43:33 | /^https ... e.com$/ | This regular expression has an unescaped '.' before 'example.com', so it might match more hosts than expected. |
+| tst-IncompleteHostnameRegExp.js:44:9:44:100 | 'protos ... ernal)' | This regular expression has an unescaped '.' before 'example-b.com', so it might match more hosts than expected. |
+| tst-IncompleteHostnameRegExp.js:46:2:46:26 | /exampl ... le.com/ | This regular expression has an unescaped '.' before 'dev\|example.com', so it might match more hosts than expected. |
diff --git a/javascript/ql/test/query-tests/Security/CWE-020/IncompleteHostnameRegExp.qlref b/javascript/ql/test/query-tests/Security/CWE-020/IncompleteHostnameRegExp.qlref
new file mode 100644
index 00000000000..e818d947252
--- /dev/null
+++ b/javascript/ql/test/query-tests/Security/CWE-020/IncompleteHostnameRegExp.qlref
@@ -0,0 +1 @@
+Security/CWE-020/IncompleteHostnameRegExp.ql
\ No newline at end of file
diff --git a/javascript/ql/test/query-tests/Security/CWE-020/IncompleteUrlRegExp.expected b/javascript/ql/test/query-tests/Security/CWE-020/IncompleteUrlRegExp.expected
deleted file mode 100644
index 685baad4165..00000000000
--- a/javascript/ql/test/query-tests/Security/CWE-020/IncompleteUrlRegExp.expected
+++ /dev/null
@@ -1,21 +0,0 @@
-| tst-IncompleteUrlRegExp.js:3:2:3:28 | /http:\\ ... le.com/ | This regular expression has an unescaped '.' before 'example.com', so it might match more hosts than expected. |
-| tst-IncompleteUrlRegExp.js:5:2:5:28 | /http:\\ ... le.net/ | This regular expression has an unescaped '.' before 'example.net', so it might match more hosts than expected. |
-| tst-IncompleteUrlRegExp.js:6:2:6:42 | /http:\\ ... b).com/ | This regular expression has an unescaped '.' before '(example-a\|example-b).com', so it might match more hosts than expected. |
-| tst-IncompleteUrlRegExp.js:11:13:11:37 | "http:/ ... le.com" | This regular expression has an unescaped '.' before 'example.com', so it might match more hosts than expected. |
-| tst-IncompleteUrlRegExp.js:12:10:12:34 | "http:/ ... le.com" | This regular expression has an unescaped '.' before 'example.com', so it might match more hosts than expected. |
-| tst-IncompleteUrlRegExp.js:15:22:15:46 | "http:/ ... le.com" | This regular expression has an unescaped '.' before 'example.com', so it might match more hosts than expected. |
-| tst-IncompleteUrlRegExp.js:17:13:17:31 | `test.example.com$` | This regular expression has an unescaped '.' before 'example.com', so it might match more hosts than expected. |
-| tst-IncompleteUrlRegExp.js:17:14:17:30 | test.example.com$ | This regular expression has an unescaped '.' before 'example.com', so it might match more hosts than expected. |
-| tst-IncompleteUrlRegExp.js:19:17:19:34 | 'test.example.com' | This regular expression has an unescaped '.' before 'example.com', so it might match more hosts than expected. |
-| tst-IncompleteUrlRegExp.js:22:27:22:44 | 'test.example.com' | This regular expression has an unescaped '.' before 'example.com', so it might match more hosts than expected. |
-| tst-IncompleteUrlRegExp.js:28:22:28:39 | 'test.example.com' | This regular expression has an unescaped '.' before 'example.com', so it might match more hosts than expected. |
-| tst-IncompleteUrlRegExp.js:37:2:37:54 | /^(http ... =$\|\\/)/ | This regular expression has an unescaped '.' before ')?example.com', so it might match more hosts than expected. |
-| tst-IncompleteUrlRegExp.js:38:2:38:44 | /^(http ... p\\/f\\// | This regular expression has an unescaped '.' before 'example.com', so it might match more hosts than expected. |
-| tst-IncompleteUrlRegExp.js:39:2:39:34 | /\\(http ... m\\/\\)/g | This regular expression has an unescaped '.' before 'example.com', so it might match more hosts than expected. |
-| tst-IncompleteUrlRegExp.js:40:2:40:29 | /https? ... le.com/ | This regular expression has an unescaped '.' before 'example.com', so it might match more hosts than expected. |
-| tst-IncompleteUrlRegExp.js:41:13:41:68 | '^http: ... e\\.com' | This regular expression has an unescaped '.' before 'example.com', so it might match more hosts than expected. |
-| tst-IncompleteUrlRegExp.js:41:41:41:68 | '^https ... e\\.com' | This regular expression has an unescaped '.' before 'example.com', so it might match more hosts than expected. |
-| tst-IncompleteUrlRegExp.js:42:13:42:61 | 'http[s ... \\/(.+)' | This regular expression has an unescaped '.' before 'example.com', so it might match more hosts than expected. |
-| tst-IncompleteUrlRegExp.js:43:2:43:33 | /^https ... e.com$/ | This regular expression has an unescaped '.' before 'example.com', so it might match more hosts than expected. |
-| tst-IncompleteUrlRegExp.js:44:9:44:100 | 'protos ... ernal)' | This regular expression has an unescaped '.' before 'example-b.com', so it might match more hosts than expected. |
-| tst-IncompleteUrlRegExp.js:46:2:46:26 | /exampl ... le.com/ | This regular expression has an unescaped '.' before 'dev\|example.com', so it might match more hosts than expected. |
diff --git a/javascript/ql/test/query-tests/Security/CWE-020/IncompleteUrlRegExp.qlref b/javascript/ql/test/query-tests/Security/CWE-020/IncompleteUrlRegExp.qlref
deleted file mode 100644
index 8a9d0df5efb..00000000000
--- a/javascript/ql/test/query-tests/Security/CWE-020/IncompleteUrlRegExp.qlref
+++ /dev/null
@@ -1 +0,0 @@
-Security/CWE-020/IncompleteUrlRegExp.ql
\ No newline at end of file
diff --git a/javascript/ql/test/query-tests/Security/CWE-020/tst-IncompleteUrlRegExp.js b/javascript/ql/test/query-tests/Security/CWE-020/tst-IncompleteHostnameRegExp.js
similarity index 100%
rename from javascript/ql/test/query-tests/Security/CWE-020/tst-IncompleteUrlRegExp.js
rename to javascript/ql/test/query-tests/Security/CWE-020/tst-IncompleteHostnameRegExp.js
From 09e7124bb1a57cbe3058931fe69bad7a06c5d938 Mon Sep 17 00:00:00 2001
From: Esben Sparre Andreasen
wwwXexample.com.
Address this vulnerability by escaping .
- appropriately: let regex =/(www|beta|)\.example\.com/.
+ appropriately: let regex = /(www|beta|)\.example\.com/.
diff --git a/javascript/ql/src/Security/CWE-020/IncompleteHostnameRegExp.ql b/javascript/ql/src/Security/CWE-020/IncompleteHostnameRegExp.ql
index 49344ee8fec..abe6d76d6f0 100644
--- a/javascript/ql/src/Security/CWE-020/IncompleteHostnameRegExp.ql
+++ b/javascript/ql/src/Security/CWE-020/IncompleteHostnameRegExp.ql
@@ -12,28 +12,25 @@
import javascript
-module IncompleteHostnameRegExpTracking {
+/**
+ * A taint tracking configuration for incomplete hostname regular expressions sources.
+ */
+class Configuration extends TaintTracking::Configuration {
+ Configuration() { this = "IncompleteHostnameRegExpTracking" }
- /**
- * A taint tracking configuration for incomplete hostname regular expressions sources.
- */
- class Configuration extends TaintTracking::Configuration {
- Configuration() { this = "IncompleteHostnameRegExpTracking" }
-
- override
- predicate isSource(DataFlow::Node source) {
- isIncompleteHostNameRegExpPattern(source.asExpr().getStringValue(), _)
- }
-
- override
- predicate isSink(DataFlow::Node sink) {
- isInterpretedAsRegExp(sink)
- }
+ override
+ predicate isSource(DataFlow::Node source) {
+ isIncompleteHostNameRegExpPattern(source.asExpr().getStringValue(), _)
+ }
+ override
+ predicate isSink(DataFlow::Node sink) {
+ isInterpretedAsRegExp(sink)
}
}
+
/**
* Holds if `pattern` is a regular expression pattern for URLs with a host matched by `hostPart`,
* and `pattern` contains a subtle mistake that allows it to match unexpected hosts.
@@ -45,7 +42,7 @@ predicate isIncompleteHostNameRegExpPattern(string pattern, string hostPart) {
// an unescaped single `.`
"(?>
+ result = "com|org|edu|gov|uk|net|io"
+ }
+}
\ No newline at end of file
From bb3e3a541d69a6f01abb1cea906a67270abb05ce Mon Sep 17 00:00:00 2001
From: Esben Sparre Andreasen example.com, effectively allowing the redirect to go to
an attacker-controlled domain such as wwwXexample.com.
+ +
+ Address this vulnerability by escaping.
appropriately: let regex = /(www|beta|)\.example\.com/.
diff --git a/javascript/ql/src/Security/CWE-020/IncompleteHostnameRegExp.ql b/javascript/ql/src/Security/CWE-020/IncompleteHostnameRegExp.ql
index abe6d76d6f0..01335fbbe0a 100644
--- a/javascript/ql/src/Security/CWE-020/IncompleteHostnameRegExp.ql
+++ b/javascript/ql/src/Security/CWE-020/IncompleteHostnameRegExp.ql
@@ -1,6 +1,6 @@
/**
* @name Incomplete regular expression for hostnames
- * @description Matching a URL or hostname against a regular expression that contains an unescaped dot as part of the hostname might match more than expected.
+ * @description Matching a URL or hostname against a regular expression that contains an unescaped dot as part of the hostname might match more hostnames than expected.
* @kind problem
* @problem.severity warning
* @precision high
From 23a2bf17566a9adb9f338547374939bd1c275e51 Mon Sep 17 00:00:00 2001
From: Jonas Jensen example.com, effectively allowing the redirect to go to
an attacker-controlled domain such as wwwXexample.com.
- +
Address this vulnerability by escaping .
appropriately: let regex = /(www|beta|)\.example\.com/.