Go CSRF / XSRF 令牌的目的、表单保护以及标准包的默认令牌有效期
大家好,我是无能。
我个人制作并个人使用的在线存储
GitHub - haturatu/puremania: No security, very fast, web UI self-hosted online storage
有一个,但是如果想在前端加上认证,所以我尝试制作了一个认证代理。
GitHub - haturatu/auth-proxy: An authentication proxy server and frontend for a website without built-in authentication. JavaScript is supported, but it can also work without JS if using PHP-FPM. The backend is written in Go.
实际上,这几乎都归功于Gemini君...
只代理通过认证的请求。
管理员用户可以为API端点颁发Bearer令牌,并使用该令牌进行请求。但是,在这种情况下,有些API端点也需要从前端会话访问,所以实际上无论是Cookie还是Bearer令牌都可以通过。
如果只保护API端点,将Web登录等前端隔离到私有网络,只公开API端点,那么实际上可以在私有网络中创建用户,并使用该用户颁发API令牌和进行API代理。(请不要说“使用API网关类的开源软件不就行了嘛”)
实际上,这样一来,Cookie和令牌的双重暴力破解就变得实际上可能了,不过嘛...。
因此,接下来是关于表单安全性的问题,为了另一个登录时Web前端的安全。
如果强制加载JS,大部分问题都可以解决,但只依赖JS不是很无聊吗?所以我们决定使用JS以外的方法来提高表单的安全性。
CSRF / XSRF 令牌
这将是本次的焦点,也就是它到底是什么。
简单来说,就是验证服务器端和客户端的请求是否确实是从我这里访问并颁发的,并且如果该令牌在有效期内则允许。
例如
<input type="hidden" name="xsrf_token" value="BeftikzaR8Oe6npnqXYC7WtBhuo:1760376550660">
这样的令牌会嵌入到前端HTML中。这个value由服务器端的密钥签名。因此服务器端知道这是从我的服务器端颁发的!1760376550660只是一个UNIX时间戳的字符串,那么它在当前时间有什么用呢?
xsrftoken package - golang.org/x/net/xsrftoken - Go Packages
func ValidFor(token, key, userID, actionID string, timeout time.Duration) bool
用于上述的期限设置。
实际上,还需要导入time包,如下所示:
if !xsrftoken.ValidFor(clientToken, string(xsrfSecret), sessionID, r.URL.Path, 15*time.Minute) {
如果不提供此参数,默认有效期为24小时,这相当宽松,但我认为这只是作为XSRF Token的本来形式提供,在这种情况下,只需要验证令牌是由服务器颁发的即可。
CSRF和XSRF有什么区别啊!
实际上,似乎没有太大区别。
目的都是为了防止跨站攻击。
对于CSRF
GitHub - gorilla/csrf: Package gorilla/csrf provides Cross Site Request Forgery (CSRF) prevention middleware for Go web applications & services 🔒
我找到了这个库,偶然间看到了这里。
gorilla/csrf CSRF漏洞演示
改进gorilla/csrf实现的一种方法是,将表单中使用的随机值替换为与用户ID关联的加密令牌。这可以防止攻击者将其自身的CSRF令牌和Cookie值替换为目标的值。因为攻击者的CSRF令牌对应的是另一个ID。实际上,这种方法已在库中实现,该库使用x/net/xsrftokenHMAC来验证用户ID、可选的表单操作和有效期。
于是我想到标准库中也有这个,
xsrftoken/xsrf.go
看了源代码,惊讶地发现,即使包含注释也只有100行!稍微有点担心还在使用SHA1,不知道以后会不会升级。
总之,如果标准库如此简单就能达到目的,那么这就足够了;如果要进行SameSite验证,可能就应该使用gorilla/csrf了。
标准库的注意事项
正如前面提到的,默认令牌有效期是24H。
在实际操作中,这个令牌有效期可能会被滥用,所以最好缩短一些。假设这个令牌本身是用于发送直到填写表单的请求,那么24小时的有效期,在没有其他安全措施的情况下,可能会导致同一个令牌被多次使用,通过无限次的curl请求,重复使用同一个令牌向表单发送请求,进行暴力破解并非不可能。