CodeQL 文档

服务器端请求伪造

ID: rb/request-forgery
Kind: path-problem
Security severity: 9.1
Severity: error
Precision: high
Tags:
   - security
   - external/cwe/cwe-918
Query suites:
   - ruby-code-scanning.qls
   - ruby-security-extended.qls
   - ruby-security-and-quality.qls

点击查看 CodeQL 仓库中的查询

直接将用户输入合并到 HTTP 请求中而不对其进行验证,可能会导致服务器端请求伪造 (SSRF) 攻击。在这些攻击中,请求可能会被更改、指向不同的服务器或通过不同的协议发送。这可能允许攻击者获取敏感信息或执行具有提升权限的操作。

建议

为了防范 SSRF 攻击,您应该避免将用户提供的输入直接放入请求 URL 中。相反,应在服务器上维护一个已授权 URL 列表;然后根据提供的输入从该列表中进行选择。或者,确保从用户输入构建的请求仅限于特定主机或更严格的 URL 前缀。

示例

以下示例显示了一个 HTTP 请求参数被直接用于形成一个新的请求而没有验证输入,这会导致 SSRF 攻击。它还显示了如何通过将用户输入与已知固定字符串进行验证来解决此问题。

require "excon"
require "json"

class PostsController < ActionController::Base
  def create
    user = params[:user_id]

    # BAD - user can control the entire URL of the request
    users_service_domain = params[:users_service_domain]
    response = Excon.post("#{users_service_domain}/logins", body: {user_id: user}).body
    token = JSON.parse(response)["token"]

    # GOOD - path is validated against a known fixed string
    path = if params[:users_service_path] == "v1/users"
             "v1/users"
           else 
             "v2/users"
           end
    response = Excon.post("users-service/#{path}", body: {user_id: user}).body
    token = JSON.parse(response)["token"]

    @post = Post.create(params[:post].merge(user_token: token))
    render @post
  end
end

参考

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