CodeQL 文档

主机名的正则表达式不完整

ID: go/incomplete-hostname-regexp
Kind: path-problem
Security severity: 7.8
Severity: warning
Precision: high
Tags:
   - correctness
   - security
   - external/cwe/cwe-20
Query suites:
   - go-code-scanning.qls
   - go-security-extended.qls
   - go-security-and-quality.qls

点击查看 CodeQL 代码库中的查询

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

如果正则表达式实现了这样的检查,则很容易因未转义正则表达式元字符(如 .)而意外地使检查过于宽松。

即使该检查未用于安全关键型环境中,不完整的检查仍然可能在意外成功时导致不希望的行为。

建议

在构造用于安全检查的正则表达式时,请适当地转义所有元字符,尤其要注意 . 元字符。

示例

以下示例代码检查 URL 重定向是否会到达 example.com 域或其子域之一。

package main

import (
	"errors"
	"net/http"
	"regexp"
)

func checkRedirect(req *http.Request, via []*http.Request) error {
	// BAD: the host of `req.URL` may be controlled by an attacker
	re := "^((www|beta).)?example.com/"
	if matched, _ := regexp.MatchString(re, req.URL.Host); matched {
		return nil
	}
	return errors.New("Invalid redirect")
}

但是,该检查很容易被绕过,因为未转义的 . 允许在 example.com 之前出现任何字符,从而有效地允许重定向到攻击者控制的域,例如 wwwXexample.com

通过适当地转义 . 来解决此漏洞

package main

import (
	"errors"
	"net/http"
	"regexp"
)

func checkRedirectGood(req *http.Request, via []*http.Request) error {
	// GOOD: the host of `req.URL` must be `example.com`, `www.example.com` or `beta.example.com`
	re := "^((www|beta)\\.)?example\\.com/"
	if matched, _ := regexp.MatchString(re, req.URL.Host); matched {
		return nil
	}
	return errors.New("Invalid redirect")
}

您还可以考虑使用原始字符串字面量,以避免必须转义反斜杠

package main

import (
	"errors"
	"net/http"
	"regexp"
)

func checkRedirectGood2(req *http.Request, via []*http.Request) error {
	// GOOD: the host of `req.URL` must be `example.com`, `www.example.com` or `beta.example.com`
	re := `^((www|beta)\.)?example\.com/`
	if matched, _ := regexp.MatchString(re, req.URL.Host); matched {
		return nil
	}
	return errors.New("Invalid redirect")
}

参考

  • ©GitHub 公司
  • 条款
  • 隐私