Listen to this Post
The vulnerability resides in Angular’s `HttpTransferCache` mechanism used during Server-Side Rendering (SSR).
When an Angular application renders on the server, HTTP requests are cached inside `TransferState` to avoid re-fetching them on the client (hydration).
Each cached response is associated with a cache key generated by hashing the request’s method, response type, mapped URL, serialized body, and sorted query parameters.
The hash function used is a weak 32-bit DJB2-like polynomial rolling hash, which produces a very small hash space (only 4,294,967,296 possible values).
Because 32 bits are cryptographically insufficient, an attacker can deliberately craft inputs that cause hash collisions.
Specifically, the attacker computes a query parameter string (e.g., ?q=aaCAZMMM) for a benign, attacker‑controlled endpoint (e.g., a search API) that yields the exact same 32‑bit hash as a sensitive endpoint (e.g., /api/user/profile).
The victim is tricked into visiting a malicious link that triggers both the benign and the sensitive request during SSR.
Due to the hash collision, the response from the attacker‑controlled search request overwrites the legitimate response for the sensitive profile endpoint inside TransferState.
When the client hydrates the application, Angular attempts to read the cached response for the profile endpoint.
Instead of the real user data, the application receives the attacker‑forged response from the search request.
This leads to State Poisoning: the application’s internal state now contains malicious data that can bypass client‑side security checks.
If the poisoned data is rendered unsafely (e.g., using `innerHTML` or similar), it can cause DOM‑based Cross‑Site Scripting (XSS).
Additionally, Information Leakage may occur if the victim’s legitimate sensitive data is inadvertently served in place of the search results and exposed to the attacker.
The attack works because the cache key does not incorporate any secret or request‑specific nonce, and the 32‑bit hash makes brute‑force collision search trivial (a few minutes on a modern CPU).
An attacker only needs to find one collision between a chosen query parameter and the target endpoint’s hash.
Once a colliding string is found, any request that includes that parameter will overwrite the target’s cache entry.
The vulnerability affects all Angular applications that enable SSR with `HttpTransferCache` (default in provideClientHydration).
No authentication or special privileges are required; the attack is remote and can be delivered via a crafted URL or any user‑controllable input that influences outgoing HTTP requests during SSR.
Angular versions prior to 17.2.1, 16.2.12, and 15.2.11 are vulnerable.
The fix replaces the weak 32‑bit hash with SHA‑256, producing a 256‑bit hexadecimal key that makes collisions computationally infeasible.
This CVE (CVE‑2024‑23331) was discovered and reported by CodeMender from Google DeepMind.
DailyCVE Form:
Platform: Angular SSR
Version: Before 17.2.1
Vulnerability: Cache Hash Collision
Severity: Medium CVSS 7.5
date: 22 February 2024
Prediction: 04 March 2024
What Undercode Say:
Generate DJB2 hash collisions (Python example)
python3 -c "
def djb2(data):
hash = 5381
for c in data:
hash = ((hash << 5) + hash) + ord(c)
return hash & 0xffffffff
target_hash = djb2('/api/user/profile')
print(f'Target hash: {target_hash}')
Brute-force collision for query param (simplified)
import itertools
import string
for length in range(8, 12):
for combo in itertools.product(string.ascii_letters, repeat=length):
q = 'q=' + ''.join(combo)
if djb2(q) == target_hash:
print(f'Collision found: {q}')
break
else:
continue
break
"
Simulate cache overwrite with colliding parameter during SSR curl -X GET 'https://victim-app.com/search?q=aaCAZMMM' \ -H 'User-Agent: bot' \ --cookie 'session=xxx'
Exploit:
- Attacker computes the 32‑bit DJB2 hash of the target sensitive endpoint (e.g.,
/api/user/profile). - Attacker brute‑forces short query strings (e.g.,
?q=...) until a collision with that hash is found. - Attacker constructs a malicious link: `https://victim.com/search?q=COLLISION_STRING&redirect=/profile` that forces the SSR to execute both the search request (attacker‑controlled) and the profile request.
- Victim clicks the link; the server renders the page, and the search response overwrites the profile cache entry.
- When the client hydrates, Angular serves the forged search response where the profile data should be, leading to state poisoning, XSS, or data leakage.
Protection:
– Upgrade to Angular 17.2.1, 16.2.12, 15.2.11 or later (framework‑level fix uses SHA‑256).
– If upgrade is not possible, disable `HttpTransferCache` globally:
provideClientHydration(withNoHttpTransferCache())
– Or disable per sensitive request:
this.http.get('/api/user/profile', { transferCache: false })
– Alternatively, patch the hash function manually to SHA‑256 in custom `HttpTransferCache` options.
Impact:
- State Poisoning: Attacker‑controlled data replaces legitimate application state, potentially bypassing client‑side security controls.
- DOM‑based XSS: Poisoned data rendered unsafely leads to arbitrary JavaScript execution in the victim’s browser.
- Information Leakage: Victim’s sensitive data (e.g., profile, tokens) may be sent to the attacker if mistakenly rendered in place of attacker’s search results.
🎯Let’s Practice Exploiting & Learn Patching For Free:
🎓 Live Courses & Certifications:
Join Undercode Academy for Verified Certifications
🚀 Request a Custom Project:
Secure, high-velocity infrastructure and disruptive technological engineering. Contact our engineering team for high-tier development and proprietary systems:
[email protected]
💎 Smart Architecture | 🛡️ Secure by Design | ⭐ Trusted by Thousands
Sources:
Reported By: github.com
Extra Source Hub:
Undercode

