CodeQL 文档

不完整的 URL 子字符串清理

ID: rb/incomplete-url-substring-sanitization
Kind: problem
Security severity: 7.8
Severity: warning
Precision: high
Tags:
   - correctness
   - security
   - external/cwe/cwe-020
Query suites:
   - ruby-code-scanning.qls
   - ruby-security-extended.qls
   - ruby-security-and-quality.qls

点击查看 CodeQL 仓库中的查询

清理不可信的 URL 是防止攻击(如请求伪造和恶意重定向)的重要技术。通常,这是通过检查 URL 的主机是否在一组允许的主机中来完成的。

但是,将 URL 视为字符串并检查允许的主机之一是否为 URL 的子字符串,这很容易出错。恶意 URL 可以通过将允许的主机之一嵌入到意外位置来绕过此类安全检查。

即使子字符串检查没有在安全关键上下文中使用,当检查意外成功时,不完整的检查仍然可能导致不良行为。

建议

在执行主机值检查之前解析 URL,并确保检查能够正确处理任意子域序列。

示例

以下示例代码检查 URL 重定向是否将到达 example.com 域或其子域之一,而不是某个恶意站点。

class AppController < ApplicationController
    def index
        url = params[:url]
        # BAD: the host of `url` may be controlled by an attacker
        if url.include?("example.com")
            redirect_to url
        end
    end
end

然而,子字符串检查很容易被绕过。例如,可以通过将 example.com 嵌入到路径组件中:http://evil-example.net/example.com,或者在查询字符串组件中:http://evil-example.net/?x=example.com。通过检查解析的 URL 的主机来解决这些缺点

class AppController < ApplicationController
    def index
        url = params[:url]
        host = URI(url).host
        # BAD: the host of `url` may be controlled by an attacker
        if host.include?("example.com")
            redirect_to url
        end
    end
end

这仍然不是一个充分的检查,因为以下 URL 会绕过它:http://evil-example.com http://example.com.evil-example.net。相反,请使用允许主机的明确白名单来确保重定向安全

class AppController < ApplicationController
    def index
        url = params[:url]
        host = URI(url).host
        # GOOD: the host of `url` can not be controlled by an attacker
        allowedHosts = [
            'example.com',
            'beta.example.com',
            'www.example.com'
        ]
        if allowedHosts.include?(host)
            redirect_to url
        end
    end
end

参考资料

  • ©GitHub, Inc.
  • 条款
  • 隐私