$ cat writeup.md…
$ cat writeup.md…
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.
$ cat /etc/rate-limit
Rate limit reached (20 reads/hour per IP). Showing preview only — full content returns at the next hour roll-over.
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.
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:
carabubu2026Those 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.
The core issue was an authenticated arbitrary file upload in a directory where Apache configuration overrides were enabled. That let us chain two uploads:
.htaccessThe .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.
The published writeup path was reproducible on the live target, but one implementation detail differed slightly during our run:
ufilenameu_12 worked for the .htaccess upload,new_filename field was the reliable way to land shell.txt in practice....
$ grep --similar