Files
michaelschiemer/tests/Framework/DDoS/Components/AttackPatternDetectorTest.php
Michael Schiemer 55a330b223 Enable Discovery debug logging for production troubleshooting
- Add DISCOVERY_LOG_LEVEL=debug
- Add DISCOVERY_SHOW_PROGRESS=true
- Temporary changes for debugging InitializerProcessor fixes on production
2025-08-11 20:13:26 +02:00

282 lines
9.0 KiB
PHP

<?php
declare(strict_types=1);
use App\Framework\DDoS\Components\AttackPatternDetector;
use App\Framework\DDoS\DDoSConfig;
use App\Framework\DDoS\ValueObjects\AttackPattern;
use App\Framework\Logging\DefaultLogger;
use App\Framework\Logging\LogLevel;
require_once __DIR__ . '/../Helpers/TestHelpers.php';
beforeEach(function () {
// Create development config (more permissive for testing)
$config = DDoSConfig::development();
// Create logger
$logger = new DefaultLogger(LogLevel::DEBUG);
$this->detector = new AttackPatternDetector($config, $logger);
});
describe('AttackPatternDetector', function () {
it('detects volumetric attacks', function () {
$analysisResults = [
'traffic_patterns' => [
'threat_score' => 0.9, // Higher than development config threshold (0.8)
'requests_per_minute' => 500,
'normal_rate' => 50,
],
];
$request = createTestRequest('192.168.1.100', 'GET', '/api/data');
$patterns = $this->detector->identifyAttackPatterns($analysisResults, $request);
expect($patterns)->toContain(AttackPattern::VOLUMETRIC);
});
it('detects distributed attacks', function () {
$analysisResults = [
'geo_anomalies' => [
'threat_score' => 0.7,
'unique_countries' => 15,
'geographic_diversity' => 0.9,
],
];
$request = createTestRequest('10.0.0.1', 'POST', '/api/login');
$patterns = $this->detector->identifyAttackPatterns($analysisResults, $request);
expect($patterns)->toContain(AttackPattern::DISTRIBUTED);
});
it('detects bot attacks from user agent patterns', function () {
$analysisResults = [
'request_signature' => [
'threat_score' => 0.6,
'user_agent_suspicion' => 0.8,
'automation_indicators' => ['unusual_timing', 'fixed_intervals'],
],
];
$request = createTestRequest('192.168.1.200', 'GET', '/scrape-data', [
'User-Agent' => 'ScrapingBot/2.0 (automated)',
]);
$patterns = $this->detector->identifyAttackPatterns($analysisResults, $request);
expect($patterns)->toContain(AttackPattern::BOTNET);
});
it('detects application layer attacks', function () {
$analysisResults = [
'waf_analysis' => [
'threat_score' => 0.9,
'malicious_patterns' => ['sql_injection', 'xss_attempt'],
'payload_analysis' => 'high_risk',
],
];
$request = createTestRequest('192.168.1.300', 'POST', '/api/search', [], [
'query' => "'; DROP TABLE users; --",
]);
$patterns = $this->detector->identifyAttackPatterns($analysisResults, $request);
expect($patterns)->toContain(AttackPattern::APPLICATION_LAYER);
});
it('detects slow rate attacks', function () {
$analysisResults = [
'traffic_patterns' => [
'threat_score' => 0.4,
'requests_per_minute' => 30,
'sustained_duration' => 3600, // 1 hour
'pattern_consistency' => 0.95,
],
];
$request = createTestRequest('192.168.1.400', 'GET', '/expensive-operation');
$patterns = $this->detector->identifyAttackPatterns($analysisResults, $request);
expect($patterns)->toContain(AttackPattern::SLOWLORIS);
});
it('detects mixed attack patterns', function () {
$analysisResults = [
'traffic_patterns' => [
'threat_score' => 0.8,
'requests_per_minute' => 300,
],
'geo_anomalies' => [
'threat_score' => 0.6,
'unique_countries' => 10,
],
'waf_analysis' => [
'threat_score' => 0.7,
'malicious_patterns' => ['xss_attempt'],
],
];
$request = createTestRequest('192.168.1.500', 'POST', '/api/submit');
$patterns = $this->detector->identifyAttackPatterns($analysisResults, $request);
expect($patterns)->toHaveCount(3);
expect($patterns)->toContain(AttackPattern::VOLUMETRIC);
expect($patterns)->toContain(AttackPattern::DISTRIBUTED);
expect($patterns)->toContain(AttackPattern::APPLICATION_LAYER);
});
it('returns empty array for normal traffic', function () {
$analysisResults = [
'traffic_patterns' => [
'threat_score' => 0.1,
'requests_per_minute' => 15,
],
'geo_anomalies' => [
'threat_score' => 0.05,
'unique_countries' => 1,
],
];
$request = createTestRequest('192.168.1.600', 'GET', '/api/health');
$patterns = $this->detector->identifyAttackPatterns($analysisResults, $request);
expect($patterns)->toBeEmpty();
});
it('identifies coordinated attack patterns', function () {
$analysisResults = [
'traffic_patterns' => [
'threat_score' => 0.6,
'coordination_score' => 0.8,
'timing_patterns' => 'synchronized',
],
];
$request = createTestRequest('192.168.1.700', 'GET', '/target-endpoint');
$patterns = $this->detector->identifyAttackPatterns($analysisResults, $request);
expect($patterns)->toContain(AttackPattern::DISTRIBUTED);
});
it('detects amplification attacks', function () {
$analysisResults = [
'traffic_patterns' => [
'threat_score' => 0.7,
'amplification_ratio' => 50,
'response_size_anomaly' => 0.9,
],
];
$request = createTestRequest('192.168.1.800', 'GET', '/api/export-large-dataset');
$patterns = $this->detector->identifyAttackPatterns($analysisResults, $request);
expect($patterns)->toContain(AttackPattern::AMPLIFICATION);
});
it('handles malformed analysis results', function () {
$analysisResults = [
'invalid_layer' => null,
'broken_data' => 'not_an_array',
];
$request = createTestRequest('192.168.1.900', 'GET', '/api/test');
$patterns = $this->detector->identifyAttackPatterns($analysisResults, $request);
expect($patterns)->toBeArray();
});
it('calculates pattern confidence scores', function () {
$analysisResults = [
'traffic_patterns' => [
'threat_score' => 0.8,
'confidence' => 0.9,
],
];
$request = createTestRequest('192.168.1.100', 'GET', '/api/data');
$confidence = $this->detector->calculatePatternConfidence($analysisResults);
expect($confidence)->toBeBetween(0.0, 1.0);
expect($confidence)->toBeGreaterThan(0.7);
});
it('provides pattern severity assessment', function () {
$patterns = [
AttackPattern::VOLUMETRIC,
AttackPattern::APPLICATION_LAYER,
];
$severity = $this->detector->assessPatternSeverity($patterns);
expect($severity)->toBeIn(['low', 'medium', 'high', 'critical']);
});
});
describe('Pattern Analysis Details', function () {
it('provides detailed pattern analysis', function () {
$analysisResults = [
'traffic_patterns' => [
'threat_score' => 0.8,
'requests_per_minute' => 500,
'peak_detection' => true,
],
];
$request = createTestRequest('192.168.1.100', 'GET', '/api/data');
$details = $this->detector->getPatternAnalysisDetails($analysisResults, $request);
expect($details)->toHaveKeys([
'detected_patterns',
'confidence_scores',
'risk_factors',
'recommendations',
]);
});
it('tracks pattern evolution over time', function () {
$historicalData = [
['timestamp' => time() - 3600, 'patterns' => [AttackPattern::VOLUMETRIC]],
['timestamp' => time() - 1800, 'patterns' => [AttackPattern::VOLUMETRIC, AttackPattern::BOTNET]],
['timestamp' => time(), 'patterns' => [AttackPattern::DISTRIBUTED]],
];
$evolution = $this->detector->analyzePatternEvolution($historicalData);
expect($evolution)->toHaveKeys(['trend', 'escalation_detected', 'pattern_changes']);
expect($evolution['escalation_detected'])->toBeTrue();
});
it('generates pattern fingerprints', function () {
$analysisResults = [
'traffic_patterns' => ['threat_score' => 0.8],
'geo_anomalies' => ['threat_score' => 0.6],
];
$request = createTestRequest('192.168.1.100', 'GET', '/api/data');
$fingerprint = $this->detector->generatePatternFingerprint($analysisResults, $request);
expect($fingerprint)->toBeString();
expect(strlen($fingerprint))->toBeGreaterThan(10);
});
});
// Helper functions are now in ../Helpers/TestHelpers.php