File size: 3,674 Bytes
7226ab4
 
 
 
486e814
7226ab4
486e814
 
 
 
 
 
 
 
 
 
 
 
7226ab4
 
486e814
1fdbae7
486e814
 
 
 
 
7226ab4
 
1fdbae7
 
7226ab4
 
 
 
 
486e814
 
7226ab4
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
486e814
7226ab4
 
 
 
 
 
 
486e814
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
7226ab4
 
 
486e814
 
 
7226ab4
 
 
 
 
 
 
 
 
486e814
7226ab4
486e814
 
 
7226ab4
486e814
7226ab4
 
486e814
7226ab4
486e814
 
7226ab4
486e814
 
7226ab4
 
486e814
7226ab4
486e814
7226ab4
486e814
7226ab4
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
const fs = require('fs');
const path = require('path');

class SecurityLogger {
  constructor(config = {}) {
    this.config = config;

    /**
     * Detecta ambiente
     * HF Spaces → filesystem root read-only
     * Railway / Docker → usar volume persistente
     */
    const isHF = !!process.env.SPACE_ID;
    const basePath = isHF
      ? '/tmp/akira_data'
      : process.env.DATA_PATH || path.resolve('data');

    this.logsPath = path.join(basePath, 'security_logs');
    this.alertsPath = path.join(this.logsPath, 'alerts.json');
    this.opsPath = path.join(this.logsPath, 'operations.json');

    try {
      fs.mkdirSync(this.logsPath, { recursive: true });
      console.log(`✅ SecurityLogger: Diretório ativo: ${this.logsPath}`);
    } catch (err) {
      console.error('❌ SecurityLogger: Falha ao criar diretório:', err.message);
      this.logsPath = null;
    }

    this.operations = this.logsPath ? this._loadJSON(this.opsPath, []) : [];
    this.alerts = this.logsPath ? this._loadJSON(this.alertsPath, []) : [];

    console.log('✅ SecurityLogger inicializado');
  }

  logOperation(operacao) {
    if (!this.logsPath) return;

    try {
      const entry = {
        id: `${Date.now()}_${Math.random().toString(36).slice(2, 9)}`,
        timestamp: new Date().toISOString(),
        usuario: operacao.usuario || 'UNKNOWN',
        tipoOperacao: operacao.tipo,
        alvo: operacao.alvo,
        resultado: operacao.resultado,
        risco: operacao.risco || 'BAIXO',
        detalhes: operacao.detalhes || {},
        ipOrigem: operacao.ipOrigem || 'N/A',
        duracao: operacao.duracao || 0
      };

      this.operations.push(entry);
      this._saveJSON(this.opsPath, this.operations);

      if (this._isSuspicious(entry)) {
        this._createAlert(entry);
      }

      console.log(`📋 [SECURITY] ${entry.tipoOperacao}${entry.alvo}`);
      return entry;
    } catch (e) {
      console.error('Erro ao logar operação:', e);
    }
  }

  _createAlert(operacao) {
    const alert = {
      id: `alert_${Date.now()}`,
      timestamp: new Date().toISOString(),
      severidade: 'ALTO',
      operacaoId: operacao.id,
      usuario: operacao.usuario,
      descricao: `Operação suspeita: ${operacao.tipoOperacao}`,
      motivo: this._getSuspiciousReason(operacao),
      status: 'NOVO'
    };

    this.alerts.push(alert);
    this._saveJSON(this.alertsPath, this.alerts);

    console.log(`🚨 [SECURITY ALERT] ${alert.descricao}`);
    return alert;
  }

  _isSuspicious(operacao) {
    const recentOps = this.operations.filter(o =>
      new Date(operacao.timestamp) - new Date(o.timestamp) < 60000
    );

    if (recentOps.length > 5) return true;
    if (operacao.tipoOperacao === 'NMAP_SCAN' && operacao.risco === 'ALTO') return true;
    if (operacao.tipoOperacao === 'SQLMAP_TEST' && operacao.resultado === 'VULNERÁVEL') return true;

    return false;
  }

  _getSuspiciousReason(operacao) {
    const reasons = [];

    if (operacao.tipoOperacao === 'NMAP_SCAN') reasons.push('Port scan');
    if (operacao.tipoOperacao === 'SQLMAP_TEST') reasons.push('SQL Injection');
    if (operacao.risco === 'CRÍTICO') reasons.push('Risco crítico');

    return reasons.join(', ') || 'Atividade incomum';
  }

  _loadJSON(file, fallback) {
    try {
      if (fs.existsSync(file)) {
        return JSON.parse(fs.readFileSync(file, 'utf8'));
      }
    } catch {}
    return fallback;
  }

  _saveJSON(file, data) {
    try {
      fs.writeFileSync(file, JSON.stringify(data, null, 2));
    } catch (e) {
      console.error(`Erro ao salvar ${file}:`, e.message);
    }
  }
}

module.exports = SecurityLogger;