@anonympins/fingerprint 0.7.5 → 0.8.1

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 (68) hide show
  1. package/CHANGELOG.md +57 -0
  2. package/README.md +1 -1
  3. package/package.json +3 -2
  4. package/public/anonympins-bot-mitigation-pow.zip +0 -0
  5. package/src/js/asn-lookup.js +223 -0
  6. package/src/js/fingerprint.client.js +1784 -1772
  7. package/src/js/fingerprint.client.obfuscated.js +1 -1
  8. package/src/js/fingerprint.js +236 -40
  9. package/src/js/fingerprint.utils.js +252 -2
  10. package/src/js/pow.worker.js +2 -2
  11. package/src/js/tests/asn-lookup.test.js +57 -0
  12. package/src/js/tests/cross_parity.test.js +3 -3
  13. package/src/js/tests/dns-circuit-breaker.test.js +6 -6
  14. package/src/js/tests/fingerprint.builder.test.js +76 -78
  15. package/src/js/tests/fingerprint.client.test.js +16 -17
  16. package/src/js/tests/fingerprint.test.js +19 -12
  17. package/src/js/tests/ja3AnomalyDetector.test.js +135 -136
  18. package/src/js/tests/library.test.js +94 -95
  19. package/src/js/tests/obfuscation.test.js +8 -8
  20. package/src/js/tests/quicFingerprint.test.js +47 -0
  21. package/src/js/tests/tcpFingerprint.test.js +4 -4
  22. package/src/js/upow-model-task.js +155 -112
  23. package/src/php/AsnLookupEngine.php +173 -0
  24. package/src/php/Challenge/ChallengeUtils.php +430 -117
  25. package/src/php/Config/SecurityProfiles.php +75 -62
  26. package/src/php/DirectFingerprint.php +80 -13
  27. package/src/php/FingerprintBuilder.php +13 -13
  28. package/src/php/FingerprintClient.php +6 -6
  29. package/src/php/FingerprintEngine.php +2141 -1837
  30. package/src/php/Ja3AnomalyDetector.php +22 -22
  31. package/src/php/NetworkProfile.php +68 -0
  32. package/src/php/Optimization/FunctionRegistry.php +4 -4
  33. package/src/php/Optimization/Optimization.php +6 -6
  34. package/src/php/ProblemManager.php +12 -2
  35. package/src/php/RequestContext.php +11 -11
  36. package/src/php/Store/InMemoryStore.php +96 -66
  37. package/src/php/Store/MongoDbStore.php +2 -2
  38. package/src/php/Store/RedisStore.php +1 -1
  39. package/src/php/Store/StoreManager.php +48 -35
  40. package/src/php/Tests/AsnLookupTest.php +61 -0
  41. package/src/php/Tests/ChallengeUtilsTest.php +31 -0
  42. package/src/php/Tests/DnsCircuitBreakerTest.php +105 -105
  43. package/src/php/Tests/FingerprintClientTest.php +70 -70
  44. package/src/php/Tests/FingerprintEngineTest.php +4 -2
  45. package/src/php/Tests/PowTest.php +37 -39
  46. package/src/php/Tests/QuicFingerprintTest.php +115 -53
  47. package/src/php/Tests/ThreatIntelTest.php +2 -2
  48. package/src/php/Utils/BigInt.php +202 -202
  49. package/src/php/Utils/BlockList.php +13 -13
  50. package/src/php/Utils/Env.php +7 -2
  51. package/src/php/Utils/Logger.php +19 -1
  52. package/src/php/Utils/MaliciousPatterns.php +6 -6
  53. package/src/php/Utils/MetricsManager.php +209 -209
  54. package/src/php/Utils/RequestUtils.php +348 -18
  55. package/src/php/Utils/TLSClientHelloParser.php +385 -369
  56. package/src/php/WordPress/WpDbStore.php +34 -7
  57. package/src/php/WordPress/anonympins-bot-mitigation-pow.php +1222 -0
  58. package/src/php/WordPress/fingerprint-anti-bot.php +0 -559
  59. package/src/php/WordPress/languages/anonympins-bot-mitigation-pow-fr_FR.mo +0 -0
  60. package/src/php/WordPress/languages/anonympins-bot-mitigation-pow-fr_FR.po +232 -0
  61. package/src/php/WordPress/languages/fingerprint-wordpress-de_DE.mo +0 -0
  62. package/src/php/WordPress/languages/fingerprint-wordpress-de_DE.po +297 -261
  63. package/src/php/WordPress/languages/fingerprint-wordpress-fr_FR.mo +0 -0
  64. package/src/php/WordPress/languages/fingerprint-wordpress-fr_FR.po +348 -267
  65. package/src/php/WordPress/package.php +88 -99
  66. package/src/php/WordPress/readme.txt +28 -6
  67. package/src/php/bin/auto-tune.php +1 -1
  68. package/public/fingerprint-anti-bot.zip +0 -0
