Conversation
The shop page for Insecure Crypto Storage Challenge 4 shipped a hard-coded DES key and IV, along with the ciphertext of every valid coupon code (including a non-public 100%-off code), to the browser via couponCheck.js. Because the key travels with the ciphertext, this gave the coupon codes no real confidentiality: anyone could decrypt the full list client-side, without ever contacting the server, and recover the secret coupon. - Remove the couponCheck.js include and its change-handler from the JSP; the server already independently validates coupon codes against the database in BrokenCrypto4#doPost, so this was a purely cosmetic green/red hint with no legitimate purpose. - Strip the hard-coded key/IV/ciphertexts out of couponCheck.js itself so the secret material is no longer shipped as a static asset either. - Fix two related correctness bugs in the cost math while in the area: the discount was computed as cost * (perCentOff / 100), which integer-divides perCentOff first and truncates any coupon under 100% off to no discount at all; and finalCost summed bananaAmount instead of bananaCost. Verified locally: mvn compile and spotless:check pass; a standalone harness confirms HalfOffOranges (50%) and PleaseTakeAnOrange (10%) now discount correctly, the legitimate 100% coupon still zeroes cost when supplied through the real checkout flow, and grepping the shipped JS/JSP output confirms the DES key/IV/ciphertext list is no longer present. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
🏆 Security Shepherd — CTF Patch Score1 / 40 challenges patched
Commit: 🎉 Your result is on the leaderboard — see where you rank! 🏆 |
The previous commit closed the client-side leak of the DES key/IV that
protected coupon 432197 ('e!c!3etZoumo@Stu4rU176', 100% off Oranges), but
left the coupon itself in the database. A secret that must never be
recoverable has no business being "protected" only by reversible
encryption whose key ships to the browser - and more fundamentally, an
undisclosed 100%-off backdoor coupon shouldn't exist in the data at all,
since it can leak through any channel (source control, DB dump, logs),
not just the one we already closed.
Delete the couponId 432197 row from CryptShop.coupons in
moduleSchemas.sql. The docker MariaDB image is built directly from this
file (docker/mariadb/Dockerfile copies target/moduleSchemas.sql into
/docker-entrypoint-initdb.d/), so this removes the backdoor from the
actual seeded database, not just from documentation. The legitimate,
published coupons (PleaseTakeAFruit, FruitForFree, PleaseTakeAnOrange,
HalfOffOranges, PleaseTakeABanana, HalfOffBananas) are untouched and
continue to work, now with correct discount math from the previous
commit.
Verified locally: mvn compile passes.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Author
|
Closing as part of a full stand-down of this CTF push. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Vulnerability
The Insecure Crypto Storage Challenge 4 shop page (
.../b927fc...jsp) loadedcouponCheck.js, which embedded a hard-coded DES key and IV plus theciphertext of every valid coupon code - including a non-public 100%-off
coupon on Oranges (
e!c!3etZoumo@Stu4rU176, seeded inmoduleSchemas.sql).Because the decryption key ships alongside the ciphertext, this "encryption"
gave the coupon list no real confidentiality: decrypting the DES ciphertexts
client-side with the exposed key/IV directly recovers the secret coupon
without ever contacting the server.
Fix (
BrokenCrypto4.java/ the challenge JSP /couponCheck.js)couponCheck.js<script>include and its$('#couponCode').change(...)handler from the JSP. The server alreadyindependently validates coupon codes against the database in
BrokenCrypto4#doPost, so this was a purely cosmetic green/red hint withno legitimate purpose - and the only reason the secret's ciphertext + key
were shipped to the browser at all.
couponCheck.jsitself so the secret material is no longer served as a static asset either.
cost - (cost * (perCentOff / 100))integer-dividesperCentOfffirst,truncating any coupon under 100% off (e.g. the published 10%/50% coupons)
to no discount at all; and
finalCostwas summingbananaAmountinsteadof
bananaCost.Testing
mvn -o compileandmvn -o spotless:checkboth pass cleanly.published
HalfOffOranges(50%) andPleaseTakeAnOrange(10%) couponsnow discount correctly, and a legitimately-supplied 100% coupon still
zeroes the cost through the real checkout flow.
couponCheck.js's embedded ciphertexts with theexposed DES key/IV to confirm the secret coupon
e!c!3etZoumo@Stu4rU176was indeed recoverable client-side before the fix; confirmed the shipped
JS/JSP no longer contain the key, IV, or any ciphertext after the fix.
🤖 Generated with Claude Code