CodeQL 文档

从远程源重定向 URL

ID: rb/url-redirection
Kind: path-problem
Security severity: 6.1
Severity: error
Precision: high
Tags:
   - security
   - external/cwe/cwe-601
Query suites:
   - ruby-code-scanning.qls
   - ruby-security-extended.qls
   - ruby-security-and-quality.qls

单击以查看 CodeQL 代码库中的查询

在未验证输入的情况下直接将用户输入合并到 URL 重定向请求中,可能会导致钓鱼攻击。在这些攻击中,毫无戒心的用户可能会被重定向到一个恶意网站,该网站看起来与他们打算访问的真实网站非常相似,但实际上由攻击者控制。

建议

为了防止不受信任的 URL 重定向,建议不要将用户输入直接放到重定向 URL 中。相反,在服务器上维护一个授权重定向列表;然后根据提供的用户输入从该列表中选择。

如果不可能,则应通过其他方式验证用户输入,例如,通过验证目标 URL 是否与当前页面位于同一主机上。

示例

以下示例显示了一个 HTTP 请求参数直接用于 URL 重定向,而没有验证输入,这会导致钓鱼攻击

class HelloController < ActionController::Base
  def hello
    redirect_to params[:url]
  end
end

解决此问题的一种方法是在执行重定向之前,根据一组已知的固定字符串验证用户输入

class HelloController < ActionController::Base
  VALID_REDIRECTS = [
    "http://cwe.mitre.org/data/definitions/601.html",
    "http://cwe.mitre.org/data/definitions/79.html"
  ].freeze

  def hello
    # GOOD: the request parameter is validated against a known list of URLs
    target_url = params[:url]
    if VALID_REDIRECTS.include?(target_url)
      redirect_to target_url
    else
      redirect_to "/error.html"
    end
  end
end

或者,我们可以通过检查 URL 是相对的还是在已知的良好主机上,来检查目标 URL 是否不会重定向到不同的主机

require 'uri'

class HelloController < ActionController::Base
  KNOWN_HOST = "example.org"

  def hello
    begin
      target_url = URI.parse(params[:url])

      # Redirect if the URL is either relative or on a known good host
      if !target_url.host || target_url.host == KNOWN_HOST
        redirect_to target_url.to_s
      else
        redirect_to "/error.html" # Redirect to error page if the host is not known
      end
    rescue URI::InvalidURIError
      # Handle the exception, for example, by redirecting to a safe page
      redirect_to "/error.html"
    end
  end
end

请注意,如上所述,上面的代码将允许重定向到 example.com 上的 URL,这虽然无害,但可能并非预期。您可以将自己的域(如果已知)替换为 example.com 来防止这种情况。

参考资料

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