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
This commit is contained in:
346
src/Application/Security/WafOWASPEventBridge.php
Normal file
346
src/Application/Security/WafOWASPEventBridge.php
Normal file
@@ -0,0 +1,346 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Application\Security;
|
||||
|
||||
use App\Application\Security\Events\Auth\{
|
||||
AuthenticationFailedEvent
|
||||
};
|
||||
use App\Application\Security\Events\Input\{
|
||||
InputValidationFailureEvent,
|
||||
MaliciousInputDetectedEvent,
|
||||
SqlInjectionAttemptEvent,
|
||||
XssAttemptEvent
|
||||
};
|
||||
use App\Application\Security\Events\Network\SuspiciousNetworkActivityEvent;
|
||||
use App\Application\Security\Events\System\SystemAnomalyEvent;
|
||||
use App\Application\Security\ValueObjects\{
|
||||
OWASPEventIdentifier,
|
||||
OWASPLogLevel,
|
||||
RequestContext,
|
||||
SecurityContext
|
||||
};
|
||||
use App\Framework\Waf\DetectionCategory;
|
||||
use App\Framework\Waf\DetectionSeverity;
|
||||
use App\Framework\Waf\ValueObjects\Detection;
|
||||
|
||||
/**
|
||||
* WAF-OWASP Event Bridge
|
||||
*
|
||||
* Consolidates the WAF Detection system with the existing OWASP Security Event framework
|
||||
* to eliminate duplication and provide unified security event handling.
|
||||
*/
|
||||
final class WafOWASPEventBridge
|
||||
{
|
||||
public function __construct(
|
||||
private readonly OWASPSecurityEventFactory $eventFactory,
|
||||
private readonly OWASPSecurityEventLogger $eventLogger
|
||||
) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert WAF Detection to OWASP Security Event and log it
|
||||
*/
|
||||
public function processWafDetection(
|
||||
Detection $detection,
|
||||
SecurityContext $securityContext,
|
||||
RequestContext $requestContext
|
||||
): OWASPSecurityEvent {
|
||||
$owaspEvent = $this->convertDetectionToOWASPEvent($detection, $requestContext);
|
||||
|
||||
// Log using existing OWASP logger
|
||||
$logFormat = $this->eventFactory->createFromDetection(
|
||||
$detection,
|
||||
$owaspEvent,
|
||||
$securityContext,
|
||||
$requestContext
|
||||
);
|
||||
|
||||
$this->eventLogger->log($logFormat);
|
||||
|
||||
return $owaspEvent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert WAF Detection to appropriate OWASP Security Event
|
||||
*/
|
||||
public function convertDetectionToOWASPEvent(
|
||||
Detection $detection,
|
||||
RequestContext $requestContext
|
||||
): OWASPSecurityEvent {
|
||||
return match ($detection->category) {
|
||||
DetectionCategory::SQL_INJECTION => $this->createSqlInjectionEvent($detection, $requestContext),
|
||||
DetectionCategory::XSS => $this->createXssEvent($detection, $requestContext),
|
||||
DetectionCategory::INJECTION,
|
||||
DetectionCategory::COMMAND_INJECTION,
|
||||
DetectionCategory::LDAP_INJECTION,
|
||||
DetectionCategory::XPATH_INJECTION,
|
||||
DetectionCategory::NOSQL_INJECTION => $this->createMaliciousInputEvent($detection, $requestContext),
|
||||
DetectionCategory::BRUTE_FORCE,
|
||||
DetectionCategory::CREDENTIAL_STUFFING,
|
||||
DetectionCategory::AUTHENTICATION_BYPASS => $this->createAuthenticationFailedEvent($detection, $requestContext),
|
||||
DetectionCategory::SUSPICIOUS_IP,
|
||||
DetectionCategory::MALICIOUS_BOT,
|
||||
DetectionCategory::DOS_ATTACK,
|
||||
DetectionCategory::DDOS_ATTACK => $this->createSuspiciousNetworkActivityEvent($detection, $requestContext),
|
||||
DetectionCategory::RATE_LIMIT_VIOLATION,
|
||||
DetectionCategory::ANOMALOUS_BEHAVIOR,
|
||||
DetectionCategory::SUSPICIOUS_USER_AGENT => $this->createSystemAnomalyEvent($detection, $requestContext),
|
||||
default => $this->createGenericInputValidationEvent($detection, $requestContext)
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Create SQL Injection OWASP event from WAF detection
|
||||
*/
|
||||
private function createSqlInjectionEvent(Detection $detection, RequestContext $requestContext): SqlInjectionAttemptEvent
|
||||
{
|
||||
$payload = $detection->payload?->getSample() ?? $detection->message;
|
||||
$targetField = $detection->location ?? 'unknown_field';
|
||||
$detectionMethod = "WAF Rule {($detection->ruleId?->value) ?? 'generic'}";
|
||||
|
||||
return new SqlInjectionAttemptEvent(
|
||||
attackPayload: $payload,
|
||||
targetField: $targetField,
|
||||
detectionMethod: $detectionMethod,
|
||||
email: $requestContext->getUserEmail()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create XSS OWASP event from WAF detection
|
||||
*/
|
||||
private function createXssEvent(Detection $detection, RequestContext $requestContext): XssAttemptEvent
|
||||
{
|
||||
$payload = $detection->payload?->getSample() ?? $detection->message;
|
||||
$targetField = $detection->location ?? 'unknown_field';
|
||||
$xssType = $this->determineXssType($payload);
|
||||
|
||||
return new XssAttemptEvent(
|
||||
attackPayload: $payload,
|
||||
targetField: $targetField,
|
||||
xssType: $xssType,
|
||||
email: $requestContext->getUserEmail()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create Malicious Input OWASP event from WAF detection
|
||||
*/
|
||||
private function createMaliciousInputEvent(Detection $detection, RequestContext $requestContext): MaliciousInputDetectedEvent
|
||||
{
|
||||
$payload = $detection->payload?->getSample() ?? $detection->message;
|
||||
$inputType = $this->mapDetectionCategoryToInputType($detection->category);
|
||||
|
||||
return new MaliciousInputDetectedEvent(
|
||||
inputPayload: $payload,
|
||||
inputType: $inputType,
|
||||
detectionMethod: "WAF Rule {($detection->ruleId?->value) ?? 'generic'}",
|
||||
email: $requestContext->getUserEmail()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create Authentication Failed OWASP event from WAF detection
|
||||
*/
|
||||
private function createAuthenticationFailedEvent(Detection $detection, RequestContext $requestContext): AuthenticationFailedEvent
|
||||
{
|
||||
$attackType = $this->mapDetectionCategoryToAttackType($detection->category);
|
||||
$email = $requestContext->getUserEmail() ?? 'anonymous@waf.detection';
|
||||
|
||||
return new AuthenticationFailedEvent(
|
||||
email: $email,
|
||||
reason: $attackType,
|
||||
failedAttempts: 1
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create Suspicious Network Activity OWASP event from WAF detection
|
||||
*/
|
||||
private function createSuspiciousNetworkActivityEvent(Detection $detection, RequestContext $requestContext): SuspiciousNetworkActivityEvent
|
||||
{
|
||||
$activityType = $this->mapDetectionCategoryToActivityType($detection->category);
|
||||
|
||||
return new SuspiciousNetworkActivityEvent(
|
||||
sourceIp: $requestContext->getClientIp(),
|
||||
activityType: $activityType,
|
||||
requestCount: 1, // WAF detections are typically single requests
|
||||
timeWindow: '1 minute',
|
||||
email: $requestContext->getUserEmail()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create System Anomaly OWASP event from WAF detection
|
||||
*/
|
||||
private function createSystemAnomalyEvent(Detection $detection, RequestContext $requestContext): SystemAnomalyEvent
|
||||
{
|
||||
$anomalyType = $this->mapDetectionCategoryToAnomalyType($detection->category);
|
||||
$metrics = [
|
||||
'threat_score' => $detection->getThreatScore()->getValue(),
|
||||
'confidence' => $detection->confidence?->getValue(),
|
||||
'location' => $detection->location,
|
||||
'client_ip' => $requestContext->getClientIp(),
|
||||
'rule_id' => $detection->ruleId?->value,
|
||||
];
|
||||
|
||||
return new SystemAnomalyEvent(
|
||||
anomalyType: $anomalyType,
|
||||
description: $detection->message,
|
||||
metrics: array_filter($metrics),
|
||||
severity: $this->mapSeverityToString($detection->severity)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create generic Input Validation OWASP event from WAF detection
|
||||
*/
|
||||
private function createGenericInputValidationEvent(Detection $detection, RequestContext $requestContext): InputValidationFailureEvent
|
||||
{
|
||||
$field = $detection->location ?? 'unknown_field';
|
||||
$reason = $detection->category->getDescription();
|
||||
|
||||
return new InputValidationFailureEvent(
|
||||
field: $field,
|
||||
reason: $reason,
|
||||
attemptedValue: $detection->payload?->getSample() ?? '',
|
||||
email: $requestContext->getUserEmail()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Map WAF Detection Category to Input Type
|
||||
*/
|
||||
private function mapDetectionCategoryToInputType(DetectionCategory $category): string
|
||||
{
|
||||
return match ($category) {
|
||||
DetectionCategory::COMMAND_INJECTION => 'command_injection',
|
||||
DetectionCategory::LDAP_INJECTION => 'ldap_injection',
|
||||
DetectionCategory::XPATH_INJECTION => 'xpath_injection',
|
||||
DetectionCategory::NOSQL_INJECTION => 'nosql_injection',
|
||||
DetectionCategory::XXE => 'xml_external_entity',
|
||||
DetectionCategory::PATH_TRAVERSAL => 'path_traversal',
|
||||
DetectionCategory::DESERIALIZATION => 'unsafe_deserialization',
|
||||
default => 'generic_injection'
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Map WAF Detection Category to Attack Type
|
||||
*/
|
||||
private function mapDetectionCategoryToAttackType(DetectionCategory $category): string
|
||||
{
|
||||
return match ($category) {
|
||||
DetectionCategory::BRUTE_FORCE => 'brute_force',
|
||||
DetectionCategory::CREDENTIAL_STUFFING => 'credential_stuffing',
|
||||
DetectionCategory::AUTHENTICATION_BYPASS => 'authentication_bypass',
|
||||
DetectionCategory::SESSION_FIXATION => 'session_fixation',
|
||||
DetectionCategory::SESSION_HIJACKING => 'session_hijacking',
|
||||
default => 'authentication_attack'
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Map WAF Detection Category to Activity Type
|
||||
*/
|
||||
private function mapDetectionCategoryToActivityType(DetectionCategory $category): string
|
||||
{
|
||||
return match ($category) {
|
||||
DetectionCategory::SUSPICIOUS_IP => 'suspicious_ip_activity',
|
||||
DetectionCategory::MALICIOUS_BOT => 'malicious_bot_activity',
|
||||
DetectionCategory::DOS_ATTACK => 'denial_of_service',
|
||||
DetectionCategory::DDOS_ATTACK => 'distributed_denial_of_service',
|
||||
DetectionCategory::SCRAPING_BOT => 'web_scraping',
|
||||
DetectionCategory::SPAM_BOT => 'spam_activity',
|
||||
DetectionCategory::AUTOMATED_ATTACK => 'automated_attack',
|
||||
DetectionCategory::TOR_EXIT_NODE => 'tor_network_activity',
|
||||
DetectionCategory::PROXY_DETECTION => 'proxy_usage',
|
||||
default => 'suspicious_network_activity'
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Map WAF Detection Category to Anomaly Type
|
||||
*/
|
||||
private function mapDetectionCategoryToAnomalyType(DetectionCategory $category): string
|
||||
{
|
||||
return match ($category) {
|
||||
DetectionCategory::RATE_LIMIT_VIOLATION => 'rate_limit_anomaly',
|
||||
DetectionCategory::ANOMALOUS_BEHAVIOR => 'behavioral_anomaly',
|
||||
DetectionCategory::SUSPICIOUS_USER_AGENT => 'user_agent_anomaly',
|
||||
DetectionCategory::FINGERPRINTING_ATTEMPT => 'fingerprinting_anomaly',
|
||||
DetectionCategory::RECONNAISSANCE => 'reconnaissance_anomaly',
|
||||
DetectionCategory::POLICY_VIOLATION => 'policy_violation_anomaly',
|
||||
default => 'system_anomaly'
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Map WAF Detection Severity to String
|
||||
*/
|
||||
private function mapSeverityToString(DetectionSeverity $severity): string
|
||||
{
|
||||
return match ($severity) {
|
||||
DetectionSeverity::CRITICAL => 'critical',
|
||||
DetectionSeverity::HIGH => 'high',
|
||||
DetectionSeverity::MEDIUM => 'medium',
|
||||
DetectionSeverity::LOW => 'low',
|
||||
DetectionSeverity::INFO => 'info'
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Create OWASP Event Identifier from WAF Detection
|
||||
*/
|
||||
public function createOWASPEventIdentifier(Detection $detection): OWASPEventIdentifier
|
||||
{
|
||||
return match ($detection->category) {
|
||||
DetectionCategory::SQL_INJECTION => OWASPEventIdentifier::maliciousInput('sql_injection'),
|
||||
DetectionCategory::XSS => OWASPEventIdentifier::maliciousInput('xss'),
|
||||
DetectionCategory::COMMAND_INJECTION => OWASPEventIdentifier::maliciousInput('command_injection'),
|
||||
DetectionCategory::AUTHENTICATION_BYPASS,
|
||||
DetectionCategory::BRUTE_FORCE => OWASPEventIdentifier::authenticationFailure('anonymous'),
|
||||
DetectionCategory::SESSION_HIJACKING => OWASPEventIdentifier::sessionHijacking('anonymous'),
|
||||
DetectionCategory::PRIVILEGE_ESCALATION => OWASPEventIdentifier::privilegeEscalation('anonymous', 'user', 'admin'),
|
||||
DetectionCategory::MALICIOUS_FILE_UPLOAD => OWASPEventIdentifier::fileUploadFailure('suspicious_file'),
|
||||
DetectionCategory::DOS_ATTACK,
|
||||
DetectionCategory::DDOS_ATTACK => OWASPEventIdentifier::systemAnomaly('denial_of_service'),
|
||||
default => OWASPEventIdentifier::systemAnomaly($detection->category->value)
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Map WAF Detection Severity to OWASP Log Level
|
||||
*/
|
||||
public function mapToOWASPLogLevel(Detection $detection): OWASPLogLevel
|
||||
{
|
||||
return match ($detection->severity) {
|
||||
DetectionSeverity::CRITICAL => OWASPLogLevel::FATAL,
|
||||
DetectionSeverity::HIGH => OWASPLogLevel::ERROR,
|
||||
DetectionSeverity::MEDIUM => OWASPLogLevel::WARN,
|
||||
DetectionSeverity::LOW => OWASPLogLevel::INFO,
|
||||
DetectionSeverity::INFO => OWASPLogLevel::DEBUG
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine XSS type from payload
|
||||
*/
|
||||
private function determineXssType(string $payload): string
|
||||
{
|
||||
$payload = strtolower($payload);
|
||||
|
||||
if (str_contains($payload, '<script') || str_contains($payload, 'javascript:')) {
|
||||
return 'stored_xss';
|
||||
} elseif (str_contains($payload, 'onload=') || str_contains($payload, 'onerror=') ||
|
||||
str_contains($payload, 'onclick=') || str_contains($payload, 'onmouse')) {
|
||||
return 'reflected_xss';
|
||||
} elseif (str_contains($payload, 'document.') || str_contains($payload, 'window.')) {
|
||||
return 'dom_xss';
|
||||
}
|
||||
|
||||
return 'generic_xss';
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user