Improper signature counter value handling in webauthn4j-spring-security
Description
WebAuthn4J Spring Security provides Web Authentication specification support for Spring applications. Affected versions are subject to improper signature counter value handling. A flaw was found in webauthn4j-spring-security-core. When an authneticator returns an incremented signature counter value during authentication, webauthn4j-spring-security-core does not properly persist the value, which means cloned authenticator detection does not work. An attacker who cloned valid authenticator in some way can use the cloned authenticator without being detected. This issue has been addressed in version 0.9.1.RELEASE. Users are advised to upgrade. There are no known workarounds for this vulnerability.
Affected packages
Versions sourced from the GitHub Security Advisory.
| Package | Affected versions | Patched versions |
|---|---|---|
com.webauthn4j:webauthn4j-spring-security-coreMaven | < 0.9.1.RELEASE | 0.9.1.RELEASE |
Affected products
1- Range: < 0.9.1.RELEASE
Patches
1129700d74d83Merge pull request from GHSA-v9hx-v6vf-g36j
4 files changed · +18 −11
gradle.properties+2 −2 modified@@ -13,5 +13,5 @@ # See the License for the specific language governing permissions and # limitations under the License. # -webAuthn4JSpringSecurityVersion=0.9.1-SNAPSHOT -latestReleasedWebAuthn4JSpringSecurityVersion=0.9.0.RELEASE +webAuthn4JSpringSecurityVersion=0.9.1.RELEASE +latestReleasedWebAuthn4JSpringSecurityVersion=0.9.1.RELEASE
README.md+1 −1 modified@@ -24,7 +24,7 @@ If you are using Maven, just add the webauthn4j-spring-security as a dependency: <properties> ... <!-- Use the latest version whenever possible. --> - <webauthn4j-spring-security.version>0.9.0.RELEASE</webauthn4j-spring-security.version> + <webauthn4j-spring-security.version>0.9.1.RELEASE</webauthn4j-spring-security.version> ... </properties>
samples/spa/src/test/java/e2e/RegistrationAndAuthenticationE2ETest.java+14 −1 modified@@ -16,6 +16,7 @@ package e2e; +import com.webauthn4j.springframework.security.authenticator.WebAuthnAuthenticatorService; import com.webauthn4j.springframework.security.webauthn.sample.SampleSPA; import e2e.page.AuthenticatorLoginComponent; import e2e.page.PasswordLoginComponent; @@ -34,18 +35,24 @@ import org.openqa.selenium.support.ui.WebDriverWait; import org.openqa.selenium.virtualauthenticator.HasVirtualAuthenticator; import org.openqa.selenium.virtualauthenticator.VirtualAuthenticatorOptions; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.junit4.SpringRunner; import java.time.Duration; +import static org.assertj.core.api.Assertions.assertThat; + @RunWith(SpringRunner.class) @SpringBootTest(classes = SampleSPA.class, webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT) public class RegistrationAndAuthenticationE2ETest { private WebDriver driver; private WebDriverWait wait; + @Autowired + private WebAuthnAuthenticatorService webAuthnAuthenticatorService; + @BeforeClass public static void setupClassTest() { WebDriverManager.chromedriver().setup(); @@ -86,8 +93,10 @@ public void test() { signupComponent.waitRegisterClickable(); signupComponent.clickRegister(); - // Password authentication wait.until(ExpectedConditions.urlToBe("http://localhost:8080/angular/login")); + long counterValueAtRegistrationPhase = webAuthnAuthenticatorService.loadAuthenticatorsByUserPrincipal("john.doe@example.com").get(0).getCounter(); + + // Password authentication PasswordLoginComponent passwordLoginComponent = new PasswordLoginComponent(driver); passwordLoginComponent.setUsername("john.doe@example.com"); passwordLoginComponent.setPassword("password"); @@ -98,6 +107,10 @@ public void test() { // nop wait.until(ExpectedConditions.urlToBe("http://localhost:8080/angular/profile")); + long counterValueAtAuthenticationPhase = webAuthnAuthenticatorService.loadAuthenticatorsByUserPrincipal("john.doe@example.com").get(0).getCounter(); + + assertThat(counterValueAtAuthenticationPhase).isGreaterThan(counterValueAtRegistrationPhase); + ProfileComponent profileComponent = new ProfileComponent(driver); }
webauthn4j-spring-security-core/src/main/java/com/webauthn4j/springframework/security/WebAuthnAuthenticationProvider.java+1 −7 modified@@ -136,13 +136,7 @@ void doAuthenticate(WebAuthnAssertionAuthenticationToken authenticationToken, We ); AuthenticationParameters authenticationParameters = new AuthenticationParameters( parameters.getServerProperty(), - new AuthenticatorImpl( - webAuthnAuthenticator.getAttestedCredentialData(), - webAuthnAuthenticator.getAttestationStatement(), - webAuthnAuthenticator.getCounter(), - webAuthnAuthenticator.getTransports(), - webAuthnAuthenticator.getClientExtensions(), - webAuthnAuthenticator.getAuthenticatorExtensions()), + webAuthnAuthenticator, null, parameters.isUserVerificationRequired(), parameters.isUserPresenceRequired()
Vulnerability mechanics
Generated by null/stub on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
5- github.com/advisories/GHSA-v9hx-v6vf-g36jghsaADVISORY
- nvd.nist.gov/vuln/detail/CVE-2023-45669ghsaADVISORY
- github.com/webauthn4j/webauthn4j-spring-security/commit/129700d74d83f9b9a82bf88ebc63707e3cb0a725ghsax_refsource_MISCWEB
- github.com/webauthn4j/webauthn4j-spring-security/security/advisories/GHSA-v9hx-v6vf-g36jghsax_refsource_CONFIRMWEB
- www.w3.org/TR/2021/REC-webauthn-2-20210408/ghsax_refsource_MISCWEB
News mentions
0No linked articles in our index yet.