缺少正则表达式锚点¶
ID: rb/regex/missing-regexp-anchor
Kind: problem
Security severity: 7.8
Severity: warning
Precision: medium
Tags:
- correctness
- security
- external/cwe/cwe-020
Query suites:
- ruby-security-extended.qls
- ruby-security-and-quality.qls
使用正则表达式清理不可信输入是一种常见技术。但是,在没有锚点(例如 \A
或 \z
)的情况下,将不可信输入与正则表达式进行匹配容易出错。恶意输入可以通过在意外位置嵌入允许的模式之一来绕过此类安全检查。
即使匹配不是在安全关键上下文中完成的,当正则表达式意外匹配时,它仍然可能导致不良行为。
建议¶
使用锚点来确保正则表达式在预期位置匹配。
示例¶
以下示例代码检查 URL 重定向是否会到达 example.com
域或其子域之一,而不是某个恶意站点。
class UsersController < ActionController::Base
def index
# BAD: the host of `params[:url]` may be controlled by an attacker
if params[:url].match? /https?:\/\/www\.example\.com\//
redirect_to params[:url]
end
end
end
但是,使用正则表达式匹配进行的检查很容易绕过。例如,可以通过在查询字符串组件中嵌入 http://example.com/
:http://evil-example.net/?x=http://example.com/
。通过在正则表达式中使用锚点来解决这些缺点
class UsersController < ActionController::Base
def index
# GOOD: the host of `params[:url]` can not be controlled by an attacker
if params[:url].match? /\Ahttps?:\/\/www\.example\.com\//
redirect_to params[:url]
end
end
end
一个相关的错误是编写一个具有多个备选方案的正则表达式,但只为其中一个备选方案包含锚点。例如,正则表达式 /^www\.example\.com|beta\.example\.com/
将匹配主机 evil.beta.example.com
,因为正则表达式被解析为 /(^www\.example\.com)|(beta\.example\.com)/
在 Ruby 中,锚点 ^
和 $
匹配行的开头和结尾,而锚点 \A
和 \z
匹配整个字符串的开头和结尾。使用行锚点可能很危险,因为这允许恶意输入使用换行符隐藏,从而导致 HTTP 标头注入等漏洞。除非您特别需要 ^
和 $
的行匹配行为,否则应使用 \A
和 \z
代替。