Skip to content

Add Cache Poisoning Vulnerability#534

Merged
preetkaran20 merged 23 commits into
SasanLabs:masterfrom
luks-santos:feature/cache-poisoning
Apr 30, 2026
Merged

Add Cache Poisoning Vulnerability#534
preetkaran20 merged 23 commits into
SasanLabs:masterfrom
luks-santos:feature/cache-poisoning

Conversation

@luks-santos
Copy link
Copy Markdown
Contributor

@luks-santos luks-santos commented Mar 16, 2026

Summary

Closes #516.
This PR delivers the full level progression for the Cache Poisoning vulnerability, from the basic route-only cache key issue to the secure implementation, and adds the supporting frontend, hints, i18n, and automated tests
needed for the lab experience.

Implemented levels

  • LEVEL_1: reflected banner query parameter is rendered unescaped (also exploitable as stored XSS via the shared cache) while the cache key uses only the route.
  • LEVEL_2: naive filtering of the banner parameter does not fix the underlying issue because the cache key is still route-only — alternative unkeyed inputs keep the poisoning viable.
  • LEVEL_3: the query parameter is now part of the cache key, but the page remains vulnerable through an unkeyed X-Forwarded-Host header used to build absolute asset URLs.
  • LEVEL_4: forwarded host headers are ignored, but personalized cookie-driven content (including derived email and tracked IP) is still cached publicly, demonstrating cross-user PII leakage from a shared cache.
  • LEVEL_5: secure variant — ignores untrusted forwarding headers, escapes reflected content, uses a trusted asset host, and returns personalized responses with Cache-Control: private, no-store.

@codecov-commenter
Copy link
Copy Markdown

codecov-commenter commented Mar 16, 2026

Codecov Report

❌ Patch coverage is 92.48120% with 10 lines in your changes missing coverage. Please review.
✅ Project coverage is 53.12%. Comparing base (45d14fc) to head (4178173).
⚠️ Report is 17 commits behind head on master.

Files with missing lines Patch % Lines
...ty/cachePoisoning/CachePoisoningVulnerability.java 95.00% 3 Missing and 3 partials ⚠️
...e/vulnerability/cachePoisoning/CachedResponse.java 63.63% 3 Missing and 1 partial ⚠️
Additional details and impacted files
@@             Coverage Diff              @@
##             master     #534      +/-   ##
============================================
+ Coverage     52.01%   53.12%   +1.10%     
- Complexity      465      510      +45     
============================================
  Files            69       72       +3     
  Lines          2676     2850     +174     
  Branches        285      296      +11     
============================================
+ Hits           1392     1514     +122     
- Misses         1153     1201      +48     
- Partials        131      135       +4     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@luks-santos luks-santos marked this pull request as ready for review March 22, 2026 19:35
@luks-santos luks-santos changed the title Add cache poisoning level 1 vulnerability (Draft) Add cache poisoning level 1 vulnerability Mar 23, 2026
…ature/cache-poisoning

# Conflicts:
#	src/main/java/org/sasanlabs/vulnerability/types/VulnerabilityType.java
#	src/main/resources/i18n/messages.properties
@luks-santos luks-santos changed the title Add cache poisoning level 1 vulnerability Add Cache Poisoning Vulnerability Mar 23, 2026
@luks-santos luks-santos marked this pull request as draft March 23, 2026 19:56
@luks-santos luks-santos marked this pull request as ready for review March 24, 2026 12:55
Comment thread src/main/resources/i18n/messages.properties Outdated
Comment thread src/main/resources/i18n/messages.properties Outdated
Comment thread src/main/resources/i18n/messages.properties
Comment thread src/main/resources/static/templates/CachePoisoning/LEVEL_1/CachePoisoning.js Outdated
Comment thread src/main/resources/static/templates/CachePoisoning/LEVEL_4/CachePoisoning.js Outdated
Comment thread src/main/resources/attackvectors/CachePoisoningPayload.properties
Copy link
Copy Markdown
Member

@preetkaran20 preetkaran20 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@luks-santos I must say this is amazing code change. Very thorough PR. I really liked the PR completeness. I have added small comments, can you please address?

@luks-santos
Copy link
Copy Markdown
Contributor Author

@preetkaran20 Thanks a lot for the feedback!
I’ll review your comments and make the updates

@luks-santos luks-santos marked this pull request as draft April 3, 2026 00:41
 - Level 4 cached response now embeds derived email and last-login IP
 - Rewrite L3, L4 and L5 payload hints around the lab UI flow
 - Auto-clear attacker input after poison click (per-level)
