webfreemedium

AgriWeb

hackthebox

Task: Patch a prototype pollution vulnerability in a Node.js Express web app to get the flag. Solution: Identify unfiltered __proto__/constructor keys in a deepMerge function, upload a patched version that filters dangerous keys, restart the app, and verify the fix via /api/verify endpoint.

$ ls tags/ techniques/
prototype_pollution_fixdeepmerge_sanitizationcode_review

$ cat /etc/rate-limit

Rate limit reached (20 reads/hour per IP). Showing preview only — full content returns at the next hour roll-over.

AgriWeb - HackTheBox CTF

Description

"Digital farmlands lie ruined as drones spin out of control and greenhouses overheat; the white-hats must infiltrate the corrupted AgriWeb interface and bring the fields back to life."

Target: http://94.237.120.112:57056

Analysis

Initial Reconnaissance

Accessed the target URL and found an "HTB Editor" - a code editor interface with API access to the application source code.

API Endpoints Discovered

  • /api/directory - List files
  • /api/file?path=X - Read file contents
  • /api/create-file - Create new files
  • /api/delete - Delete files
  • /api/restart - Restart application
  • /api/verify - Verify if vulnerability is patched

Application Structure

app.js              - Main Express application
routes/auth.js      - Authentication routes
routes/profile.js   - Profile update routes (VULNERABLE)
utils/jwt.js        - JWT token handling
utils/database.js   - SQLite database setup
exploit/solver.py   - Hint file showing the attack

Vulnerability: Prototype Pollution in deepMerge

Found in routes/profile.js:

function deepMerge(target, source) { for (let key in source) { if (source[key] && typeof source[key] === 'object' && !Array.isArray(source[key])) { if (!target[key]) target[key] = {}; deepMerge(target[key], source[key]); } else { target[key] = source[key]; } } return target; }

Problem: This function doesn't filter dangerous keys (__proto__, constructor, prototype), allowing prototype pollution.

Impact: The JWT token generation in utils/jwt.js checks user.role === 'admin' to set isAdmin: true. By polluting the Object prototype with isAdmin: true, any user could bypass admin authentication.

The Twist - Code Patching Challenge

The /api/verify endpoint returned: "Application vulnerability is not patched."

This revealed the challenge wasn't about exploiting the vulnerability, but patching it!

Solution

Step 1: Delete the vulnerable file

curl -X DELETE "http://94.237.120.112:57056/api/delete" \ -H "Content-Type: application/json" \ -d '{"path":"routes/profile.js"}'

Step 2: Create patched version with prototype pollution protection

...

$ grep --similar

Similar writeups