Skip to content

Commit 9e8930c

Browse files
committed
Ruby: IncompleteHostnameRegExp.ql
1 parent 832c9c4 commit 9e8930c

File tree

12 files changed

+150
-127
lines changed

12 files changed

+150
-127
lines changed

javascript/ql/src/Security/CWE-020/IncompleteHostnameRegExp.qhelp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@
3030
<p>
3131

3232
Escape all meta-characters appropriately when constructing
33-
regular expressions for security checks, pay special attention to the
33+
regular expressions for security checks, and pay special attention to the
3434
<code>.</code> meta-character.
3535

3636
</p>

python/ql/src/Security/CWE-020/IncompleteHostnameRegExp.qhelp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@
3030
<p>
3131

3232
Escape all meta-characters appropriately when constructing
33-
regular expressions for security checks, pay special attention to the
33+
regular expressions for security checks, and pay special attention to the
3434
<code>.</code> meta-character.
3535

3636
</p>

ruby/ql/lib/codeql/ruby/security/performance/RegExpTreeView.qll

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -637,6 +637,9 @@ class RegExpGroup extends RegExpTerm, TRegExpGroup {
637637
*/
638638
int getNumber() { result = re.getGroupNumber(start, end) }
639639

640+
/** Holds if this is a capture group. */
641+
predicate isCapture() { not exists(this.getNumber()) }
642+
640643
/** Holds if this is a named capture group. */
641644
predicate isNamed() { exists(this.getName()) }
642645

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
---
2+
category: newQuery
3+
---
4+
* Added a new query, `rb/incomplete-hostname-regexp`. The query finds instances where a hostname is incompletely sanitized due to an unescaped character in a regular expression.

ruby/ql/src/queries/security/cwe-020/HostnameRegexpShared.qll

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@
33
* that match URLs and hostname patterns.
44
*/
55

6-
import javascript
6+
private import codeql.ruby.security.performance.RegExpTreeView
7+
private import codeql.ruby.DataFlow
78

89
/**
910
* Holds if the given constant is unlikely to occur in the origin part of a URL.
@@ -19,7 +20,7 @@ predicate isConstantInvalidInsideOrigin(RegExpConstant term) {
1920

2021
/** Holds if `term` is a dot constant of form `\.` or `[.]`. */
2122
predicate isDotConstant(RegExpTerm term) {
22-
term.(RegExpCharEscape).getValue() = "."
23+
term.(RegExpEscape).getValue() = "."
2324
or
2425
exists(RegExpCharacterClass cls |
2526
term = cls and

ruby/ql/src/queries/security/cwe-020/IncompleteHostnameRegExp.qhelp

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@
3030
<p>
3131

3232
Escape all meta-characters appropriately when constructing
33-
regular expressions for security checks, pay special attention to the
33+
regular expressions for security checks, and pay special attention to the
3434
<code>.</code> meta-character.
3535

3636
</p>
@@ -46,7 +46,7 @@
4646

4747
</p>
4848

49-
<sample src="examples/IncompleteHostnameRegExp.js"/>
49+
<sample src="examples/IncompleteHostnameRegExp.rb"/>
5050

5151
<p>
5252

@@ -59,14 +59,13 @@
5959
<p>
6060

6161
Address this vulnerability by escaping <code>.</code>
62-
appropriately: <code>let regex = /((www|beta)\.)?example\.com/</code>.
62+
appropriately: <code>regex = /((www|beta)\.)?example\.com/</code>.
6363

6464
</p>
6565

6666
</example>
6767

6868
<references>
69-
<li>MDN: <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions">Regular Expressions</a></li>
7069
<li>OWASP: <a href="https://www.owasp.org/index.php/Server_Side_Request_Forgery">SSRF</a></li>
7170
<li>OWASP: <a href="https://cheatsheetseries.owasp.org/cheatsheets/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html">XSS Unvalidated Redirects and Forwards Cheat Sheet</a>.</li>
7271
</references>

ruby/ql/src/queries/security/cwe-020/IncompleteHostnameRegExp.ql

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,16 @@
55
* @problem.severity warning
66
* @security-severity 7.8
77
* @precision high
8-
* @id js/incomplete-hostname-regexp
8+
* @id rb/incomplete-hostname-regexp
99
* @tags correctness
1010
* security
1111
* external/cwe/cwe-020
1212
*/
1313

14-
import javascript
15-
import semmle.javascript.CharacterEscapes
1614
import HostnameRegexpShared
15+
import codeql.ruby.security.performance.RegExpTreeView
16+
import codeql.ruby.DataFlow
17+
import codeql.ruby.AST as AST
1718

1819
/**
1920
* Holds if `term` occurs inside a quantifier or alternative (and thus
@@ -102,6 +103,5 @@ where
102103
) else (
103104
kind = "regular expression" and aux = re
104105
)
105-
) and
106-
not CharacterEscapes::hasALikelyRegExpPatternMistake(re)
106+
)
107107
select hostSequence, "This " + kind + " " + msg, aux, "here"
Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,13 @@
1-
app.get('/some/path', function(req, res) {
2-
let url = req.param('url'),
3-
host = urlLib.parse(url).host;
4-
// BAD: the host of `url` may be controlled by an attacker
5-
let regex = /^((www|beta).)?example.com/;
6-
if (host.match(regex)) {
7-
res.redirect(url);
8-
}
9-
});
1+
class AppController < ApplicationController
2+
3+
def index
4+
url = params[:url]
5+
host = URI(url).host
6+
# BAD: the host of `url` may be controlled by an attacker
7+
regex = /^((www|beta).)?example.com/
8+
if host.match(regex)
9+
redirect_to url
10+
end
11+
end
12+
13+
end

ruby/ql/test/query-tests/security/cwe-020/IncompleteHostnameRegExp/IncompleteHostnameRegExp.expected

Lines changed: 32 additions & 26 deletions
Large diffs are not rendered by default.
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
Security/CWE-020/IncompleteHostnameRegExp.ql
1+
queries/security/cwe-020/IncompleteHostnameRegExp.ql

0 commit comments

Comments
 (0)