fingerprint-mcp 0.1.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/LICENSE +663 -0
- package/README.ar.md +767 -0
- package/README.bn.md +767 -0
- package/README.bs.md +767 -0
- package/README.da.md +767 -0
- package/README.de.md +770 -0
- package/README.el.md +767 -0
- package/README.es.md +769 -0
- package/README.fr.md +769 -0
- package/README.hi.md +767 -0
- package/README.it.md +767 -0
- package/README.ja.md +767 -0
- package/README.ko.md +772 -0
- package/README.md +767 -0
- package/README.no.md +767 -0
- package/README.pl.md +767 -0
- package/README.pt-BR.md +767 -0
- package/README.ru.md +767 -0
- package/README.th.md +767 -0
- package/README.tr.md +767 -0
- package/README.uk.md +767 -0
- package/README.vi.md +767 -0
- package/README.zh-TW.md +768 -0
- package/README.zh.md +768 -0
- package/dist/app/index.d.ts +3 -0
- package/dist/app/index.d.ts.map +1 -0
- package/dist/app/index.js +614 -0
- package/dist/app/index.js.map +1 -0
- package/dist/composite/analyze.d.ts +3 -0
- package/dist/composite/analyze.d.ts.map +1 -0
- package/dist/composite/analyze.js +59 -0
- package/dist/composite/analyze.js.map +1 -0
- package/dist/composite/correlate.d.ts +3 -0
- package/dist/composite/correlate.d.ts.map +1 -0
- package/dist/composite/correlate.js +184 -0
- package/dist/composite/correlate.js.map +1 -0
- package/dist/composite/enumerate.d.ts +3 -0
- package/dist/composite/enumerate.d.ts.map +1 -0
- package/dist/composite/enumerate.js +94 -0
- package/dist/composite/enumerate.js.map +1 -0
- package/dist/composite/helpers.d.ts +22 -0
- package/dist/composite/helpers.d.ts.map +1 -0
- package/dist/composite/helpers.js +111 -0
- package/dist/composite/helpers.js.map +1 -0
- package/dist/composite/index.d.ts +3 -0
- package/dist/composite/index.d.ts.map +1 -0
- package/dist/composite/index.js +29 -0
- package/dist/composite/index.js.map +1 -0
- package/dist/composite/meta.d.ts +3 -0
- package/dist/composite/meta.d.ts.map +1 -0
- package/dist/composite/meta.js +23 -0
- package/dist/composite/meta.js.map +1 -0
- package/dist/composite/osint.d.ts +3 -0
- package/dist/composite/osint.d.ts.map +1 -0
- package/dist/composite/osint.js +40 -0
- package/dist/composite/osint.js.map +1 -0
- package/dist/composite/recon.d.ts +3 -0
- package/dist/composite/recon.d.ts.map +1 -0
- package/dist/composite/recon.js +131 -0
- package/dist/composite/recon.js.map +1 -0
- package/dist/composite/scan-dns.d.ts +3 -0
- package/dist/composite/scan-dns.d.ts.map +1 -0
- package/dist/composite/scan-dns.js +44 -0
- package/dist/composite/scan-dns.js.map +1 -0
- package/dist/composite/scan-http.d.ts +3 -0
- package/dist/composite/scan-http.d.ts.map +1 -0
- package/dist/composite/scan-http.js +68 -0
- package/dist/composite/scan-http.js.map +1 -0
- package/dist/composite/scan-paths.d.ts +3 -0
- package/dist/composite/scan-paths.d.ts.map +1 -0
- package/dist/composite/scan-paths.js +32 -0
- package/dist/composite/scan-paths.js.map +1 -0
- package/dist/composite/scan-ports.d.ts +3 -0
- package/dist/composite/scan-ports.d.ts.map +1 -0
- package/dist/composite/scan-ports.js +79 -0
- package/dist/composite/scan-ports.js.map +1 -0
- package/dist/composite/scan-services.d.ts +3 -0
- package/dist/composite/scan-services.d.ts.map +1 -0
- package/dist/composite/scan-services.js +111 -0
- package/dist/composite/scan-services.js.map +1 -0
- package/dist/composite/scan-tls.d.ts +3 -0
- package/dist/composite/scan-tls.d.ts.map +1 -0
- package/dist/composite/scan-tls.js +32 -0
- package/dist/composite/scan-tls.js.map +1 -0
- package/dist/composite/scan-waf.d.ts +3 -0
- package/dist/composite/scan-waf.d.ts.map +1 -0
- package/dist/composite/scan-waf.js +35 -0
- package/dist/composite/scan-waf.js.map +1 -0
- package/dist/correlation/index.d.ts +3 -0
- package/dist/correlation/index.d.ts.map +1 -0
- package/dist/correlation/index.js +1044 -0
- package/dist/correlation/index.js.map +1 -0
- package/dist/data/analytics-patterns.d.ts +21 -0
- package/dist/data/analytics-patterns.d.ts.map +1 -0
- package/dist/data/analytics-patterns.js +449 -0
- package/dist/data/analytics-patterns.js.map +1 -0
- package/dist/data/app-signatures.d.ts +52 -0
- package/dist/data/app-signatures.d.ts.map +1 -0
- package/dist/data/app-signatures.js +1143 -0
- package/dist/data/app-signatures.js.map +1 -0
- package/dist/data/c2-signatures.d.ts +54 -0
- package/dist/data/c2-signatures.d.ts.map +1 -0
- package/dist/data/c2-signatures.js +256 -0
- package/dist/data/c2-signatures.js.map +1 -0
- package/dist/data/cloud-ranges.d.ts +34 -0
- package/dist/data/cloud-ranges.d.ts.map +1 -0
- package/dist/data/cloud-ranges.js +628 -0
- package/dist/data/cloud-ranges.js.map +1 -0
- package/dist/data/cookie-patterns.d.ts +28 -0
- package/dist/data/cookie-patterns.d.ts.map +1 -0
- package/dist/data/cookie-patterns.js +225 -0
- package/dist/data/cookie-patterns.js.map +1 -0
- package/dist/data/error-signatures.d.ts +19 -0
- package/dist/data/error-signatures.d.ts.map +1 -0
- package/dist/data/error-signatures.js +321 -0
- package/dist/data/error-signatures.js.map +1 -0
- package/dist/data/favicon-hashes.d.ts +25 -0
- package/dist/data/favicon-hashes.d.ts.map +1 -0
- package/dist/data/favicon-hashes.js +249 -0
- package/dist/data/favicon-hashes.js.map +1 -0
- package/dist/data/h2-signatures.d.ts +50 -0
- package/dist/data/h2-signatures.d.ts.map +1 -0
- package/dist/data/h2-signatures.js +211 -0
- package/dist/data/h2-signatures.js.map +1 -0
- package/dist/data/header-order.d.ts +38 -0
- package/dist/data/header-order.d.ts.map +1 -0
- package/dist/data/header-order.js +185 -0
- package/dist/data/header-order.js.map +1 -0
- package/dist/data/jarm-signatures.d.ts +25 -0
- package/dist/data/jarm-signatures.d.ts.map +1 -0
- package/dist/data/jarm-signatures.js +213 -0
- package/dist/data/jarm-signatures.js.map +1 -0
- package/dist/data/saas-patterns.d.ts +23 -0
- package/dist/data/saas-patterns.d.ts.map +1 -0
- package/dist/data/saas-patterns.js +139 -0
- package/dist/data/saas-patterns.js.map +1 -0
- package/dist/data/sensitive-paths.d.ts +12 -0
- package/dist/data/sensitive-paths.d.ts.map +1 -0
- package/dist/data/sensitive-paths.js +1539 -0
- package/dist/data/sensitive-paths.js.map +1 -0
- package/dist/data/service-banners.d.ts +59 -0
- package/dist/data/service-banners.d.ts.map +1 -0
- package/dist/data/service-banners.js +323 -0
- package/dist/data/service-banners.js.map +1 -0
- package/dist/data/smtp-signatures.d.ts +12 -0
- package/dist/data/smtp-signatures.d.ts.map +1 -0
- package/dist/data/smtp-signatures.js +350 -0
- package/dist/data/smtp-signatures.js.map +1 -0
- package/dist/data/takeover-patterns.d.ts +37 -0
- package/dist/data/takeover-patterns.d.ts.map +1 -0
- package/dist/data/takeover-patterns.js +249 -0
- package/dist/data/takeover-patterns.js.map +1 -0
- package/dist/data/tech-patterns.d.ts +44 -0
- package/dist/data/tech-patterns.d.ts.map +1 -0
- package/dist/data/tech-patterns.js +690 -0
- package/dist/data/tech-patterns.js.map +1 -0
- package/dist/data/waf-signatures.d.ts +21 -0
- package/dist/data/waf-signatures.d.ts.map +1 -0
- package/dist/data/waf-signatures.js +318 -0
- package/dist/data/waf-signatures.js.map +1 -0
- package/dist/dns/index.d.ts +3 -0
- package/dist/dns/index.d.ts.map +1 -0
- package/dist/dns/index.js +1067 -0
- package/dist/dns/index.js.map +1 -0
- package/dist/enum/index.d.ts +3 -0
- package/dist/enum/index.d.ts.map +1 -0
- package/dist/enum/index.js +818 -0
- package/dist/enum/index.js.map +1 -0
- package/dist/h2/index.d.ts +3 -0
- package/dist/h2/index.d.ts.map +1 -0
- package/dist/h2/index.js +414 -0
- package/dist/h2/index.js.map +1 -0
- package/dist/http/index.d.ts +3 -0
- package/dist/http/index.d.ts.map +1 -0
- package/dist/http/index.js +2444 -0
- package/dist/http/index.js.map +1 -0
- package/dist/identify/index.d.ts +3 -0
- package/dist/identify/index.d.ts.map +1 -0
- package/dist/identify/index.js +447 -0
- package/dist/identify/index.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +165 -0
- package/dist/index.js.map +1 -0
- package/dist/infra/index.d.ts +3 -0
- package/dist/infra/index.d.ts.map +1 -0
- package/dist/infra/index.js +989 -0
- package/dist/infra/index.js.map +1 -0
- package/dist/iot/index.d.ts +3 -0
- package/dist/iot/index.d.ts.map +1 -0
- package/dist/iot/index.js +610 -0
- package/dist/iot/index.js.map +1 -0
- package/dist/meta/index.d.ts +3 -0
- package/dist/meta/index.d.ts.map +1 -0
- package/dist/meta/index.js +442 -0
- package/dist/meta/index.js.map +1 -0
- package/dist/osint/index.d.ts +3 -0
- package/dist/osint/index.d.ts.map +1 -0
- package/dist/osint/index.js +687 -0
- package/dist/osint/index.js.map +1 -0
- package/dist/passive/index.d.ts +3 -0
- package/dist/passive/index.d.ts.map +1 -0
- package/dist/passive/index.js +944 -0
- package/dist/passive/index.js.map +1 -0
- package/dist/path/index.d.ts +3 -0
- package/dist/path/index.d.ts.map +1 -0
- package/dist/path/index.js +878 -0
- package/dist/path/index.js.map +1 -0
- package/dist/protocol/mcp-server.d.ts +4 -0
- package/dist/protocol/mcp-server.d.ts.map +1 -0
- package/dist/protocol/mcp-server.js +32 -0
- package/dist/protocol/mcp-server.js.map +1 -0
- package/dist/protocol/tools.d.ts +3 -0
- package/dist/protocol/tools.d.ts.map +1 -0
- package/dist/protocol/tools.js +5 -0
- package/dist/protocol/tools.js.map +1 -0
- package/dist/service/index.d.ts +3 -0
- package/dist/service/index.d.ts.map +1 -0
- package/dist/service/index.js +1053 -0
- package/dist/service/index.js.map +1 -0
- package/dist/smtp/index.d.ts +3 -0
- package/dist/smtp/index.d.ts.map +1 -0
- package/dist/smtp/index.js +437 -0
- package/dist/smtp/index.js.map +1 -0
- package/dist/ssh/index.d.ts +3 -0
- package/dist/ssh/index.d.ts.map +1 -0
- package/dist/ssh/index.js +676 -0
- package/dist/ssh/index.js.map +1 -0
- package/dist/tcp/index.d.ts +3 -0
- package/dist/tcp/index.d.ts.map +1 -0
- package/dist/tcp/index.js +369 -0
- package/dist/tcp/index.js.map +1 -0
- package/dist/timing/index.d.ts +3 -0
- package/dist/timing/index.d.ts.map +1 -0
- package/dist/timing/index.js +425 -0
- package/dist/timing/index.js.map +1 -0
- package/dist/tls/index.d.ts +3 -0
- package/dist/tls/index.d.ts.map +1 -0
- package/dist/tls/index.js +1332 -0
- package/dist/tls/index.js.map +1 -0
- package/dist/types/index.d.ts +26 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +8 -0
- package/dist/types/index.js.map +1 -0
- package/dist/utils/cache.d.ts +11 -0
- package/dist/utils/cache.d.ts.map +1 -0
- package/dist/utils/cache.js +35 -0
- package/dist/utils/cache.js.map +1 -0
- package/dist/utils/murmurhash3.d.ts +3 -0
- package/dist/utils/murmurhash3.d.ts.map +1 -0
- package/dist/utils/murmurhash3.js +57 -0
- package/dist/utils/murmurhash3.js.map +1 -0
- package/dist/utils/rate-limiter.d.ts +10 -0
- package/dist/utils/rate-limiter.d.ts.map +1 -0
- package/dist/utils/rate-limiter.js +35 -0
- package/dist/utils/rate-limiter.js.map +1 -0
- package/dist/utils/require-key.d.ts +2 -0
- package/dist/utils/require-key.d.ts.map +1 -0
- package/dist/utils/require-key.js +8 -0
- package/dist/utils/require-key.js.map +1 -0
- package/dist/waf/index.d.ts +3 -0
- package/dist/waf/index.d.ts.map +1 -0
- package/dist/waf/index.js +767 -0
- package/dist/waf/index.js.map +1 -0
- package/dist/web/index.d.ts +3 -0
- package/dist/web/index.d.ts.map +1 -0
- package/dist/web/index.js +1366 -0
- package/dist/web/index.js.map +1 -0
- package/package.json +66 -0
|
@@ -0,0 +1,425 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { RateLimiter } from "../utils/rate-limiter.js";
|
|
3
|
+
import { json } from "../types/index.js";
|
|
4
|
+
const limiter = new RateLimiter(100);
|
|
5
|
+
// ─── Helpers ───
|
|
6
|
+
const REQUEST_TIMEOUT = 15_000;
|
|
7
|
+
/** Send a single GET request and measure response time. */
|
|
8
|
+
async function measureRequest(url, index) {
|
|
9
|
+
const start = performance.now();
|
|
10
|
+
try {
|
|
11
|
+
const controller = new AbortController();
|
|
12
|
+
const timeout = setTimeout(() => controller.abort(), REQUEST_TIMEOUT);
|
|
13
|
+
const response = await fetch(url, {
|
|
14
|
+
method: "GET",
|
|
15
|
+
signal: controller.signal,
|
|
16
|
+
redirect: "follow",
|
|
17
|
+
headers: {
|
|
18
|
+
"User-Agent": "fingerprint-mcp/timing-baseline",
|
|
19
|
+
Accept: "*/*",
|
|
20
|
+
},
|
|
21
|
+
});
|
|
22
|
+
clearTimeout(timeout);
|
|
23
|
+
// Consume body to ensure full response is received
|
|
24
|
+
await response.arrayBuffer();
|
|
25
|
+
const elapsed = performance.now() - start;
|
|
26
|
+
return {
|
|
27
|
+
index,
|
|
28
|
+
responseTimeMs: Math.round(elapsed * 100) / 100,
|
|
29
|
+
statusCode: response.status,
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
catch (err) {
|
|
33
|
+
const elapsed = performance.now() - start;
|
|
34
|
+
return {
|
|
35
|
+
index,
|
|
36
|
+
responseTimeMs: Math.round(elapsed * 100) / 100,
|
|
37
|
+
statusCode: 0,
|
|
38
|
+
error: err.message,
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
/** Calculate statistical metrics from an array of numbers. */
|
|
43
|
+
function computeStats(values) {
|
|
44
|
+
if (values.length === 0) {
|
|
45
|
+
return { mean: 0, median: 0, min: 0, max: 0, stddev: 0, p95: 0 };
|
|
46
|
+
}
|
|
47
|
+
const sorted = [...values].sort((a, b) => a - b);
|
|
48
|
+
const n = sorted.length;
|
|
49
|
+
const sum = sorted.reduce((a, b) => a + b, 0);
|
|
50
|
+
const mean = sum / n;
|
|
51
|
+
const median = n % 2 === 0
|
|
52
|
+
? (sorted[n / 2 - 1] + sorted[n / 2]) / 2
|
|
53
|
+
: sorted[Math.floor(n / 2)];
|
|
54
|
+
const min = sorted[0];
|
|
55
|
+
const max = sorted[n - 1];
|
|
56
|
+
const variance = sorted.reduce((acc, v) => acc + (v - mean) ** 2, 0) / n;
|
|
57
|
+
const stddev = Math.sqrt(variance);
|
|
58
|
+
const p95Index = Math.ceil(n * 0.95) - 1;
|
|
59
|
+
const p95 = sorted[Math.min(p95Index, n - 1)];
|
|
60
|
+
return {
|
|
61
|
+
mean: Math.round(mean * 100) / 100,
|
|
62
|
+
median: Math.round(median * 100) / 100,
|
|
63
|
+
min: Math.round(min * 100) / 100,
|
|
64
|
+
max: Math.round(max * 100) / 100,
|
|
65
|
+
stddev: Math.round(stddev * 100) / 100,
|
|
66
|
+
p95: Math.round(p95 * 100) / 100,
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
/** Detect bimodal distribution: two clusters of timings with a gap between them. */
|
|
70
|
+
function detectBimodal(values) {
|
|
71
|
+
if (values.length < 4)
|
|
72
|
+
return { bimodal: false };
|
|
73
|
+
const sorted = [...values].sort((a, b) => a - b);
|
|
74
|
+
// Find the largest gap between consecutive sorted values
|
|
75
|
+
let maxGap = 0;
|
|
76
|
+
let gapIndex = 0;
|
|
77
|
+
for (let i = 1; i < sorted.length; i++) {
|
|
78
|
+
const gap = sorted[i] - sorted[i - 1];
|
|
79
|
+
if (gap > maxGap) {
|
|
80
|
+
maxGap = gap;
|
|
81
|
+
gapIndex = i;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
// Consider bimodal if the gap is > 50% of the overall range and both clusters have at least 2 points
|
|
85
|
+
const range = sorted[sorted.length - 1] - sorted[0];
|
|
86
|
+
if (range > 0 && maxGap / range > 0.3 && gapIndex >= 2 && sorted.length - gapIndex >= 2) {
|
|
87
|
+
return {
|
|
88
|
+
bimodal: true,
|
|
89
|
+
clusters: {
|
|
90
|
+
low: sorted.slice(0, gapIndex),
|
|
91
|
+
high: sorted.slice(gapIndex),
|
|
92
|
+
},
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
return { bimodal: false };
|
|
96
|
+
}
|
|
97
|
+
// ─── Tool 1: timing_baseline ───
|
|
98
|
+
async function timingBaseline(args, _ctx) {
|
|
99
|
+
const url = args.url;
|
|
100
|
+
const count = args.count ?? 10;
|
|
101
|
+
await limiter.acquire();
|
|
102
|
+
// Send requests sequentially to get clean timing measurements
|
|
103
|
+
const samples = [];
|
|
104
|
+
for (let i = 0; i < count; i++) {
|
|
105
|
+
const sample = await measureRequest(url, i);
|
|
106
|
+
samples.push(sample);
|
|
107
|
+
}
|
|
108
|
+
const successSamples = samples.filter((s) => !s.error);
|
|
109
|
+
const failedSamples = samples.filter((s) => s.error);
|
|
110
|
+
const times = successSamples.map((s) => s.responseTimeMs);
|
|
111
|
+
if (times.length === 0) {
|
|
112
|
+
return json({
|
|
113
|
+
url,
|
|
114
|
+
requestCount: count,
|
|
115
|
+
error: "All requests failed",
|
|
116
|
+
failures: failedSamples.map((s) => ({ index: s.index, error: s.error })),
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
const stats = computeStats(times);
|
|
120
|
+
// Intelligence analysis
|
|
121
|
+
const intelligence = {
|
|
122
|
+
hostingType: "unknown",
|
|
123
|
+
confidence: "low",
|
|
124
|
+
indicators: [],
|
|
125
|
+
};
|
|
126
|
+
// Stddev-based hosting type detection
|
|
127
|
+
if (stats.stddev < 5) {
|
|
128
|
+
intelligence.hostingType = "dedicated / bare metal";
|
|
129
|
+
intelligence.confidence = "medium";
|
|
130
|
+
intelligence.indicators.push(`Very low timing variance (stddev: ${stats.stddev}ms) suggests dedicated infrastructure`);
|
|
131
|
+
}
|
|
132
|
+
else if (stats.stddev < 25) {
|
|
133
|
+
intelligence.hostingType = "shared hosting / cloud VM";
|
|
134
|
+
intelligence.confidence = "medium";
|
|
135
|
+
intelligence.indicators.push(`Moderate timing variance (stddev: ${stats.stddev}ms) typical of shared/cloud hosting`);
|
|
136
|
+
}
|
|
137
|
+
else {
|
|
138
|
+
intelligence.hostingType = "heavily shared / CDN edge";
|
|
139
|
+
intelligence.confidence = "medium";
|
|
140
|
+
intelligence.indicators.push(`High timing variance (stddev: ${stats.stddev}ms) suggests heavily shared infrastructure or CDN edge variation`);
|
|
141
|
+
}
|
|
142
|
+
// Cold start detection (serverless)
|
|
143
|
+
if (times.length >= 3) {
|
|
144
|
+
const firstTime = times[0];
|
|
145
|
+
const restAvg = times.slice(1).reduce((a, b) => a + b, 0) / (times.length - 1);
|
|
146
|
+
if (firstTime > restAvg * 2 && firstTime - restAvg > 100) {
|
|
147
|
+
intelligence.hostingType = "serverless (Lambda / Cloud Functions)";
|
|
148
|
+
intelligence.confidence = "high";
|
|
149
|
+
intelligence.indicators.push(`First request (${firstTime.toFixed(1)}ms) is ${(firstTime / restAvg).toFixed(1)}x slower than average of subsequent requests (${restAvg.toFixed(1)}ms) — cold start pattern`);
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
// Bimodal distribution detection
|
|
153
|
+
const bimodal = detectBimodal(times);
|
|
154
|
+
if (bimodal.bimodal && bimodal.clusters) {
|
|
155
|
+
const lowStats = computeStats(bimodal.clusters.low);
|
|
156
|
+
const highStats = computeStats(bimodal.clusters.high);
|
|
157
|
+
intelligence.indicators.push(`Bimodal distribution detected: cluster A (${bimodal.clusters.low.length} requests, avg ${lowStats.mean}ms) and cluster B (${bimodal.clusters.high.length} requests, avg ${highStats.mean}ms) — possible load balancer with different backends`);
|
|
158
|
+
intelligence.hostingType = "load-balanced (multiple backends)";
|
|
159
|
+
intelligence.confidence = "high";
|
|
160
|
+
}
|
|
161
|
+
// Consistent response times suggest caching
|
|
162
|
+
if (stats.stddev < 2 && stats.mean < 50) {
|
|
163
|
+
intelligence.indicators.push("Very consistent low response times suggest aggressive caching (CDN or reverse proxy cache)");
|
|
164
|
+
}
|
|
165
|
+
return json({
|
|
166
|
+
url,
|
|
167
|
+
requestCount: count,
|
|
168
|
+
successCount: successSamples.length,
|
|
169
|
+
failedCount: failedSamples.length,
|
|
170
|
+
samples: samples.map((s) => ({
|
|
171
|
+
index: s.index,
|
|
172
|
+
responseTimeMs: s.responseTimeMs,
|
|
173
|
+
statusCode: s.statusCode,
|
|
174
|
+
error: s.error,
|
|
175
|
+
})),
|
|
176
|
+
statistics: stats,
|
|
177
|
+
intelligence,
|
|
178
|
+
failures: failedSamples.length > 0
|
|
179
|
+
? failedSamples.map((s) => ({ index: s.index, error: s.error }))
|
|
180
|
+
: undefined,
|
|
181
|
+
});
|
|
182
|
+
}
|
|
183
|
+
// ─── Tool 2: timing_auth ───
|
|
184
|
+
const DEFAULT_VALID_USERNAMES = ["admin", "root", "user"];
|
|
185
|
+
const INVALID_USERNAME = "xyzrandom_nonexistent_user_1928374650";
|
|
186
|
+
const AUTH_ROUNDS = 5;
|
|
187
|
+
const WRONG_PASSWORD = "wrongpassword_timing_test_12345";
|
|
188
|
+
/** Send a login request (POST or GET) with given credentials. */
|
|
189
|
+
async function sendLoginRequest(url, usernameField, passwordField, username, password, method) {
|
|
190
|
+
const start = performance.now();
|
|
191
|
+
try {
|
|
192
|
+
const controller = new AbortController();
|
|
193
|
+
const timeout = setTimeout(() => controller.abort(), REQUEST_TIMEOUT);
|
|
194
|
+
let response;
|
|
195
|
+
if (method === "POST") {
|
|
196
|
+
const body = new URLSearchParams();
|
|
197
|
+
body.set(usernameField, username);
|
|
198
|
+
body.set(passwordField, password);
|
|
199
|
+
response = await fetch(url, {
|
|
200
|
+
method: "POST",
|
|
201
|
+
body: body.toString(),
|
|
202
|
+
signal: controller.signal,
|
|
203
|
+
redirect: "follow",
|
|
204
|
+
headers: {
|
|
205
|
+
"Content-Type": "application/x-www-form-urlencoded",
|
|
206
|
+
"User-Agent": "fingerprint-mcp/timing-auth",
|
|
207
|
+
Accept: "*/*",
|
|
208
|
+
},
|
|
209
|
+
});
|
|
210
|
+
}
|
|
211
|
+
else {
|
|
212
|
+
const params = new URLSearchParams();
|
|
213
|
+
params.set(usernameField, username);
|
|
214
|
+
params.set(passwordField, password);
|
|
215
|
+
const separator = url.includes("?") ? "&" : "?";
|
|
216
|
+
response = await fetch(`${url}${separator}${params.toString()}`, {
|
|
217
|
+
method: "GET",
|
|
218
|
+
signal: controller.signal,
|
|
219
|
+
redirect: "follow",
|
|
220
|
+
headers: {
|
|
221
|
+
"User-Agent": "fingerprint-mcp/timing-auth",
|
|
222
|
+
Accept: "*/*",
|
|
223
|
+
},
|
|
224
|
+
});
|
|
225
|
+
}
|
|
226
|
+
clearTimeout(timeout);
|
|
227
|
+
await response.arrayBuffer();
|
|
228
|
+
const elapsed = performance.now() - start;
|
|
229
|
+
return {
|
|
230
|
+
responseTimeMs: Math.round(elapsed * 100) / 100,
|
|
231
|
+
statusCode: response.status,
|
|
232
|
+
};
|
|
233
|
+
}
|
|
234
|
+
catch (err) {
|
|
235
|
+
const elapsed = performance.now() - start;
|
|
236
|
+
return {
|
|
237
|
+
responseTimeMs: Math.round(elapsed * 100) / 100,
|
|
238
|
+
statusCode: 0,
|
|
239
|
+
error: err.message,
|
|
240
|
+
};
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
async function timingAuth(args, _ctx) {
|
|
244
|
+
const url = args.url;
|
|
245
|
+
const usernameField = args.usernameField ?? "username";
|
|
246
|
+
const passwordField = args.passwordField ?? "password";
|
|
247
|
+
const validUsernames = args.validUsernames ?? DEFAULT_VALID_USERNAMES;
|
|
248
|
+
const method = (args.method ?? "POST");
|
|
249
|
+
await limiter.acquire();
|
|
250
|
+
const allSamples = [];
|
|
251
|
+
// Test each valid username
|
|
252
|
+
for (const username of validUsernames) {
|
|
253
|
+
for (let round = 0; round < AUTH_ROUNDS; round++) {
|
|
254
|
+
const result = await sendLoginRequest(url, usernameField, passwordField, username, WRONG_PASSWORD, method);
|
|
255
|
+
allSamples.push({
|
|
256
|
+
username,
|
|
257
|
+
round,
|
|
258
|
+
responseTimeMs: result.responseTimeMs,
|
|
259
|
+
statusCode: result.statusCode,
|
|
260
|
+
error: result.error,
|
|
261
|
+
});
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
// Test invalid username
|
|
265
|
+
const invalidSamples = [];
|
|
266
|
+
for (let round = 0; round < AUTH_ROUNDS; round++) {
|
|
267
|
+
const result = await sendLoginRequest(url, usernameField, passwordField, INVALID_USERNAME, WRONG_PASSWORD, method);
|
|
268
|
+
invalidSamples.push({
|
|
269
|
+
username: INVALID_USERNAME,
|
|
270
|
+
round,
|
|
271
|
+
responseTimeMs: result.responseTimeMs,
|
|
272
|
+
statusCode: result.statusCode,
|
|
273
|
+
error: result.error,
|
|
274
|
+
});
|
|
275
|
+
}
|
|
276
|
+
allSamples.push(...invalidSamples);
|
|
277
|
+
// Analysis: compare timing per username vs invalid
|
|
278
|
+
const invalidTimes = invalidSamples
|
|
279
|
+
.filter((s) => !s.error)
|
|
280
|
+
.map((s) => s.responseTimeMs);
|
|
281
|
+
const invalidStats = computeStats(invalidTimes);
|
|
282
|
+
const usernameAnalyses = [];
|
|
283
|
+
for (const username of validUsernames) {
|
|
284
|
+
const userSamples = allSamples
|
|
285
|
+
.filter((s) => s.username === username && !s.error);
|
|
286
|
+
const userTimes = userSamples.map((s) => s.responseTimeMs);
|
|
287
|
+
const userStats = computeStats(userTimes);
|
|
288
|
+
const timeDiff = userStats.mean - invalidStats.mean;
|
|
289
|
+
const percentDiff = invalidStats.mean > 0
|
|
290
|
+
? (timeDiff / invalidStats.mean) * 100
|
|
291
|
+
: 0;
|
|
292
|
+
// Statistical significance: is the difference larger than the noise?
|
|
293
|
+
const combinedStddev = Math.max(userStats.stddev, invalidStats.stddev, 1);
|
|
294
|
+
const zScore = Math.abs(timeDiff) / combinedStddev;
|
|
295
|
+
let significance;
|
|
296
|
+
let enumerable = false;
|
|
297
|
+
if (zScore > 3 && Math.abs(timeDiff) > 10) {
|
|
298
|
+
significance = "high";
|
|
299
|
+
enumerable = true;
|
|
300
|
+
}
|
|
301
|
+
else if (zScore > 2 && Math.abs(timeDiff) > 5) {
|
|
302
|
+
significance = "medium";
|
|
303
|
+
enumerable = true;
|
|
304
|
+
}
|
|
305
|
+
else if (zScore > 1.5 && Math.abs(timeDiff) > 3) {
|
|
306
|
+
significance = "low";
|
|
307
|
+
enumerable = false;
|
|
308
|
+
}
|
|
309
|
+
else {
|
|
310
|
+
significance = "none";
|
|
311
|
+
enumerable = false;
|
|
312
|
+
}
|
|
313
|
+
usernameAnalyses.push({
|
|
314
|
+
username,
|
|
315
|
+
stats: userStats,
|
|
316
|
+
timeDiffFromInvalid: Math.round(timeDiff * 100) / 100,
|
|
317
|
+
percentDiffFromInvalid: Math.round(percentDiff * 100) / 100,
|
|
318
|
+
enumerable,
|
|
319
|
+
significance,
|
|
320
|
+
});
|
|
321
|
+
}
|
|
322
|
+
// Overall vulnerability assessment
|
|
323
|
+
const enumerableUsernames = usernameAnalyses.filter((a) => a.enumerable);
|
|
324
|
+
const hasVulnerability = enumerableUsernames.length > 0;
|
|
325
|
+
const vulnerability = {
|
|
326
|
+
vulnerable: hasVulnerability,
|
|
327
|
+
severity: "none",
|
|
328
|
+
description: "",
|
|
329
|
+
enumerableUsernames: enumerableUsernames.map((a) => a.username),
|
|
330
|
+
recommendations: [],
|
|
331
|
+
};
|
|
332
|
+
if (hasVulnerability) {
|
|
333
|
+
const highSig = enumerableUsernames.filter((a) => a.significance === "high");
|
|
334
|
+
if (highSig.length > 0) {
|
|
335
|
+
vulnerability.severity = "high";
|
|
336
|
+
vulnerability.description =
|
|
337
|
+
`Username enumeration via timing side-channel detected with high confidence. ${highSig.length} username(s) show statistically significant timing differences compared to invalid usernames.`;
|
|
338
|
+
}
|
|
339
|
+
else {
|
|
340
|
+
vulnerability.severity = "medium";
|
|
341
|
+
vulnerability.description =
|
|
342
|
+
`Possible username enumeration via timing side-channel. ${enumerableUsernames.length} username(s) show timing differences that may indicate existence, but significance is moderate.`;
|
|
343
|
+
}
|
|
344
|
+
vulnerability.recommendations = [
|
|
345
|
+
"Implement constant-time comparison for username lookup",
|
|
346
|
+
"Add random delay jitter to authentication responses",
|
|
347
|
+
"Use the same code path for valid and invalid usernames (hash the password regardless)",
|
|
348
|
+
"Consider rate limiting login attempts",
|
|
349
|
+
"Implement account lockout or CAPTCHA after failed attempts",
|
|
350
|
+
];
|
|
351
|
+
}
|
|
352
|
+
else {
|
|
353
|
+
vulnerability.description =
|
|
354
|
+
"No significant timing difference detected between valid and invalid usernames. The application appears resistant to timing-based username enumeration.";
|
|
355
|
+
}
|
|
356
|
+
return json({
|
|
357
|
+
url,
|
|
358
|
+
method,
|
|
359
|
+
usernameField,
|
|
360
|
+
passwordField,
|
|
361
|
+
testedUsernames: [...validUsernames, INVALID_USERNAME],
|
|
362
|
+
rounds: AUTH_ROUNDS,
|
|
363
|
+
invalidBaseline: {
|
|
364
|
+
username: INVALID_USERNAME,
|
|
365
|
+
stats: invalidStats,
|
|
366
|
+
},
|
|
367
|
+
usernameAnalysis: usernameAnalyses.map((a) => ({
|
|
368
|
+
username: a.username,
|
|
369
|
+
meanResponseMs: a.stats.mean,
|
|
370
|
+
stddevMs: a.stats.stddev,
|
|
371
|
+
timeDiffFromInvalidMs: a.timeDiffFromInvalid,
|
|
372
|
+
percentDiffFromInvalid: a.percentDiffFromInvalid,
|
|
373
|
+
significance: a.significance,
|
|
374
|
+
likelyExists: a.enumerable,
|
|
375
|
+
})),
|
|
376
|
+
vulnerability,
|
|
377
|
+
rawSamples: allSamples.map((s) => ({
|
|
378
|
+
username: s.username,
|
|
379
|
+
round: s.round,
|
|
380
|
+
responseTimeMs: s.responseTimeMs,
|
|
381
|
+
statusCode: s.statusCode,
|
|
382
|
+
error: s.error,
|
|
383
|
+
})),
|
|
384
|
+
});
|
|
385
|
+
}
|
|
386
|
+
// ─── Tool Definitions ───
|
|
387
|
+
export const timingTools = [
|
|
388
|
+
{
|
|
389
|
+
name: "timing_baseline",
|
|
390
|
+
description: "Response time analysis for infrastructure fingerprinting. Sends multiple identical GET requests and calculates mean, median, min, max, standard deviation, and p95. Detects hosting type from variance (low stddev = dedicated, medium = cloud, high = shared/CDN), cold start patterns (serverless), and bimodal distribution (load balancer with different backends).",
|
|
391
|
+
schema: {
|
|
392
|
+
url: z.string().url().describe("URL to measure response timing"),
|
|
393
|
+
count: z.number().optional().default(10).describe("Number of requests to send"),
|
|
394
|
+
},
|
|
395
|
+
execute: timingBaseline,
|
|
396
|
+
},
|
|
397
|
+
{
|
|
398
|
+
name: "timing_auth",
|
|
399
|
+
description: "Authentication timing side-channel analysis. Compares response times for likely-valid usernames (admin, root, user) vs clearly-invalid usernames with wrong passwords. Detects username enumeration vulnerabilities when valid usernames take significantly longer due to password hash computation. Uses statistical significance testing (z-score) over multiple rounds for reliable detection.",
|
|
400
|
+
schema: {
|
|
401
|
+
url: z.string().url().describe("Login form URL"),
|
|
402
|
+
usernameField: z
|
|
403
|
+
.string()
|
|
404
|
+
.optional()
|
|
405
|
+
.default("username")
|
|
406
|
+
.describe("Username form field name"),
|
|
407
|
+
passwordField: z
|
|
408
|
+
.string()
|
|
409
|
+
.optional()
|
|
410
|
+
.default("password")
|
|
411
|
+
.describe("Password form field name"),
|
|
412
|
+
validUsernames: z
|
|
413
|
+
.array(z.string())
|
|
414
|
+
.optional()
|
|
415
|
+
.describe("Likely valid usernames to test (default: admin, root, user)"),
|
|
416
|
+
method: z
|
|
417
|
+
.enum(["POST", "GET"])
|
|
418
|
+
.optional()
|
|
419
|
+
.default("POST")
|
|
420
|
+
.describe("HTTP method for login form"),
|
|
421
|
+
},
|
|
422
|
+
execute: timingAuth,
|
|
423
|
+
},
|
|
424
|
+
];
|
|
425
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/timing/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/tls/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAe,MAAM,mBAAmB,CAAC;AAy+C9D,eAAO,MAAM,QAAQ,EAAE,OAAO,EAS7B,CAAC"}
|