所有早于 1.2.0 版本的 nosurf 都未能对传入请求应用同源检查。
这是因为依赖 Go 标准库 net/http.Request 类型的 .URL.Scheme 字段来首先确保请求通过 HTTPS 服务,然后才应用同源检查。
上述 Scheme 字段在传入请求中不会被 Go HTTP 服务器填充:
// For server requests, the URL is parsed from the URI // supplied on the Request-Line as stored in RequestURI. For // most requests, fields other than Path and RawQuery will be // empty.
因为在一般情况下,Go 无法判断请求是否通过 TLS 进行(由于可能存在 TLS 终止的反向代理等)。
这可能允许攻击者向您的网站发出非安全的跨源请求。
除了实施同源检查外,nosurf 还使用双重提交 Cookie 模式来额外防止 CSRF。
这意味着,要成功发出一个变异的跨源请求,攻击者还需要控制您网站上某个页面的内容,或者您网站子域名的内容。
这可以通过 XSS 实现,或者如果您有意让用户控制网站上的 HTML 内容(例如,您是一个托管提供商 example.com,允许用户在 alice.example.com 上托管他们的网站)。
本仓库中的 PoC 演示了后一种情况下的此类攻击,即攻击者控制了网站主域名下子域名的内容。
需要 Go 和 Caddy。手动运行服务器:
$ go run attacker.go & go run target.go & caddy run
或通过 Process Compose:
$ process-compose
访问 https://attacker.target.localhost。
点击按钮向 https://target.localhost 提交表单,观察请求成功完成。
此问题的修复已发布在 nosurf 1.2.0 中。
感谢 Patrick O'Doherty 报告此问题。