PHP项目日志审计与SIEM

wen PHP项目 3

PHP项目日志审计与SIEM集成方案

日志审计基础架构

日志收集层级

应用层(PHP) → 系统层(文件/数据库) → 集中收集(Filebeat/Logstash) → 存储(Elasticsearch) → 分析(SIEM)

关键日志类型

// 1. 应用操作日志
class AuditLogger {
    public static function log($user, $action, $resource, $detail) {
        $entry = [
            'timestamp' => date('c'),
            'user_id' => $user->id ?? 'anonymous',
            'user_ip' => $_SERVER['REMOTE_ADDR'] ?? '',
            'session_id' => session_id(),
            'action' => $action, // create, read, update, delete, login, export
            'resource' => $resource, // user, order, payment
            'resource_id' => $detail['id'] ?? null,
            'detail' => json_encode($detail),
            'user_agent' => $_SERVER['HTTP_USER_AGENT'] ?? '',
            'request_method' => $_SERVER['REQUEST_METHOD'],
            'request_uri' => $_SERVER['REQUEST_URI']
        ];
        self::writeLog($entry);
    }
}

日志输出实现

结构化日志格式

class StructuredLog {
    const LOG_FORMAT = 'json'; // 使用JSON便于SIEM解析
    public function format($level, $message, array $context = []) {
        $log = [
            '@timestamp' => date('c'),
            'level' => $level,
            'message' => $message,
            'app_name' => env('APP_NAME'),
            'environment' => env('APP_ENV'),
            'hostname' => gethostname(),
            'pid' => getmypid(),
            'memory_usage' => memory_get_usage(true)
        ];
        return array_merge($log, $context);
    }
}

多通道日志输出

// 使用Monolog的多处理器
$logger = new Logger('app');
$logger->pushHandler(new StreamHandler('php://stderr', Logger::DEBUG));
// JSON格式处理器
$jsonHandler = new StreamHandler(storage_path('logs/audit-' . date('Y-m-d') . '.log'));
$jsonHandler->setFormatter(new JsonFormatter());
$logger->pushHandler($jsonHandler);
// UDP/Syslog转发
$syslogHandler = new SyslogUdpHandler('siem-server.local', 514);
$logger->pushHandler($syslogHandler);

安全事件监控指标

关键审计指标

class SecurityMetrics {
    const METRICS = [
        // 认证相关
        'failed_logins' => ['threshold' => 5, 'time_window' => 300],
        'account_lockouts' => ['threshold' => 1, 'time_window' => 3600],
        'password_resets' => ['threshold' => 3, 'time_window' => 600],
        // 数据访问
        'unauthorized_access' => ['threshold' => 3, 'time_window' => 300],
        'data_exports' => ['threshold' => 10, 'time_window' => 3600],
        'bulk_deletions' => ['threshold' => 5, 'time_window' => 300],
        // API滥用
        'rate_limit_exceeded' => ['threshold' => 100, 'time_window' => 60],
        'invalid_api_keys' => ['threshold' => 10, 'time_window' => 300]
    ];
}

实时告警规则

class AlertRules {
    public static function evaluate($logEntry) {
        $rules = [
            'multiple_failed_logins' => [
                'condition' => function($entry) {
                    return $entry['action'] === 'login_failed' 
                        && $entry['user_id'] !== 'anonymous';
                },
                'aggregation' => ['type' => 'count', 'window' => '5m'],
                'threshold' => 5,
                'severity' => 'high'
            ],
            'data_breach_detection' => [
                'condition' => function($entry) {
                    return in_array($entry['action'], ['export', 'download'])
                        && $entry['resource'] === 'sensitive_data';
                },
                'aggregation' => ['type' => 'count', 'window' => '1h'],
                'threshold' => 10,
                'severity' => 'critical'
            ]
        ];
        foreach ($rules as $rule => $config) {
            if ($config['condition']($logEntry)) {
                self::checkAndAlert($rule, $config, $logEntry);
            }
        }
    }
}

SIEM集成方案

数据发送方式

