18/12/2025
Blog technique
[CVE-2025-66406] ARBITRARY SSH CERTIFICATE REVOCATION ON STEP-CA
Gabriel DEPARTOUT & Andy RUSSON
Recently, our team performed a security audit of SmallStep Certificates PKI. This audit was focused on the cryptographic aspects of the PKI, mainly the keys and certificates management and storage, certificates transfer, API security and code review. This audit was aimed at evaluating the cryptographic level and robustness of the solution.
This security audit was funded by the French cybersecurity agency (ANSSI) as part of its efforts to support the security assessment of open source software (more info here).
During this pentest, we identified one vulnerability, allowing a user to revoke any ssh certificate issued by the PKI. This vulnerability was responsibly disclosed to SmallStep, which fixed it quickly : https://github.com/smallstep/certificates/security/advisories/GHSA-j7c9-79×7-8hpr.
The CVE ID CVE-2025-66406 was assigned to it.
Exploit scenario
Any user possessing an SSH certificate signed by the PKI Step CA can revoke arbitrarily any existing SSH certificate issued by the PKI Step CA by simply authentifying himself with a valid sshpop JWT (that he can provide) and modifying the target serial number in the revocation request.
Attack path
The attacker has to forge a valid JWT containing his SSH legitimate certificate and then sign the JWT with the private key of its SSH certificate.
Then, he can use this token to authenticate himself on the Step CA PKI in order to revoke his SSH certificate. The attacker has to intercept and modify the revocation request and replace his certificate serial number by the target certificate serial number he wants to revoke.
Proof of concept
Create two SSH certificates with Step CA, one for the attacker and one for the victim:
step ssh certificate attack.cert ssh_attack_key
step ssh certificate victim.cert ssh_victim_key
Get the serial number of the victim certificate:
step ssh inspect ssh_victim_key-cert.pub
[…]
Serial: 9270442165428020971
[…]
Make a revocation request using sshpop JWT authentication for the attacker certificate:
step ssh revoke --sshpop-cert ssh_attack_key-cert.pub --sshpop-key ssh_attack_key
Set up Burp proxy to intercept the request and replace the value serial by the target victim serial number:
Step CA PKI accepts the request. Once done, one can notice that the certificate associated with the target serial number in the revocation request is now revoked, but not the attacker SSH certificate.
Source code
Indeed, our team also checked in the source code: it does not check if the serial number in the sshpop payload is the same than the one provided in the value serial.
In the file api/revoke.go, a consistency check exists during the revocation of a X.509 certificate inside the Revoke() function that is called upon reception of the HTTP request. However, there is no such consistency check in the case of an SSH certificate in the file api/sshRevoke.go in the function SSHRevoke() that manages the HTTP request for SSH revocation.
If you want to find out more about the security audit or evaluation capabilities of our SEAL, feel free to reach us.
If you would like more information about ANSSI’s efforts to support open‑source security, please send an email to [email protected].