Improper Verification of Cryptographic Signature
Summary
This category covers a service accepting a cryptographically-signed object - most commonly a JWT - without actually verifying its signature is valid, or without properly restricting which signature algorithms it will accept. The best-known concrete instance is the JWT alg: none bug: some JWT libraries, if not explicitly told otherwise, will honor a token whose header declares "alg": "none" and accept it as valid with no signature check at all, letting an attacker forge any claims (including an admin role) by simply re-encoding the header and payload with no signature. A related variant swaps RS256 (asymmetric) for HS256 (symmetric) - if the server's public RSA key is discoverable and the verification code doesn't pin the expected algorithm, an attacker can sign a forged token with the public key treated as an HMAC secret, and the server will verify it as valid.
Top Affected Components / Targets
- JWT-based session/API authentication
- Signed webhook payloads and callback verification
- Signed license keys or feature-flag tokens
Common Attack Vectors
- Decode a captured JWT, change
"alg"to"none", strip the signature segment, and replay the token with modified claims (e.g.role: admin) - Re-sign a captured token using
HS256with the server's known/discoverable RSA public key as the HMAC secret, when the original token usedRS256
Common Payloads
{"alg":"none","typ":"JWT"}header with an empty signature segment- A token re-signed with
HS256using the target's public key as the shared secret
Detection Strategy
For every JWT discovered in cookies, headers, or request bodies, decode the header and check alg. If the header already declares none, that's direct proof the server issues unsigned tokens. Where the header declares a real algorithm, actively forge a variant with alg set to none and an empty signature, replay it against an authenticated endpoint, and check whether the server accepts it - confirming the server-side verification code doesn't reject the downgrade.
Tip: Testing tools that run these checks in parallel across every discovered endpoint can cut the time required substantially compared to fully manual testing, as long as they confirm findings with more than one signal to keep the false-positive rate down.
False-Positive Notes
- A passive
alg: noneobservation (the token as captured already usesnone) is definitive on its own. - The active forgery variant requires the server to actually accept the replayed token on a real authenticated request - a token that's merely well-formed but rejected at the application layer isn't a finding.
How to Test
Manual Testing Methodology
Here is a systematic approach to identifying Improper Verification of Cryptographic Signature vulnerabilities in a target application.
Before testing, map all input vectors that could be affected. Identify parameters, headers, cookies, and request bodies that interact with the vulnerable component. A proxy such as Burp Suite or OWASP ZAP, paired with normal browsing of the target, is usually enough to build this list.
Send a legitimate request and record the normal response: status code, content length, response time, and any identifying tokens. This baseline matters because it's what you'll compare later responses against once payloads are involved.
Inject test payloads into each identified input vector one at a time. Start with benign detection payloads before escalating to anything that could actually trigger the vulnerability. For Improper Verification of Cryptographic Signature specifically, capture traffic on any link expected to be encrypted (including internal/service-to-service where reachable) to check for cleartext transmission, and probe signature or token-verification endpoints with a stripped, empty, or mismatched signature to see whether verification is actually enforced.
Compare the response against your baseline, looking specifically for sensitive data (credentials, personal information, session tokens) visible in plaintext on the wire or in storage, or a request with an invalid/missing signature that the server accepts as valid anyway.
Once a potential vulnerability is detected, confirm it with at least a few independent test cases to rule out coincidence. Document the exact request and response as proof. For Improper Verification of Cryptographic Signature, a confirmed finding typically means showing that attacker-controlled input changes the application's behavior in a way that matters for security, not just that a payload was reflected somewhere harmless.
Real-World Impact
Real-World Impact
Sensitive data stored or transmitted in cleartext is exposed to anyone with read access to the storage layer or the network path — a database backup, a misconfigured bucket, or a passive network observer on an unencrypted link all yield the data directly, with no cryptographic barrier to defeat first.
Broken cryptographic-signature verification is a related but distinct failure: even where encryption is used correctly elsewhere, a signature check implemented as a naive string comparison (rather than a constant-time comparison) or that accepts a malformed or absent signature can let an attacker forge tokens, licenses, or authenticated messages outright.
Both failure modes tend to surface only when it's already too late — in a breach post-mortem, a compliance audit, or a researcher's report — since neither one changes the application's normal behavior in a way that would be caught by functional testing alone.
Prevention & Remediation
Prevention and Secure Coding
Preventing Improper Verification of Cryptographic Signature takes a defense-in-depth approach — no single control below is sufficient alone, but together they close off both the primary path and the most common bypasses.
Encrypt sensitive data at rest. Apply encryption to sensitive fields and backups at the storage layer, with key management separated from the data itself.
TLS everywhere, including internal traffic. Enforce TLS for all data in transit — between the client and the edge, and between internal services, since an internal network is not an implicit trust boundary.
Constant-time signature comparison. Verify cryptographic signatures using the crypto library's constant-time comparison function, never a plain ==/.equals() check, which leaks timing information an attacker can use to forge a valid signature byte by byte.
Keep TLS configuration current. Disable legacy protocol versions and weak cipher suites, and monitor certificate expiry actively rather than reactively.
Minimize what needs protecting. Don't retain or transmit sensitive data that isn't actually needed — the cheapest way to reduce cleartext-exposure risk is to reduce the surface that requires protection at all.