Spring Security 6 的 CSRF 令牌比较失败

问题描述 投票:0回答:2

我正在编写一个带有 Svelte 前端和 Spring Boot 3 后端(版本“3.0.6”)的应用程序。

我阅读了有关针对 BREACH 攻击的新保护措施,并应用了 Spring Security 的新配置

在我的前端,在发送任何 POST 请求之前,我读取

XSRF-TOKEN
cookie 的值,并将该值复制到标头
X-XSRF-TOKEN

通过调试代码,我可以看到

CsrfFilter
能够从标头中提取令牌值。

不幸的是,接收两个相同字符串作为输入的方法

XorCsrfTokenRequestAttributeHandler::getTokenValue
返回
null
。鉴于输入完全由我的客户端发送的内容定义,我想我必须先转换
XSRF-TOKEN
值,然后再将其复制到标头
X-XSRF-TOKEN

方法代码为:

// example call: actualToken = token = "b4b40051-9f64-4d8e-9092-cc84cc769ae0"
private static String getTokenValue(String actualToken, String token) {
    byte[] actualBytes;
    try {
        actualBytes = Base64.getUrlDecoder().decode(actualToken);
    }
    catch (Exception ex) {
        return null;
    }

    byte[] tokenBytes = Utf8.encode(token);
    int tokenSize = tokenBytes.length;
    if (actualBytes.length < tokenSize) {
        // 24 < 36 so we arrive here
        return null;
    }

    // extract token and random bytes
    int randomBytesSize = actualBytes.length - tokenSize;
    byte[] xoredCsrf = new byte[tokenSize];
    byte[] randomBytes = new byte[randomBytesSize];

    System.arraycopy(actualBytes, 0, randomBytes, 0, randomBytesSize);
    System.arraycopy(actualBytes, randomBytesSize, xoredCsrf, 0, tokenSize);

    byte[] csrfBytes = xorCsrf(randomBytes, xoredCsrf);
    return Utf8.decode(csrfBytes);
}

当一切顺利时,该方法应该返回与“token”相同的值,并且调用

equalsConstantTime(csrfToken.getToken(), actualToken)
返回
true
,其中
actualToken
是上述方法的返回值。

那么,在将 cookie 的值

XSRF-TOKEN
复制到标头
X-XSRF-TOKEN
之前,我应该对它做什么?

javascript spring spring-security
2个回答
1
投票

我在这里找到了解决方案:

https://docs.spring.io/spring-security/reference/5.8/migration/servlet/exploits.html#_i_am_using_a_single_page_application_with_httpsessioncsrftokenrepository

基本上,JavaScript 客户端根本不需要与 cookie 进行交互。相反,服务器可以定义端点

@GetMapping("/csrf")
public CsrfToken csrfToken(CsrfToken csrfToken) {
    return csrfToken;
}

例如返回:

{
    "parameterName":"_csrf",
    "token":"pKpetTa2tv6yhmnko7ZvtaiP7CgX8cB5uBbR1G-ZR6NiKTpIkcltgALX0J-fslyGkJtbgpG_wRFxl_VUgCDm513_dMVUGQ15",
    "headerName":"X-XSRF-TOKEN"
}

连同 cookie 中相应的原始令牌,浏览器将自动转发。


0
投票

我无权添加评论。因此我被迫在这里发布我的问题。

我在 Spring 中使用 CookieCsrfTokenRepository 并返回带有令牌的 cookie。我使用 JS 从 cookie 中检索令牌并将其发送到 Ajax POST 请求的标头中,如下所示。 标头:{ 'X-XSRF-TOKEN': csrfToken }

我遇到了阿德里安提到的同样的问题。虽然我理解提供的解决方案,但我无法理解为什么 XorCsrfTokenRequestAttributeHandler 没有解码请求标头中的 X-XSRF-TOKEN 值。下面的文档说 XorCsrfTokenRequestAttributeHandler 是 Spring security 6.0 中的默认设置。我也尝试明确添加它,但它不起作用。

我使用了 CsrfTokenRequestAttributeHandler 并且它有效,但只有当我们想选择退出 BREACH 时才应使用 CsrfTokenRequestAttributeHandler。

我可以像 Adrien 所说的那样使用 /csrf 端点,但是 Spring security 将 XSRF-TOKEN cookie 返回到浏览器有什么意义呢?

https://docs.spring.io/spring-security/reference/6.0/servlet/exploits/csrf.html#csrf-token-request-handler

© www.soinside.com 2019 - 2024. All rights reserved.