diff --git a/web/src/main/java/org/springframework/security/web/csrf/XorCsrfTokenRequestAttributeHandler.java b/web/src/main/java/org/springframework/security/web/csrf/XorCsrfTokenRequestAttributeHandler.java index d5699dff2ea..8d966331ae2 100644 --- a/web/src/main/java/org/springframework/security/web/csrf/XorCsrfTokenRequestAttributeHandler.java +++ b/web/src/main/java/org/springframework/security/web/csrf/XorCsrfTokenRequestAttributeHandler.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2022 the original author or authors. + * Copyright 2002-2023 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/web/src/main/java/org/springframework/security/web/server/csrf/XorServerCsrfTokenRequestAttributeHandler.java b/web/src/main/java/org/springframework/security/web/server/csrf/XorServerCsrfTokenRequestAttributeHandler.java index 12edaf0420f..1c94b233ff4 100644 --- a/web/src/main/java/org/springframework/security/web/server/csrf/XorServerCsrfTokenRequestAttributeHandler.java +++ b/web/src/main/java/org/springframework/security/web/server/csrf/XorServerCsrfTokenRequestAttributeHandler.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2022 the original author or authors. + * Copyright 2002-2023 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -88,7 +88,7 @@ private static String getTokenValue(String actualToken, String token) { System.arraycopy(actualBytes, randomBytesSize, xoredCsrf, 0, tokenSize); byte[] csrfBytes = xorCsrf(randomBytes, xoredCsrf); - return Utf8.decode(csrfBytes); + return (csrfBytes != null) ? Utf8.decode(csrfBytes) : null; } private static String createXoredCsrfToken(SecureRandom secureRandom, String token) { @@ -105,6 +105,9 @@ private static String createXoredCsrfToken(SecureRandom secureRandom, String tok } private static byte[] xorCsrf(byte[] randomBytes, byte[] csrfBytes) { + if (csrfBytes.length < randomBytes.length) { + return null; + } int len = Math.min(randomBytes.length, csrfBytes.length); byte[] xoredCsrf = new byte[len]; System.arraycopy(csrfBytes, 0, xoredCsrf, 0, csrfBytes.length); diff --git a/web/src/test/java/org/springframework/security/web/csrf/XorCsrfTokenRequestAttributeHandlerTests.java b/web/src/test/java/org/springframework/security/web/csrf/XorCsrfTokenRequestAttributeHandlerTests.java index acad523c74c..6f508624119 100644 --- a/web/src/test/java/org/springframework/security/web/csrf/XorCsrfTokenRequestAttributeHandlerTests.java +++ b/web/src/test/java/org/springframework/security/web/csrf/XorCsrfTokenRequestAttributeHandlerTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2022 the original author or authors. + * Copyright 2002-2023 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/web/src/test/java/org/springframework/security/web/server/csrf/XorServerCsrfTokenRequestAttributeHandlerTests.java b/web/src/test/java/org/springframework/security/web/server/csrf/XorServerCsrfTokenRequestAttributeHandlerTests.java index ef5b8c0cd66..315c2533025 100644 --- a/web/src/test/java/org/springframework/security/web/server/csrf/XorServerCsrfTokenRequestAttributeHandlerTests.java +++ b/web/src/test/java/org/springframework/security/web/server/csrf/XorServerCsrfTokenRequestAttributeHandlerTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2022 the original author or authors. + * Copyright 2002-2023 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -182,6 +182,16 @@ public void resolveCsrfTokenValueWhenHeaderAndFormDataSetThenFormDataIsPreferred StepVerifier.create(csrfToken).expectNext(this.token.getToken()).verifyComplete(); } + @Test + public void resolveCsrfTokenIsInvalidThenReturnsNull() { + this.exchange = MockServerWebExchange.builder(MockServerHttpRequest.post("/") + .header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_FORM_URLENCODED_VALUE) + .body(this.token.getParameterName() + "=" + XOR_CSRF_TOKEN_VALUE)).build(); + CsrfToken token = new DefaultCsrfToken("headerName", "paramName", "a"); + Mono csrfToken = this.handler.resolveCsrfTokenValue(this.exchange, token); + assertThat(csrfToken.block()).isNull(); + } + private static Answer fillByteArray() { return (invocation) -> { byte[] bytes = invocation.getArgument(0);