Web Gauntlet 3 picoCTF 2021 Solution

Published: April 2, 2026

Description

Final boss! Log in as admin using the SQLite-backed login form. More keywords are filtered this time.

Visit /filter to see the full blocklist before attempting your bypass.

Open the challenge URL and check /filter to see blocked keywords.

bash
curl http://mercury.picoctf.net:<PORT_FROM_INSTANCE>/filter
  1. Step 1Enumerate the expanded blocklist
    GET /filter to see every blocked term. Compared to Web Gauntlet 2, this version typically also blocks LIKE, GLOB, additional comment styles (#, /**/), and possibly || itself.
    bash
    curl http://mercury.picoctf.net:<PORT_FROM_INSTANCE>/filter
    Learn more

    Strategy. With most named operators blocked, the goal is to manipulate the query without spelling out any blocked term. SQLite has two escape hatches that rarely show up in blocklists: CHAR() for code-point strings, and hex blob literals for raw byte strings.

  2. Step 2Build 'admin' from CHAR() or a hex blob literal
    If you can output literal characters but not the word 'admin', generate the string with CHAR(97,100,109,105,110) or X'61646d696e'. Both evaluate to 'admin' inside the query without any letter appearing in your input.
    bash
    # Generate CHAR() expression for any string:
    python3 -c "s='admin'; print(','.join(str(ord(c)) for c in s))"
    # 97,100,109,105,110
    
    # Hex literal:
    python3 -c "print('admin'.encode().hex())"
    # 61646d696e   ->  X'61646d696e'
    Learn more

    CHAR() function. SQLite's CHAR(n1, n2, ...) returns the string formed by the given Unicode code points. CHAR(97,100,109,105,110) is admin. No quote, no letter, no recognizable keyword.

    Hex blob literal. X'hexstring' is a SQLite literal that decodes the hex into raw bytes. X'61646d696e' is the byte sequence 61 64 6D 69 6E which is ASCII admin. SQLite implicitly converts BLOB to TEXT for string comparisons, so it works as a username. Useful when you can output hex but not quotes around your payload.

    See SQL injection for CTF for the broader CHAR/hex/UNHEX trick library.

  3. Step 3Submit the bypass and retrieve the flag
    POST a username crafted with CHAR() or a hex literal that ends up evaluating to admin in the query, plus any password. A successful login reveals the flag.
    bash
    # Example bypass (assumes /* and */ are allowed):
    curl -X POST http://mercury.picoctf.net:<PORT_FROM_INSTANCE>/login \
      -d "username=admin'/*&password=x"
    Learn more

    Multiline comment bypass. If /* and */ are unblocked, admin'/* closes the username string and starts a multiline comment that swallows the password check until the next */ the server appends. Shape of the resulting query: WHERE username='admin'/* AND password='x'. The comment kills the password condition.

    Defense in depth doesn't help here. Each filter version closes one escape hatch and SQLite offers another. Parameterized queries are the only fix.

Flag

picoCTF{...}

SQLite's CHAR() function and hex blob literals bypass even aggressive keyword filters. The only real fix is parameterized queries, not blocklists.

Want more picoCTF 2021 writeups?

Useful tools for Web Exploitation

Related reading

What to try next