打开 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
直接将用户输入合并到 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 并检查其主机名之前,会将所有反斜杠替换为正斜杠。
参考¶
OWASP: XSS 未验证的重定向和转发备忘单。
常见弱点枚举:CWE-601。