CodeQL 文档

打开 URL 重定向

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

点击查看 CodeQL 存储库中的查询

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

建议

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

如果无法做到这一点,则应以其他方式验证用户输入,例如,通过验证目标 URL 是否为本地 URL 并且不会重定向到其他主机。

示例

以下示例显示了如何在不验证输入的情况下直接在 URL 重定向中使用 HTTP 请求参数,这会导致网络钓鱼攻击

package main

import (
	"net/http"
)

func serve() {
	http.HandleFunc("/redir", func(w http.ResponseWriter, r *http.Request) {
		r.ParseForm()
		http.Redirect(w, r, r.Form.Get("target"), 302)
	})
}

解决此问题的一种方法是解析目标 URL 并检查其主机名是否为空,这意味着它是一个相对 URL

package main

import (
	"net/http"
	"net/url"
	"strings"
)

func serve1() {
	http.HandleFunc("/redir", func(w http.ResponseWriter, r *http.Request) {
		r.ParseForm()
		targetUrl := r.Form.Get("target")
		// replace all backslashes with forward slashes before parsing the URL
		targetUrl = strings.ReplaceAll(targetUrl, "\\", "/")

		target, err := url.Parse(targetUrl)
		if err != nil {
			// ...
		}

		if target.Hostname() == "" {
			// GOOD: check that it is a local redirect
			http.Redirect(w, r, target.String(), 302)
		} else {
			w.WriteHeader(400)
		}
	})
}

请注意,某些浏览器将 URL 中的反斜杠视为正斜杠。为了解决这个问题,我们在解析 URL 并检查其主机名之前,会将所有反斜杠替换为正斜杠。

参考

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