@anonympins/fingerprint 0.6.6 → 0.7.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.
@@ -81,83 +81,31 @@
81
81
  return null;
82
82
  }
83
83
 
84
- private static function dnsResolveUdp(string $query, string $type, float $timeout = 0.5): ?array
84
+ private static function resolveDnsNative(string $query, string $type): ?array
85
85
  {
86
- $dnsServer = '8.8.8.8';
87
- $port = 53;
88
- $fp = @stream_socket_client("udp://$dnsServer:$port", $errno, $errstr, $timeout);
89
- if (!$fp) return null;
90
- stream_set_timeout($fp, 0, (int)($timeout * 1000000));
91
-
92
- $id = rand(10000, 65000);
93
- $header = pack('n6', $id, 0x0100, 1, 0, 0, 0);
94
-
95
- $qType = ($type === 'PTR') ? 12 : (($type === 'AAAA') ? 28 : 1);
96
- $parts = explode('.', $query);
97
- $qName = '';
98
- foreach ($parts as $part) {
99
- $qName .= chr(strlen($part)) . $part;
86
+ $typeMap = [
87
+ 'PTR' => DNS_PTR,
88
+ 'A' => DNS_A,
89
+ 'AAAA' => DNS_AAAA
90
+ ];
91
+ $dnsType = $typeMap[$type] ?? null;
92
+ if ($dnsType === null) {
93
+ return null;
100
94
  }
101
- $qName .= chr(0);
102
- $question = $qName . pack('n2', $qType, 1);
103
-
104
- if (!@fwrite($fp, $header . $question)) {
105
- fclose($fp);
95
+
96
+ $records = @dns_get_record($query, $dnsType);
97
+ if ($records === false) {
106
98
  return null;
107
99
  }
108
-
109
- $response = @fread($fp, 512);
110
- fclose($fp);
111
- if (!$response || strlen($response) < 12) return null;
112
-
113
- $resHeader = unpack('n6', substr($response, 0, 12));
114
- if ($resHeader[1] !== $id) return null;
115
-
116
- $answersCount = $resHeader[4];
117
- if ($answersCount <= 0) return [];
118
-
119
- $offset = 12 + strlen($question);
100
+
120
101
  $results = [];
121
- for ($i = 0; $i < $answersCount; $i++) {
122
- if ($offset + 12 > strlen($response)) break;
123
- if ((ord($response[$offset]) & 0xc0) === 0xc0) {
124
- $offset += 2;
125
- } else {
126
- while ($offset < strlen($response) && ord($response[$offset]) !== 0) {
127
- $offset += 1 + ord($response[$offset]);
128
- }
129
- $offset++;
130
- }
131
- if ($offset + 10 > strlen($response)) break;
132
- $typeAndClass = unpack('n2type_class/Nttl/nlen', substr($response, $offset, 10));
133
- $rType = $typeAndClass['type_class1'];
134
- $rLen = $typeAndClass['len'];
135
- $offset += 10;
136
- if ($offset + $rLen > strlen($response)) break;
137
- $rData = substr($response, $offset, $rLen);
138
- $offset += $rLen;
139
-
140
- if ($rType === 12) {
141
- $ptrName = '';
142
- $p = 0;
143
- while ($p < strlen($rData)) {
144
- $l = ord($rData[$p]);
145
- if ($l === 0) break;
146
- if (($l & 0xc0) === 0xc0) {
147
- break;
148
- }
149
- $ptrName .= substr($rData, $p + 1, $l) . '.';
150
- $p += 1 + $l;
151
- }
152
- $results[] = rtrim($ptrName, '.');
153
- } elseif ($rType === 1) {
154
- if ($rLen === 4) {
155
- $results[] = long2ip(unpack('N', $rData)[1]);
156
- }
157
- } elseif ($rType === 28) {
158
- if ($rLen === 16) {
159
- $results[] = inet_ntop($rData);
160
- }
102
+ foreach ($records as $record) {
103
+ if ($type === 'PTR' && isset($record['target'])) {
104
+ $results[] = $record['target'];
105
+ } elseif ($type === 'A' && isset($record['ip'])) {
106
+ $results[] = $record['ip'];
107
+ } elseif ($type === 'AAAA' && isset($record['ipv6'])) {
108
+ $results[] = $record['ipv6'];
161
109
  }
162
110
  }
163
111
  return $results;
@@ -690,10 +638,8 @@
690
638
  // Score d'incohérence du fingerprint (déplacé ici pour être avec les autres)
691
639
  $currentDeviceHash = RequestUtils::getCompositeDeviceHash($context);
692
640
  $consistencyScore = FingerprintBuilder::compare($deviceData['initialDeviceHash'] ?? '', $currentDeviceHash);
693
- $inconsistencyScore = min(100.0, max(0.0, (1 - $consistencyScore) * 200));
694
- if ($consistencyScore < ($this->securityConfig['similarityThreshold'] ?? 0.7)) {
695
- $inconsistencyScore = 100.0;
696
- }
641
+ $similarityThreshold = (float)($this->securityConfig['similarityThreshold'] ?? 0.72);
642
+ $inconsistencyScore = RequestUtils::calculateAnalogInconsistencyScore($consistencyScore, $similarityThreshold);
697
643
 
698
644
  $behavioral = RequestUtils::getBehavioralIndicators($context, $deviceData);
699
645
 
@@ -703,6 +649,7 @@
703
649
  // Score de spoofing TLS
704
650
  $tlsSpoofing = RequestUtils::getTlsSpoofingScore($context);
705
651
  $tlsSpoofingScore = (float)($tlsSpoofing['tlsSpoofingScore'] ?? 0.0);
652
+ $virtualizationScore = RequestUtils::getVirtualizationAnomalyScore($context);
706
653
 
707
654
  // Advanced JA4 TLS Inconsistency checks
708
655
  $ja4 = $context->getHeader('x-ja4-hash');
@@ -830,6 +777,7 @@
830
777
  'tcpAnomalyScore' => $tcpAnomaly['tcpAnomalyScore'],
831
778
  'protocolAnomalyScore' => $protocolAnomaly['protocolAnomalyScore'],
832
779
  'renderingAnomalyScore' => $renderingAnomaly['renderingAnomalyScore'],
780
+ 'virtualizationScore' => $virtualizationScore
833
781
  ]);
834
782
 
835
783
  // Sauvegarder l'état mis à jour de l'appareil dans le store
@@ -1233,7 +1181,8 @@
1233
1181
 
1234
1182
  // 5. Prendre une décision basée sur le score - Vérifier le blocage d'abord.
1235
1183
  $blockThreshold = $thresholds['block'] ?? 95;
1236
- if ($finalScore >= $blockThreshold) {
1184
+ $isBlocked = $finalScore >= $blockThreshold;
1185
+ if ($isBlocked) {
1237
1186
  if ($this->logger) {
1238
1187
  MetricsManager::incrementCounter('requests_total', ['status' => 'blocked']);
1239
1188
  $this->logger->log('info', 'request_blocked', ['deviceId' => $deviceId, 'score' => $finalScore, 'vector' => $suspicionVector]);
@@ -1295,8 +1244,14 @@
1295
1244
  return $decision;
1296
1245
  }
1297
1246
 
1298
- $highThreshold = $thresholds['high'] ?? 75;
1299
- $mustReChallenge = $finalScore >= $highThreshold && $hasValidTicket && $finalScore > 0;
1247
+ $mediumThreshold = $thresholds['medium'] ?? 45;
1248
+ $maxIndicatorsCount = 0;
1249
+ foreach ($suspicionVector as $val) {
1250
+ if (is_numeric($val) && (float)$val >= 100.0) {
1251
+ $maxIndicatorsCount++;
1252
+ }
1253
+ }
1254
+ $mustReChallenge = (($suspicionVector['honeypotScore'] ?? 0.0) >= $mediumThreshold) || ($maxIndicatorsCount >= 1);
1300
1255
 
1301
1256
  $lowThreshold = $thresholds['low'] ?? 20;
1302
1257
  if (($finalScore >= $lowThreshold && !$hasValidTicket) || $mustReChallenge) {
@@ -1665,12 +1620,12 @@
1665
1620
 
1666
1621
  try {
1667
1622
  // 1. Reverse DNS lookup with strict 500ms timeout using our custom UDP DNS Client
1668
- $revName = self::getReverseDnsName($context->client_ip);
1623
+ $revName = self::getReverseDnsName($context->clientIp);
1669
1624
  if (!$revName) {
1670
1625
  $store->set($cacheKey, 'failed', 300); // 5 min negative caching
1671
1626
  return false;
1672
1627
  }
1673
- $hostnames = self::dnsResolveUdp($revName, 'PTR', 0.5);
1628
+ $hostnames = self::resolveDnsNative($revName, 'PTR');
1674
1629
  if ($hostnames === null || empty($hostnames)) {
1675
1630
  self::recordDnsFailure();
1676
1631
  $store->set($cacheKey, 'failed', 300); // 5 min negative caching
@@ -1692,7 +1647,7 @@
1692
1647
 
1693
1648
  // 2. Forward DNS lookup with strict 500ms timeout
1694
1649
  $ips = [];
1695
- $resolvedA = self::dnsResolveUdp($validHostname, 'A', 0.5);
1650
+ $resolvedA = self::resolveDnsNative($validHostname, 'A');
1696
1651
  if ($resolvedA === null) {
1697
1652
  self::recordDnsFailure();
1698
1653
  $store->set($cacheKey, 'failed', 300); // 5 min negative caching
@@ -1700,7 +1655,7 @@
1700
1655
  }
1701
1656
  $ips = array_merge($ips, $resolvedA);
1702
1657
 
1703
- $resolvedAaaa = self::dnsResolveUdp($validHostname, 'AAAA', 0.5);
1658
+ $resolvedAaaa = self::resolveDnsNative($validHostname, 'AAAA');
1704
1659
  if ($resolvedAaaa === null) {
1705
1660
  self::recordDnsFailure();
1706
1661
  $store->set($cacheKey, 'failed', 300); // 5 min negative caching
@@ -1708,7 +1663,7 @@
1708
1663
  }
1709
1664
  $ips = array_merge($ips, $resolvedAaaa);
1710
1665
 
1711
- if (in_array($context->client_ip, $ips, true)) {
1666
+ if (in_array($context->clientIp, $ips, true)) {
1712
1667
  self::recordDnsSuccess();
1713
1668
  $store->set($cacheKey, 'verified', 86400);
1714
1669
  return true;