@anonympins/fingerprint 0.6.0 → 0.6.3
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 +28 -0
- package/README.md +128 -119
- package/composer.json +2 -1
- package/package.json +1 -1
- package/public/fp.js +1 -1
- package/public/fp.wasm +0 -0
- package/src/js/build-client.js +1 -1
- package/src/js/fingerprint.client.js +2 -0
- package/src/js/fingerprint.client.obfuscated.js +1 -1
- package/src/js/fingerprint.js +6802 -6411
- package/src/js/library.js +18 -11
- package/src/js/problem-manager.js +6 -2
- package/src/js/tests/cross_parity.test.js +17 -11
- package/src/js/tests/fingerprint.test.js +47 -10
- package/src/js/tests/metrics.test.js +157 -103
- package/src/php/Challenge/ChallengeUtils.php +69 -6
- package/src/php/Config/SecurityProfiles.php +3 -2
- package/src/php/FingerprintEngine.php +154 -21
- package/src/php/Optimization/OptimizationOperators.php +21 -21
- package/src/php/RequestContext.php +5 -0
- package/src/php/Tests/ChallengeUtilsTest.php +6 -4
- package/src/php/Tests/FingerprintEngineTest.php +186 -0
- package/src/php/Tests/MetricsTest.php +97 -45
- package/src/php/Tests/RequestUtilsTest.php +14 -14
- package/src/php/Tests/config/ed25519_key.json +4 -0
- package/src/php/Utils/Env.php +50 -0
- package/src/php/Utils/MetricsManager.php +209 -166
- package/src/php/Utils/RequestUtils.php +70 -14
|
@@ -1025,7 +1025,13 @@ class RequestUtils
|
|
|
1025
1025
|
|
|
1026
1026
|
public static function getThreatIntelScore(RequestContext $context, array $threatIntelConfig): array
|
|
1027
1027
|
{
|
|
1028
|
-
|
|
1028
|
+
$zkpY = $context->zkpY;
|
|
1029
|
+
if (empty($zkpY)) {
|
|
1030
|
+
return ['threatIntelScore' => 0.0];
|
|
1031
|
+
}
|
|
1032
|
+
$store = StoreManager::getStore();
|
|
1033
|
+
$isBanned = $store->has("banned-zkp-y:{$zkpY}");
|
|
1034
|
+
return ['threatIntelScore' => $isBanned ? 100.0 : 0.0];
|
|
1029
1035
|
}
|
|
1030
1036
|
|
|
1031
1037
|
/**
|
|
@@ -1248,12 +1254,20 @@ class RequestUtils
|
|
|
1248
1254
|
'highScoreCount' => 0,
|
|
1249
1255
|
'deviceIds' => [],
|
|
1250
1256
|
'highScoreDevices' => [],
|
|
1251
|
-
'lastActivity' => 0
|
|
1257
|
+
'lastActivity' => 0,
|
|
1258
|
+
'ips' => [],
|
|
1259
|
+
'uas' => []
|
|
1252
1260
|
];
|
|
1253
1261
|
|
|
1254
1262
|
if (!isset($subnetData['highScoreDevices'])) {
|
|
1255
1263
|
$subnetData['highScoreDevices'] = [];
|
|
1256
1264
|
}
|
|
1265
|
+
if (!isset($subnetData['ips'])) {
|
|
1266
|
+
$subnetData['ips'] = [];
|
|
1267
|
+
}
|
|
1268
|
+
if (!isset($subnetData['uas'])) {
|
|
1269
|
+
$subnetData['uas'] = [];
|
|
1270
|
+
}
|
|
1257
1271
|
|
|
1258
1272
|
// Utilisation de la partie stable du fingerprint matériel plutôt que l'ID de cookie volatil
|
|
1259
1273
|
$currentDeviceHash = self::getCompositeDeviceHash($context);
|
|
@@ -1268,6 +1282,16 @@ class RequestUtils
|
|
|
1268
1282
|
if (!in_array($stableFpId, $subnetData['deviceIds'], true)) {
|
|
1269
1283
|
$subnetData['deviceIds'][] = $stableFpId;
|
|
1270
1284
|
}
|
|
1285
|
+
|
|
1286
|
+
if (!in_array($context->clientIp, $subnetData['ips'], true)) {
|
|
1287
|
+
$subnetData['ips'][] = $context->clientIp;
|
|
1288
|
+
}
|
|
1289
|
+
|
|
1290
|
+
$userAgent = $context->getHeader('user-agent') ?? '';
|
|
1291
|
+
if (!empty($userAgent) && !in_array($userAgent, $subnetData['uas'], true)) {
|
|
1292
|
+
$subnetData['uas'][] = $userAgent;
|
|
1293
|
+
}
|
|
1294
|
+
|
|
1271
1295
|
$subnetData['lastActivity'] = time();
|
|
1272
1296
|
|
|
1273
1297
|
// Limiter la taille du tableau des deviceIds pour éviter une consommation mémoire excessive.
|
|
@@ -1279,6 +1303,12 @@ class RequestUtils
|
|
|
1279
1303
|
unset($subnetData['highScoreDevices'][$oldDeviceId]);
|
|
1280
1304
|
}
|
|
1281
1305
|
}
|
|
1306
|
+
if (count($subnetData['ips']) > 100) {
|
|
1307
|
+
array_shift($subnetData['ips']);
|
|
1308
|
+
}
|
|
1309
|
+
if (count($subnetData['uas']) > 50) {
|
|
1310
|
+
array_shift($subnetData['uas']);
|
|
1311
|
+
}
|
|
1282
1312
|
|
|
1283
1313
|
// TTL de 24 heures pour les données de sous-réseau.
|
|
1284
1314
|
$store->set($key, $subnetData, 86400);
|
|
@@ -1312,23 +1342,32 @@ class RequestUtils
|
|
|
1312
1342
|
|
|
1313
1343
|
$highScoreCount = $subnetData['highScoreCount'] ?? 0;
|
|
1314
1344
|
$deviceCount = isset($subnetData['deviceIds']) ? count($subnetData['deviceIds']) : 0;
|
|
1345
|
+
$ipCount = isset($subnetData['ips']) ? count($subnetData['ips']) : 1;
|
|
1346
|
+
$uaCount = isset($subnetData['uas']) ? count($subnetData['uas']) : 1;
|
|
1315
1347
|
|
|
1316
1348
|
if ($halfLives > 0) {
|
|
1317
|
-
$
|
|
1318
|
-
$
|
|
1349
|
+
$decay = pow(2, $halfLives);
|
|
1350
|
+
$highScoreCount = max(0, (int)floor($highScoreCount / $decay));
|
|
1351
|
+
$deviceCount = max(0, (int)floor($deviceCount / $decay));
|
|
1352
|
+
$ipCount = max(1, (int)floor($ipCount / $decay));
|
|
1353
|
+
$uaCount = max(1, (int)floor($uaCount / $decay));
|
|
1319
1354
|
}
|
|
1320
1355
|
|
|
1321
|
-
$
|
|
1322
|
-
|
|
1323
|
-
// Pénalité basée sur le nombre de devices uniques vus depuis ce sous-réseau.
|
|
1324
|
-
if ($deviceCount > 10) {
|
|
1325
|
-
$score += min(80.0, ($deviceCount - 10) * 5);
|
|
1356
|
+
if ($deviceCount === 0) {
|
|
1357
|
+
return ['subnetScore' => 0.0];
|
|
1326
1358
|
}
|
|
1327
1359
|
|
|
1328
|
-
|
|
1329
|
-
$
|
|
1360
|
+
$suspicionDensity = $highScoreCount / $deviceCount;
|
|
1361
|
+
$ipDeviceRatio = $ipCount / $deviceCount;
|
|
1362
|
+
|
|
1363
|
+
$baseScore = 100.0 * (1.0 - exp(-0.15 * $highScoreCount));
|
|
1364
|
+
|
|
1365
|
+
$densityMultiplier = 0.4 + (1.6 * $suspicionDensity);
|
|
1366
|
+
$distributionMultiplier = 0.5 + (1.0 * $ipDeviceRatio);
|
|
1330
1367
|
|
|
1331
|
-
|
|
1368
|
+
$finalScore = min(100.0, round($baseScore * $densityMultiplier * $distributionMultiplier * 10.0) / 10.0);
|
|
1369
|
+
|
|
1370
|
+
return ['subnetScore' => $finalScore];
|
|
1332
1371
|
}
|
|
1333
1372
|
|
|
1334
1373
|
/**
|
|
@@ -1358,10 +1397,15 @@ class RequestUtils
|
|
|
1358
1397
|
});
|
|
1359
1398
|
$clusterData = array_values($clusterData);
|
|
1360
1399
|
|
|
1400
|
+
$userAgent = $context->getHeader('user-agent') ?? '';
|
|
1401
|
+
$subnet = self::getIpSubnet($context->clientIp) ?? 'unknown';
|
|
1402
|
+
|
|
1361
1403
|
$found = false;
|
|
1362
1404
|
foreach ($clusterData as &$entry) {
|
|
1363
1405
|
if (isset($entry['ip']) && $entry['ip'] === $context->clientIp) {
|
|
1364
1406
|
$entry['timestamp'] = $now;
|
|
1407
|
+
$entry['ua'] = $userAgent;
|
|
1408
|
+
$entry['subnet'] = $subnet;
|
|
1365
1409
|
$found = true;
|
|
1366
1410
|
break;
|
|
1367
1411
|
}
|
|
@@ -1369,14 +1413,26 @@ class RequestUtils
|
|
|
1369
1413
|
unset($entry);
|
|
1370
1414
|
|
|
1371
1415
|
if (!$found) {
|
|
1372
|
-
$clusterData[] = [
|
|
1416
|
+
$clusterData[] = [
|
|
1417
|
+
'ip' => $context->clientIp,
|
|
1418
|
+
'timestamp' => $now,
|
|
1419
|
+
'ua' => $userAgent,
|
|
1420
|
+
'subnet' => $subnet
|
|
1421
|
+
];
|
|
1373
1422
|
}
|
|
1374
1423
|
|
|
1375
1424
|
$store->set($key, $clusterData, 600);
|
|
1376
1425
|
$uniqueIpsCount = count($clusterData);
|
|
1377
1426
|
$botnetClusterScore = 0.0;
|
|
1378
1427
|
if ($uniqueIpsCount >= 2) {
|
|
1379
|
-
$
|
|
1428
|
+
$uniqueSubnets = count(array_unique(array_filter(array_column($clusterData, 'subnet'))));
|
|
1429
|
+
$uniqueUserAgents = count(array_unique(array_filter(array_column($clusterData, 'ua'))));
|
|
1430
|
+
|
|
1431
|
+
$subnetMultiplier = $uniqueSubnets > 1 ? 1.3 : 0.6;
|
|
1432
|
+
$uaRotationMultiplier = $uniqueUserAgents > 1 ? 1.5 : 1.0;
|
|
1433
|
+
|
|
1434
|
+
$baseScore = 100.0 * (1.0 - exp(-0.35 * ($uniqueIpsCount - 1)));
|
|
1435
|
+
$botnetClusterScore = min(100.0, round($baseScore * $subnetMultiplier * $uaRotationMultiplier * 10.0) / 10.0);
|
|
1380
1436
|
}
|
|
1381
1437
|
return ['botnetClusterScore' => $botnetClusterScore];
|
|
1382
1438
|
}
|