// 方案一:Filebeat + Logstash (推荐)
filebeat.inputs:
- type: log
  paths:
    - /var/www/html/storage/logs/*.log
  json.keys_under_root: true
  fields_under_root: true
  fields:
    log_type: "php_application"
    environment: "production"
output.logstash:
  hosts: ["logstash:5044"]
// 方案二:直接HTTP/HTTPS发送
class SIEMHttpSender {
    public function send($logEntry) {
        $ch = curl_init(env('SIEM_ENDPOINT'));
        curl_setopt_array($ch, [
            CURLOPT_POST => true,
            CURLOPT_HTTPHEADER => ['Content-Type: application/json'],
            CURLOPT_POSTFIELDS => json_encode($logEntry),
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_TIMEOUT => 5
        ]);
        curl_exec($ch);
        curl_close($ch);
    }
}

日志格式化适配

// 适配常见SIEM格式
class SIEMFormatter {
    // CEF (Common Event Format)
    public function toCEF($log) {
        return sprintf(
            'CEF:0|%s|%s|%s|%s|%s|%s|%s',
            env('APP_NAME'),
            'php-application',
            '1.0',
            $log['action'],
            $log['resource'],
            $log['severity'],
            $this->formatExtensions($log)
        );
    }
    // LEEF (Log Event Extended Format)
    public function toLEEF($log) {
        $fields = [
            'devTime' => $log['timestamp'],
            'src' => $log['user_ip'],
            'usrName' => $log['user_id'],
            'sev' => $log['severity'],
            'msg' => $log['message']
        ];
        return sprintf(
            'LEEF:1.0|%s|%s|%s|%s|%s',
            env('APP_NAME'),
            'php-application',
            '1.0',
            $log['event_id'],
            http_build_query($fields, '', '\t')
        );
    }
}

审计数据完整性

日志签名与防篡改

class LogIntegrity {
    public function sign($logEntry) {
        $data = json_encode($logEntry);
        $hash = hash_hmac('sha256', $data, env('LOG_SECRET_KEY'));
        return array_merge($logEntry, [
            'hash' => $hash,
            'previous_hash' => $this->getLastHash()
        ]);
    }
    public function verify($logEntry) {
        $hash = $logEntry['hash'];
        $previousHash = $logEntry['previous_hash'];
        unset($logEntry['hash'], $logEntry['previous_hash']);
        $calculatedHash = hash_hmac('sha256', json_encode($logEntry), env('LOG_SECRET_KEY'));
        return hash_equals($hash, $calculatedHash) 
            && $previousHash === $this->getStoredPreviousHash();
    }
}

日志备份策略

class LogRetentionPolicy {
    public static function getConfig() {
        return [
            'hot_storage' => [
                'duration' => '7d',
                'location' => '/var/log/app/hot'
            ],
            'warm_storage' => [
                'duration' => '30d',
                'location' => '/var/log/app/warm'
            ],
            'cold_storage' => [
                'duration' => '365d',
                'location' => 's3://audit-logs/'
            ],
            'encryption' => 'AES-256-GCM',
            'compression' => 'gzip'
        ];
    }
}

KPI与监控指标

指标 目标值 告警阈值 严重级别
日志丢失率 <0.1% >0.5% 严重
日志延迟 <5s >30s 警告
存储使用率 <70% >85% 警告
审计事件处理量 1000/s >5000/s 严重
告警准确率 >95% <90% 中等

实施建议

  1. 渐进式迁移:先审计关键操作(登录、支付、权限变更)
  2. 性能优化:使用异步日志写入,避免阻塞
  3. 成本控制:设置合理的日志保留周期和采样比例
  4. 合规性:确保符合PCI DSS、HIPAA等标准要求
  5. 测试验证:模拟攻击场景验证审计覆盖率

常见问题处理

// 性能问题:使用环形缓冲区
class RingBufferLogger {
    private $buffer = [];
    private $maxSize = 10000;
    public function log($entry) {
        if (count($this->buffer) >= $this->maxSize) {
            array_shift($this->buffer); // 移除最旧的日志
        }
        $this->buffer[] = $entry;
        // 异步批量写入
        if (count($this->buffer) % 100 === 0) {
            dispatch(new BatchLogWriter($this->buffer));
        }
    }
}

方案提供了PHP项目与SIEM系统集成的完整实现路径,可根据实际规模和需求选择合适的方案组合。

PHP项目日志审计与SIEM

抱歉,评论功能暂时关闭!