…ature/cache-poisoning

# Conflicts:
#	src/main/resources/i18n/messages.properties
@luks-santos luks-santos marked this pull request as ready for review April 17, 2026 11:54
@luks-santos
Copy link
Copy Markdown
Contributor Author

Hi @preetkaran20

I've pushed the changes addressing the feedback. Summary of what was implemented:

Frontend / UX

  • Moved level-specific templates into a common directory to reduce duplication (230afec).
  • Refactored levels 1–5 to reuse doGetAjaxCall and pass xhr to callbacks (6049137).
  • Added a "reset cache" button on every level so the lab is reproducible without restarting (3bae76d).

Vulnerability depth

  • Made Level 1 exploitable as XSS through the poisoned cached response (179777a).
  • Exposed multiple attack vectors per level with matching hints/payloads (5afcb79, f0f30a9).
  • Enriched Level 4 PII leak (derived email + tracked IP) and tightened the overall lab (447b47c).
  • Improved Level 3 visualization and fixed the simulation (ba62756, 2673d64).

The PR description has been updated to reflect the final scope. Let me know if there's anything else you'd like me to adjust!

Comment thread src/main/resources/static/templates/CachePoisoning/Common/CachePoisoning.js Outdated
Comment thread src/main/resources/static/templates/CachePoisoning/Common/CachePoisoning.js Outdated
Comment thread src/main/resources/static/vulnerableApp.js
Comment thread src/main/resources/i18n/messages_en_US.properties
Copy link
Copy Markdown
Member

@preetkaran20 preetkaran20 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overall, @luks-santos this is really a great PR. I have added a few comments, I think once they are resolved, i think we can merge it quickly. Just a few thoughts on browser side caching issues which we need to work on.

…t keyed by level, so that clearing only evicts entries for the requested level instead of flushing the whole shared cache.
Introduces a per-level toggle that switches between two Cache-Control modes on the server response:
  - ON (default, realistic): public, max-age=60 — browser and shared cache
  - OFF (student-friendly): public, s-maxage=60, max-age=0 — shared cache only, browser always revalidates, scanners still detect via s-maxage
@luks-santos
Copy link
Copy Markdown
Contributor Author

luks-santos commented Apr 28, 2026

Hi @preetkaran20,

I've pushed the changes addressing the feedback. Here's a principal summary of what was implemented:

Cache reset reliability

  • Moved cache clearing into a single POST /clearCache?level=<level> endpoint. This ensures that resetting one level no longer flushes the entire shared cache, each reset now evicts only entries for the targeted level (5d02696).

Browser cache toggle (Levels 1–4)

  • Added a Browser cache checkbox to the Controls block on each vulnerable level (4178173).

  • When OFF, the server emits:

    Cache-Control: public, s-maxage=60, max-age=0
    

    instead of:

    Cache-Control: public, max-age=60
    

This ensures the browser always revalidates while the shared cache layer (the one being poisoned) keeps its 60-second TTL.

  • I think s-maxage directive preserves scanner detection.

  • Level 5 (secure variant) remains unchanged.


Let me know if there's anything else you'd like me to adjust!

I've opened the PR at SasanLabs/VulnerableApp-facade#112

Copy link
Copy Markdown
Member

@preetkaran20 preetkaran20 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Amazing job @luks-santos One of the best change.

@preetkaran20 preetkaran20 merged commit c68b25b into SasanLabs:master Apr 30, 2026
1 check passed
@preetkaran20
Copy link
Copy Markdown
Member

Merged the PR @luks-santos Amazing work!!!!!

@preetkaran20
Copy link
Copy Markdown
Member

🎉 Thanks for contributing @luks-santos!
We’d love to stay in touch and grow SasanLabs 🚀
👉 Please fill this (takes 30 sec):
https://docs.google.com/forms/d/e/1FAIpQLSfwWVdnULUhtfruA-DN328NwKnBGebaWg9U5y0xivLLxxoMog/viewform?usp=pp_url&entry.1414771947=luks-santos

Also consider ⭐ starring the repo if you like it!

🎯 Want to keep going? Here's a good next issue for you:
👉 #497 - Add NOSQL Injection vulnerability.

@preetkaran20
Copy link
Copy Markdown
Member

@all-contributors please add @luks-santos for code

@allcontributors
Copy link
Copy Markdown
Contributor

@preetkaran20

I've put up a pull request to add @luks-santos! 🎉

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Implement Cache Poisoning Vulnerability

3 participants