@anonympins/fingerprint 0.7.0 → 0.7.2
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/CHANGELOG.md +29 -0
- package/README.md +1 -1
- package/composer.json +8 -1
- package/package.json +1 -1
- package/public/fingerprint-wordpress.zip +0 -0
- package/src/js/build-client.js +8 -10
- package/src/js/fingerprint.builder.js +37 -38
- package/src/js/fingerprint.client.js +1531 -1463
- package/src/js/fingerprint.client.obfuscated.js +1 -0
- package/src/js/fingerprint.js +190 -16
- package/src/js/fingerprint.utils.js +213 -213
- package/src/js/library.js +340 -376
- package/src/js/mongodb-store.js +1 -1
- package/src/js/optimization.worker.js +27 -27
- package/src/js/pow.solver.inline.js +154 -56
- package/src/js/pow.solver.js +180 -92
- package/src/js/pow.worker.js +48 -48
- package/src/js/redis-store.js +1 -1
- package/src/js/tests/fingerprint.client.init.test.js +146 -143
- package/src/js/tests/fingerprint.test.js +124 -10
- package/src/js/tests/ip-reputation.test.js +1 -0
- package/src/js/upow-model-task.js +14 -15
- package/src/php/AutoTuner.php +34 -34
- package/src/php/Challenge/ChallengeUtils.php +57 -11
- package/src/php/Config/SecurityProfiles.php +20 -0
- package/src/php/DirectFingerprint.php +190 -145
- package/src/php/FingerprintBuilder.php +29 -30
- package/src/php/FingerprintClient.php +147 -148
- package/src/php/FingerprintEngine.php +44 -17
- package/src/php/Ja3AnomalyDetector.php +33 -32
- package/src/php/Optimization/FunctionRegistry.php +7 -7
- package/src/php/Optimization/Optimization.php +24 -24
- package/src/php/Optimization/OptimizationOperators.php +26 -25
- package/src/php/Optimization/ProblemInitializers.php +52 -52
- package/src/php/ProblemManager.php +31 -34
- package/src/php/RequestContext.php +8 -1
- package/src/php/Store/IStore.php +7 -8
- package/src/php/Store/InMemoryStore.php +66 -66
- package/src/php/Store/MongoDbStore.php +5 -5
- package/src/php/Store/RedisStore.php +5 -5
- package/src/php/Store/StoreManager.php +35 -35
- package/src/php/Tests/ChallengeUtilsTest.php +453 -453
- package/src/php/Tests/DnsCircuitBreakerTest.php +105 -105
- package/src/php/Tests/FingerprintEngineTest.php +38 -0
- package/src/php/Tests/IpReputationTest.php +10 -0
- package/src/php/Tests/MaliciousPatternsTest.php +103 -103
- package/src/php/Tests/MetricsTest.php +97 -97
- package/src/php/Tests/ProblemManagerTest.php +376 -376
- package/src/php/Tests/QuicFingerprintTest.php +53 -53
- package/src/php/Tests/RequestUtilsTest.php +471 -471
- package/src/php/Tests/TLSClientHelloParserTest.php +177 -177
- package/src/php/Tests/config/ed25519_key.json +3 -3
- package/src/php/Utils/BlockList.php +99 -99
- package/src/php/Utils/Env.php +49 -49
- package/src/php/Utils/MaliciousPatterns.php +74 -74
- package/src/php/Utils/MetricsManager.php +209 -209
- package/src/php/Utils/RequestUtils.php +129 -7
- package/src/php/Utils/TLSClientHelloParser.php +369 -369
- package/src/php/WordPress/WpDbStore.php +155 -0
- package/src/php/WordPress/fingerprint-wordpress.php +554 -0
- package/src/php/WordPress/languages/fingerprint-wordpress-de_DE.mo +0 -0
- package/src/php/WordPress/languages/fingerprint-wordpress-de_DE.po +262 -0
- package/src/php/WordPress/languages/fingerprint-wordpress-fr_FR.mo +0 -0
- package/src/php/WordPress/languages/fingerprint-wordpress-fr_FR.po +268 -0
- package/src/php/WordPress/package.php +218 -0
- package/src/php/bin/auto-tune.php +118 -118
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
<?php
|
|
2
|
+
|
|
3
|
+
declare(strict_types=1);
|
|
4
|
+
|
|
5
|
+
namespace Anonympins\Fingerprint\WordPress;
|
|
6
|
+
|
|
7
|
+
use Anonympins\Fingerprint\Store\IStore;
|
|
8
|
+
|
|
9
|
+
// Polyfill pour ARRAY_A si chargé hors du cycle de vie standard de WordPress
|
|
10
|
+
if (!defined('ARRAY_A')) {
|
|
11
|
+
define('ARRAY_A', 'ARRAY_A');
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Adaptateur IStore persistant pour WordPress exploitant l'objet $wpdb.
|
|
16
|
+
* Permet de stocker les sessions d'appareils, nonces et états de PoW
|
|
17
|
+
* sans dépendre d'une extension mémoire comme Redis ou APCu.
|
|
18
|
+
*/
|
|
19
|
+
class WpDbStore implements IStore
|
|
20
|
+
{
|
|
21
|
+
/** @var \wpdb|object|null */
|
|
22
|
+
private $db;
|
|
23
|
+
private string $table;
|
|
24
|
+
|
|
25
|
+
public function __construct($db = null)
|
|
26
|
+
{
|
|
27
|
+
global $wpdb;
|
|
28
|
+
$this->db = $db ?? $wpdb;
|
|
29
|
+
$prefix = (is_object($this->db) && isset($this->db->prefix)) ? $this->db->prefix : 'wp_';
|
|
30
|
+
$this->table = $prefix . 'fingerprint_store';
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Crée la table de stockage si elle n'existe pas encore.
|
|
35
|
+
*/
|
|
36
|
+
public function ensureTable(): void
|
|
37
|
+
{
|
|
38
|
+
if (!$this->db || !method_exists($this->db, 'get_charset_collate')) {
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
$charsetCollate = $this->db->get_charset_collate();
|
|
43
|
+
$sql = "CREATE TABLE IF NOT EXISTS {$this->table} (
|
|
44
|
+
`key_id` VARCHAR(191) NOT NULL,
|
|
45
|
+
`value` LONGTEXT NOT NULL,
|
|
46
|
+
`expires_at` BIGINT UNSIGNED NULL,
|
|
47
|
+
PRIMARY KEY (`key_id`),
|
|
48
|
+
KEY `expires_idx` (`expires_at`)
|
|
49
|
+
) {$charsetCollate};";
|
|
50
|
+
|
|
51
|
+
// Chargement sécurisé de dbDelta si ABSPATH est présent
|
|
52
|
+
if (!function_exists('dbDelta') && defined('ABSPATH')) {
|
|
53
|
+
$upgradeFile = ABSPATH . 'wp-admin/includes/upgrade.php';
|
|
54
|
+
if (file_exists($upgradeFile)) {
|
|
55
|
+
require_once $upgradeFile;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
if (function_exists('dbDelta')) {
|
|
60
|
+
dbDelta($sql);
|
|
61
|
+
} elseif (method_exists($this->db, 'query')) {
|
|
62
|
+
$this->db->query($sql);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
public function get(string $key)
|
|
67
|
+
{
|
|
68
|
+
if (!$this->db || !method_exists($this->db, 'prepare')) {
|
|
69
|
+
return null;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
$sql = $this->db->prepare(
|
|
73
|
+
"SELECT `value`, `expires_at` FROM {$this->table} WHERE `key_id` = %s",
|
|
74
|
+
$key
|
|
75
|
+
);
|
|
76
|
+
$outputType = defined('ARRAY_A') ? \ARRAY_A : 'ARRAY_A';
|
|
77
|
+
$row = $this->db->get_row($sql, $outputType);
|
|
78
|
+
|
|
79
|
+
if (!$row) {
|
|
80
|
+
return null;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
if ($row['expires_at'] !== null && (int)$row['expires_at'] < time()) {
|
|
84
|
+
$this->delete($key);
|
|
85
|
+
return null;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
$decoded = json_decode((string)$row['value'], true);
|
|
89
|
+
return (json_last_error() === JSON_ERROR_NONE) ? $decoded : $row['value'];
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
public function set(string $key, $value, ?int $ttl = null): void
|
|
93
|
+
{
|
|
94
|
+
if (!$this->db || !method_exists($this->db, 'replace')) {
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
$expiresAt = ($ttl !== null && $ttl > 0) ? (time() + $ttl) : null;
|
|
99
|
+
$serialized = is_scalar($value) && !is_bool($value)
|
|
100
|
+
? (string)$value
|
|
101
|
+
: json_encode($value, JSON_UNESCAPED_SLASHES);
|
|
102
|
+
|
|
103
|
+
$this->db->replace(
|
|
104
|
+
$this->table,
|
|
105
|
+
[
|
|
106
|
+
'key_id' => $key,
|
|
107
|
+
'value' => $serialized,
|
|
108
|
+
'expires_at' => $expiresAt
|
|
109
|
+
],
|
|
110
|
+
['%s', '%s', $expiresAt !== null ? '%d' : null]
|
|
111
|
+
);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
public function has(string $key): bool
|
|
115
|
+
{
|
|
116
|
+
return $this->get($key) !== null;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
public function delete(string $key): void
|
|
120
|
+
{
|
|
121
|
+
if (!$this->db || !method_exists($this->db, 'delete')) {
|
|
122
|
+
return;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
$this->db->delete(
|
|
126
|
+
$this->table,
|
|
127
|
+
['key_id' => $key],
|
|
128
|
+
['%s']
|
|
129
|
+
);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
public function clear(): void
|
|
133
|
+
{
|
|
134
|
+
if (!$this->db || !method_exists($this->db, 'query')) {
|
|
135
|
+
return;
|
|
136
|
+
}
|
|
137
|
+
$this->db->query("TRUNCATE TABLE {$this->table}");
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* Nettoie les lignes expirées (appelé par le WP-Cron périodique).
|
|
142
|
+
*/
|
|
143
|
+
public function pruneExpired(): int
|
|
144
|
+
{
|
|
145
|
+
if (!$this->db || !method_exists($this->db, 'prepare')) {
|
|
146
|
+
return 0;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
$now = time();
|
|
150
|
+
$deleted = $this->db->query(
|
|
151
|
+
$this->db->prepare("DELETE FROM {$this->table} WHERE `expires_at` IS NOT NULL AND `expires_at` < %d", $now)
|
|
152
|
+
);
|
|
153
|
+
return is_numeric($deleted) ? (int)$deleted : 0;
|
|
154
|
+
}
|
|
155
|
+
}
|