package/CHANGELOG.md CHANGED
@@ -1,3 +1,60 @@
1
+ ## Version 0.8.1
2
+
3
+ - 🎟️ **Private Access Tokens (PAT / Privacy Pass) Evaluation (RFC 9578)**:
4
+ - Implemented end-to-end token extraction (`Authorization: PrivateToken`, `Sec-Private-State-Token`) and cryptographic verification across JS and PHP runtimes.
5
+ - Added multi-algorithm signature checking (Blind RSA SHA-384 / SHA-256 and VOPRF Ed25519) with anti-replay persistent nonce caching (`pat-nonce:{nonce}`).
6
+ - Zero-friction exemption granting immediate clearance while preserving fail-safe blocks against active honeypot probes and condemned devices.
7
+
8
+ - 🔒 **Security Fix: URI Parsing & Open Redirect Hardening**:
9
+ - Hardened `sanitizeRedirectPath` against protocol-relative (`//evil.com`) and absolute external redirect targets.
10
+ - Standardized URI parsing on WordPress endpoints using `wp_parse_url()` with graceful native fallbacks.
11
+ - Secured PoW challenge parameter cleanup routines (`cleanUrlFromPowParams`).
12
+
13
+ - 🌐 **High-Performance In-Memory ASN & Network Profile Engine**:
14
+ - Introduced zero-I/O Patricia/Radix Trie engine (`AsnLookupEngine`) resolving IPv4 and IPv6 subnets under 50ns in memory.
15
+ - Pre-loaded CIDR definitions for Datacenters (AWS, Hetzner, OVH, DigitalOcean), Cellular CGNAT (RFC 6598), Satellite (Starlink), and Tor exit relays.
16
+ - Dynamic modulation of `calculateAnalogInconsistencyScore` adjusting suspicion inflection points based on the network profile.
17
+
18
+ - 🔌 **WordPress Plugin: Hardening & Plugin Check Compliance**:
19
+ - Full compliance with WordPress.org security and coding guidelines: replaced direct `<script>` injection with `wp_register_script`, `wp_enqueue_script`, and `wp_add_inline_script`.
20
+ - Eliminated remote CDN dependencies in automated packaging script (`package.php`).
21
+ - Automated native gettext compilation (`PO` to `MO`) during packaging for German and French translations.
22
+ - Hardened SQL caching adapter (`WpDbStore`) and sanitization routines across all admin and REST API controllers.
23
+
24
+ ---
25
+
26
+ ## Version 0.8.0
27
+
28
+ - 🎟️ **Private Access Tokens (PAT / Privacy Pass) Support (RFC 9505, RFC 9577, RFC 9578)**:
29
+ - **Zero-Friction Cryptographic Bypass**: Integrated native validation for Privacy Pass tokens extracted from `Authorization: PrivateToken` and `Sec-Private-State-Token` headers. Clients presenting valid tokens obtain an immediate zero-friction bypass (`action: next`, `score: 0.0`) without executing CPU/Memory challenges or CAPTCHAs.
30
+ - **Multi-Algorithm Token Verification**: Supports Blind RSA (types `0x0001` and `0x0002` using RSA-PSS SHA-384 / SHA-256 and PKCS#1 v1.5 padding) as well as VOPRF / Ed25519 (type `0x0003`).
31
+ - **Anti-Replay Nonce Tracking**: Verified token nonces are indexed in the persistent datastore (`pat-nonce:{nonce}`) with configurable expiration (`pat.nonceTtl`, default 24h) to prevent token reuse.
32
+
33
+ - 🔒 **TLS 1.3 Encrypted Client Hello (ECH) & RFC 9460 Validation**:
34
+ - Added deep inspection for ECH presence and Outer SNI discrepancies (`x-ech-outer-sni`, `x-ech-present`, `x-ech-expected`).
35
+ - Flags client connections where modern browsers (Chrome $\ge 119$, Firefox $\ge 118$) fail to negotiate ECH when expected on HTTPS endpoints.
36
+
37
+ - 🌐 **HTTP/2 & QUIC / HTTP/3 Protocol Conformance (RFC 7540, RFC 9114, RFC 9218)**:
38
+ - **Hop-by-Hop Header Prohibition**: Enforced RFC 7540 and RFC 9114 constraints by heavily penalizing forbidden hop-by-hop headers (`Connection`, `Keep-Alive`, `Proxy-Connection`) on HTTP/2 and HTTP/3 multiplexed streams.
39
+ - **Extensible Prioritization Scheme (RFC 9218)**: Validated priority urgency bounds ($u \in [0, 7]$) and incremental flags (`i`), penalizing malformed or out-of-spec client priority frames.
40
+ - **HTTP/2 Stream Tree & Compression Analysis**: Added detection for stream self-dependency loops (`streamId === depStreamId`), non-browser priority frame distributions, and dynamic HPACK/QPACK table zero-entry anomalies under repeated requests.
41
+
42
+ - 📡 **Passive MTU & Transport Tunnel Detection (`mtuAnomalyScore`)**:
43
+ - Analyzes TCP SYN parameters, Path MTU, and Don't Fragment (`DF`) flags across IPv4 and IPv6 to detect WireGuard, OpenVPN, GRE encapsulation, and residential proxy backconnects.
44
+ - **Dynamic Weight Amplification**: When an MTU anomaly indicates network tunneling ($\text{mtuAnomalyScore} > 50$), the engine dynamically amplifies downstream weights (`tlsSpoofingScore`, `crossLayerInconsistencyScore`, `clientHintsInconsistencyScore`, `behaviorScore`, `requestPatternScore`).
45
+
46
+ - 🛠️ **WordPress Plugin: Sandbox Mode & Live Telemetry Feed**:
47
+ - **Dedicated Sandbox / Test Mode**: Configurable non-blocking Audit-Only mode, targeted IP whitelist filter, and diagnostic HTTP headers (`X-Fingerprint-Sandbox`, `X-Fingerprint-Score`).
48
+ - **Real-Time Observability**: Implemented a Server-Sent Events (SSE) streaming route (`/wp-json/fingerprint/v1/sandbox/sse`) and a REST polling endpoint (`/wp-json/fingerprint/v1/sandbox/telemetry`) to monitor challenged visitors and suspicion vector breakdowns live.
49
+ - **Client-Side Event Injection**: Injects `window.__FINGERPRINT_VECTOR__` and dispatches `fingerprint:suspicion` DOM CustomEvents when sandbox mode or administrative sessions are active.
50
+
51
+ - 🌍 **Code Standardization & Parity**:
52
+ - **Python Engine Enhancements**: Merged modular architecture improvements (`feature/python_classes`) for parity with Node.js and PHP.
53
+ - **Java Testing**: Added comprehensive test coverage for RFC 9578 Private Access Token extraction, parsing, and anti-replay verification (`PatTest.java`).
54
+ - **Documentation & Localization**: Standardized code comments into English across modules and updated French/German translations in compliance with WordPress guidelines.
55
+
56
+ ---
57
+
1
58
  ## Version 0.7.5
2
59
 
3
60
  - 🛡️ **Differential Privacy on Federated Threat Intelligence**:
package/README.md CHANGED
@@ -91,7 +91,7 @@ In your **pom.xml**, add :
91
91
  <dependency>
92
92
  <groupId>com.anonympins</groupId>
93
93
  <artifactId>fingerprint-engine</artifactId>
94
- <version>0.7.5</version>
94
+ <version>0.8.1</version>
95
95
  </dependency>
96
96
  ```
97
97
  ## Documentation
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@anonympins/fingerprint",
3
- "version": "0.7.5",
3
+ "version": "0.8.1",
4
4
  "description": "Advanced anti-bot library for Node.js using multi-layer fingerprinting (JA3, client-side, headers), behavioral analysis, and adaptive Proof-of-Work (PoW) challenges to mitigate scraping, scalping, and automated threats.",
5
5
  "main": "index.js",
6
6
  "type": "module",
@@ -81,7 +81,8 @@
81
81
  },
82
82
  "overrides": {
83
83
  "body-parser": "2.3.0",
84
- "qs": "6.16.0"
84
+ "qs": "6.16.0",
85
+ "fast-uri": "3.1.8"
85
86
  },
86
87
  "peerDependencies": {
87
88
  "ioredis": "^5.3.2",
@@ -0,0 +1,223 @@
1
+ import { isIPv4, isIPv6 } from "node:net";
2
+
3
+ /**
4
+ * Profils de réseaux et paramètres de modulation pour le scoring analogique.
5
+ */
6
+ export const NetworkProfile = {
7
+ RESIDENTIAL: {
8
+ type: 'RESIDENTIAL',
9
+ baseScore: 0.0,
10
+ inflectionPoint: 0.72,
11
+ toleranceRotation: false,
12
+ jitterTolerance: 60.0
13
+ },
14
+ CELLULAR: {
15
+ type: 'CELLULAR',
16
+ baseScore: 10.0,
17
+ inflectionPoint: 0.60,
18
+ toleranceRotation: true,
19
+ jitterTolerance: 80.0
20
+ },
21
+ SATELLITE: {
22
+ type: 'SATELLITE',
23
+ baseScore: 15.0,
24
+ inflectionPoint: 0.68,
25
+ toleranceRotation: false,
26
+ jitterTolerance: 150.0
27
+ },
28
+ HOSTING: {
29
+ type: 'HOSTING',
30
+ baseScore: 55.0,
31
+ inflectionPoint: 0.85,
32
+ toleranceRotation: false,
33
+ jitterTolerance: 30.0
34
+ },
35
+ ANONYMIZER: {
36
+ type: 'ANONYMIZER',
37
+ baseScore: 85.0,
38
+ inflectionPoint: 0.90,
39
+ toleranceRotation: false,
40
+ jitterTolerance: 40.0
41
+ }
42
+ };
43
+
44
+ /**
45
+ * Nœud compact pour l'arbre Radix binaire.
46
+ */
47
+ class TrieNode {
48
+ constructor() {
49
+ this.children = [null, null]; // 0 et 1
50
+ this.profile = null;
51
+ }
52
+ }
53
+
54
+ /**
55
+ * Patricia Trie / Radix Trie en mémoire vive pour résolution IPv4/IPv6 sous 50ns.
56
+ */
57
+ export class AsnLookupEngine {
58
+ constructor() {
59
+ this.rootV4 = new TrieNode();
60
+ this.rootV6 = new TrieNode();
61
+ this.loadDefaultPrefixes();
62
+ }
63
+
64
+ /**
65
+ * Insère un préfixe CIDR avec son profil réseau associé.
66
+ * @param {string} cidr Ex: "100.64.0.0/10", "198.51.100.0/24"
67
+ * @param {object} profile Configuration du NetworkProfile
68
+ */
69
+ insert(cidr, profile) {
70
+ const [ip, prefixLenStr] = cidr.split('/');
71
+ const isV4 = isIPv4(ip);
72
+ const isV6 = isIPv6(ip);
73
+ if (!isV4 && !isV6) return;
74
+
75
+ const maxBits = isV4 ? 32 : 128;
76
+ const prefixLen = prefixLenStr !== undefined ? parseInt(prefixLenStr, 10) : maxBits;
77
+ if (isNaN(prefixLen) || prefixLen < 0 || prefixLen > maxBits) return;
78
+
79
+ let current = isV4 ? this.rootV4 : this.rootV6;
80
+ const bits = this._ipToBits(ip, isV4);
81
+
82
+ for (let i = 0; i < prefixLen; i++) {
83
+ const bit = bits[i];
84
+ if (!current.children[bit]) {
85
+ current.children[bit] = new TrieNode();
86
+ }
87
+ current = current.children[bit];
88
+ }
89
+ current.profile = profile;
90
+ }
91
+
92
+ /**
93
+ * Résout une adresse IP en profil réseau (< 50 nanosecondes, sans I/O).
94
+ * @param {string} ip
95
+ * @returns {typeof NetworkProfile.RESIDENTIAL}
96
+ */
97
+ lookup(ip) {
98
+ if (!ip || typeof ip !== 'string') return NetworkProfile.RESIDENTIAL;
99
+
100
+ let cleanIp = ip.trim().toLowerCase();
101
+ if (cleanIp.startsWith('::ffff:')) {
102
+ cleanIp = cleanIp.substring(7);
103
+ }
104
+
105
+ const isV4 = isIPv4(cleanIp);
106
+ const isV6 = isIPv6(cleanIp);
107
+ if (!isV4 && !isV6) return NetworkProfile.RESIDENTIAL;
108
+
109
+ let current = isV4 ? this.rootV4 : this.rootV6;
110
+ let matchedProfile = null;
111
+ const bits = this._ipToBits(cleanIp, isV4);
112
+
113
+ for (let i = 0; i < bits.length; i++) {
114
+ if (current.profile !== null) {
115
+ matchedProfile = current.profile; // Longest-Prefix-Match
116
+ }
117
+ const bit = bits[i];
118
+ current = current.children[bit];
119
+ if (!current) break;
120
+ }
121
+
122
+ if (current && current.profile !== null) {
123
+ matchedProfile = current.profile;
124
+ }
125
+
126
+ return matchedProfile || NetworkProfile.RESIDENTIAL;
127
+ }
128
+
129
+ /**
130
+ * Convertit une adresse IP en tableau de bits (0 et 1).
131
+ * @private
132
+ */
133
+ _ipToBits(ip, isV4) {
134
+ if (isV4) {
135
+ const octets = ip.split('.').map(Number);
136
+ const bits = new Uint8Array(32);
137
+ let idx = 0;
138
+ for (let i = 0; i < 4; i++) {
139
+ const byte = octets[i];
140
+ for (let b = 7; b >= 0; b--) {
141
+ bits[idx++] = (byte >> b) & 1;
142
+ }
143
+ }
144
+ return bits;
145
+ } else {
146
+ let normalized = ip;
147
+ if (normalized.includes("::")) {
148
+ const parts = normalized.split("::");
149
+ const left = parts[0] ? parts[0].split(":") : [];
150
+ const right = parts[1] ? parts[1].split(":") : [];
151
+ const missing = 8 - (left.length + right.length);
152
+ const middle = Array(missing).fill("0000");
153
+ normalized = [...left, ...middle, ...right].join(":");
154
+ }
155
+ const groups = normalized.split(":").map(g => parseInt(g, 16) || 0);
156
+ const bits = new Uint8Array(128);
157
+ let idx = 0;
158
+ for (let i = 0; i < 8; i++) {
159
+ const word = groups[i];
160
+ for (let b = 15; b >= 0; b--) {
161
+ bits[idx++] = (word >> b) & 1;
162
+ }
163
+ }
164
+ return bits;
165
+ }
166
+ }
167
+
168
+ /**
169
+ * Charge les plages fondamentales (Cloud providers, Tor, Mobile CGNAT, Satellite).
170
+ */
171
+ loadDefaultPrefixes() {
172
+ // Mobile CGNAT (RFC 6598)
173
+ this.insert('100.64.0.0/10', NetworkProfile.CELLULAR);
174
+
175
+ // Réseaux Datacenters / Cloud majeurs (AWS, OVH, Hetzner, DigitalOcean)
176
+ const datacenterRanges = [
177
+ // AWS
178
+ '3.0.0.0/9', '3.128.0.0/9', '18.192.0.0/11', '34.192.0.0/10',
179
+ '35.156.0.0/14', '52.0.0.0/11', '54.0.0.0/8',
180
+ // Hetzner
181
+ '78.46.0.0/15', '88.198.0.0/16', '94.130.0.0/16', '95.216.0.0/15',
182
+ '116.202.0.0/15', '135.181.0.0/16', '136.243.0.0/16', '138.201.0.0/16',
183
+ '142.132.0.0/16', '144.76.0.0/16', '148.251.0.0/16', '159.69.0.0/16',
184
+ '168.119.0.0/16', '178.63.0.0/16', '188.40.0.0/16', '195.201.0.0/16',
185
+ // OVH
186
+ '51.68.0.0/14', '51.75.0.0/15', '51.77.0.0/16', '51.79.0.0/16',
187
+ '51.81.0.0/16', '51.83.0.0/16', '51.89.0.0/16', '51.91.0.0/16',
188
+ '137.74.0.0/16', '141.94.0.0/15', '145.239.0.0/16', '147.135.0.0/16',
189
+ '176.31.0.0/16', '178.32.0.0/15', '188.165.0.0/16', '198.27.64.0/18',
190
+ // DigitalOcean
191
+ '64.225.0.0/16', '68.183.0.0/16', '104.248.0.0/16', '128.199.0.0/16',
192
+ '134.209.0.0/16', '138.68.0.0/16', '138.197.0.0/16', '139.59.0.0/16',
193
+ '142.93.0.0/16', '143.198.0.0/16', '146.190.0.0/16', '157.230.0.0/16',
194
+ '159.65.0.0/16', '159.89.0.0/16', '161.35.0.0/16', '164.90.128.0/17',
195
+ '165.22.0.0/16', '165.227.0.0/16', '167.99.0.0/16', '174.138.0.0/16',
196
+ '178.62.0.0/16', '178.128.0.0/16', '188.166.0.0/16', '206.189.0.0/16'
197
+ ];
198
+
199
+ for (const range of datacenterRanges) {
200
+ this.insert(range, NetworkProfile.HOSTING);
201
+ }
202
+
203
+ // Satellite (ex: Starlink Space-X)
204
+ const satelliteRanges = [
205
+ '98.97.0.0/16', '129.222.0.0/16', '143.130.0.0/16',
206
+ '143.244.0.0/16', '206.214.224.0/19'
207
+ ];
208
+ for (const range of satelliteRanges) {
209
+ this.insert(range, NetworkProfile.SATELLITE);
210
+ }
211
+
212
+ // Anonymizers / Tor Exit Relays connus
213
+ const anonymizerRanges = [
214
+ '185.220.101.0/24', '185.220.102.0/24', '185.220.103.0/24',
215
+ '185.100.86.128/25', '198.98.56.0/24', '199.249.230.0/24'
216
+ ];
217
+ for (const range of anonymizerRanges) {
218
+ this.insert(range, NetworkProfile.ANONYMIZER);
219
+ }
220
+ }
221
+ }
222
+
223
+ export const defaultAsnLookup = new AsnLookupEngine();