akra35567 commited on
Commit
486e814
Β·
verified Β·
1 Parent(s): 9124c31

Update modules/SecurityLogger.js

Browse files
Files changed (1) hide show
  1. modules/SecurityLogger.js +54 -203
modules/SecurityLogger.js CHANGED
@@ -1,66 +1,41 @@
1
- /**
2
- * ═══════════════════════════════════════════════════════════════════════════
3
- * SECURITY LOGGER - LOG DETALHADO DE OPERAÇÕES DE CYBERSECURITY
4
- * ═══════════════════════════════════════════════════════════════════════════
5
- * βœ… Registra todas as operaΓ§Γ΅es com timestamps
6
- * βœ… Armazena em database segura
7
- * βœ… Fornece relatΓ³rios de auditoria
8
- * βœ… Detecta atividade suspeita
9
- * βœ… IntegraΓ§Γ£o com alertas
10
- * ═══════════════════════════════════════════════════════════════════════════
11
- */
12
-
13
  const fs = require('fs');
14
  const path = require('path');
15
 
16
  class SecurityLogger {
17
- constructor(config) {
18
  this.config = config;
19
-
20
- // ═══════════════════════════════════════════════════════════════════
21
- // HF SPACES: Usar /tmp para garantir permissΓ΅es de escrita
22
- // O HF Spaces tem sistema de arquivos somente-leitura em /
23
- // ═══════════════════════════════════════════════════════════════════
24
-
25
- // ForΓ§ar uso de /tmp no HF Spaces (sistema read-only)
26
- this.logsPath = '/tmp/akira_data/security_logs';
 
 
 
 
27
  this.alertsPath = path.join(this.logsPath, 'alerts.json');
28
  this.opsPath = path.join(this.logsPath, 'operations.json');
29
-
30
- // Cria diretΓ³rios com tratamento de erro
31
  try {
32
- if (!fs.existsSync(this.logsPath)) {
33
- fs.mkdirSync(this.logsPath, { recursive: true });
34
- console.log(`βœ… SecurityLogger: DiretΓ³rio criado: ${this.logsPath}`);
35
- }
36
- } catch (error) {
37
- console.warn(`⚠️ SecurityLogger: Não foi possível criar diretório em ${this.logsPath}:`, error.message);
38
-
39
- // Fallback para /tmp direto
40
- const tmpPath = '/tmp/security_logs';
41
- try {
42
- fs.mkdirSync(tmpPath, { recursive: true });
43
- this.logsPath = tmpPath;
44
- this.alertsPath = path.join(this.logsPath, 'alerts.json');
45
- this.opsPath = path.join(this.logsPath, 'operations.json');
46
- console.log(`βœ… SecurityLogger: Usando fallback: ${this.logsPath}`);
47
- } catch (fallbackError) {
48
- console.error('❌ SecurityLogger: Erro crítico ao criar diretório:', fallbackError.message);
49
- this.logsPath = null;
50
- }
51
  }
52
 
53
- // Carrega logs
54
  this.operations = this.logsPath ? this._loadJSON(this.opsPath, []) : [];
55
  this.alerts = this.logsPath ? this._loadJSON(this.alertsPath, []) : [];
56
 
57
  console.log('βœ… SecurityLogger inicializado');
58
  }
59
 
60
- /**
61
- * Registra operaΓ§Γ£o de cybersecurity
62
- */
63
  logOperation(operacao) {
 
 
64
  try {
65
  const entry = {
66
  id: `${Date.now()}_${Math.random().toString(36).slice(2, 9)}`,
@@ -75,199 +50,75 @@ class SecurityLogger {
75
  duracao: operacao.duracao || 0
76
  };
77
 
78
- // Adiciona ao log
79
  this.operations.push(entry);
80
  this._saveJSON(this.opsPath, this.operations);
81
 
82
- // Verifica se Γ© atividade suspeita
83
  if (this._isSuspicious(entry)) {
84
  this._createAlert(entry);
85
  }
86
 
87
- console.log(`πŸ“‹ [SECURITY LOG] ${entry.tipoOperacao} em ${entry.alvo}`);
88
  return entry;
89
  } catch (e) {
90
  console.error('Erro ao logar operaΓ§Γ£o:', e);
91
  }
92
  }
93
 
94
- /**
95
- * Cria alerta de atividade suspeita
96
- */
97
  _createAlert(operacao) {
98
- try {
99
- const alert = {
100
- id: `alert_${Date.now()}`,
101
- timestamp: new Date().toISOString(),
102
- severidade: 'ALTO',
103
- operacaoId: operacao.id,
104
- usuario: operacao.usuario,
105
- descricao: `OperaΓ§Γ£o suspeita: ${operacao.tipoOperacao} em ${operacao.alvo}`,
106
- motivo: this._getSuspiciousReason(operacao),
107
- status: 'NOVO'
108
- };
109
-
110
- this.alerts.push(alert);
111
- this._saveJSON(this.alertsPath, this.alerts);
112
-
113
- console.log(`🚨 [ALERT] ${alert.descricao}`);
114
- return alert;
115
- } catch (e) {
116
- console.error('Erro ao criar alerta:', e);
117
- }
118
  }
119
 
120
- /**
121
- * ObtΓ©m relatΓ³rio de operaΓ§Γ΅es
122
- */
123
- getOperationReport(filtros = {}) {
124
- try {
125
- let ops = [...this.operations];
126
-
127
- // Filtra por usuΓ‘rio
128
- if (filtros.usuario) {
129
- ops = ops.filter(o => o.usuario === filtros.usuario);
130
- }
131
-
132
- // Filtra por tipo
133
- if (filtros.tipo) {
134
- ops = ops.filter(o => o.tipoOperacao === filtros.tipo);
135
- }
136
-
137
- // Filtra por perΓ­odo
138
- if (filtros.dataInicio && filtros.dataFim) {
139
- const inicio = new Date(filtros.dataInicio);
140
- const fim = new Date(filtros.dataFim);
141
- ops = ops.filter(o => {
142
- const data = new Date(o.timestamp);
143
- return data >= inicio && data <= fim;
144
- });
145
- }
146
-
147
- // Agrupa por tipo
148
- const porTipo = {};
149
- const porRisco = {};
150
-
151
- ops.forEach(op => {
152
- porTipo[op.tipoOperacao] = (porTipo[op.tipoOperacao] || 0) + 1;
153
- porRisco[op.risco] = (porRisco[op.risco] || 0) + 1;
154
- });
155
-
156
- return {
157
- totalOperacoes: ops.length,
158
- operacoes: ops.slice(-50), // Últimas 50
159
- resumoPorTipo: porTipo,
160
- resumoPorRisco: porRisco,
161
- operaçáesSuspeitas: ops.filter(o => o.risco === 'ALTO' || o.risco === 'CRÍTICO').length
162
- };
163
- } catch (e) {
164
- console.error('Erro ao gerar relatΓ³rio:', e);
165
- return { erro: e.message };
166
- }
167
- }
168
-
169
- /**
170
- * ObtΓ©m relatΓ³rio de alertas
171
- */
172
- getAlertReport() {
173
- try {
174
- const alertasNovos = this.alerts.filter(a => a.status === 'NOVO');
175
- const alertasResolvidos = this.alerts.filter(a => a.status === 'RESOLVIDO');
176
-
177
- return {
178
- totalAlertas: this.alerts.length,
179
- alertasNovos: alertasNovos.length,
180
- alertasResolvidos: alertasResolvidos.length,
181
- ultimos: this.alerts.slice(-20)
182
- };
183
- } catch (e) {
184
- return { erro: e.message };
185
- }
186
- }
187
-
188
- /**
189
- * Marca alerta como resolvido
190
- */
191
- resolveAlert(alertId) {
192
- try {
193
- const alert = this.alerts.find(a => a.id === alertId);
194
- if (alert) {
195
- alert.status = 'RESOLVIDO';
196
- alert.resolvidoEm = new Date().toISOString();
197
- this._saveJSON(this.alertsPath, this.alerts);
198
- return true;
199
- }
200
- return false;
201
- } catch (e) {
202
- return false;
203
- }
204
- }
205
-
206
- /**
207
- * DetecΓ§Γ£o de atividade suspeita
208
- */
209
  _isSuspicious(operacao) {
210
- // OperaΓ§Γ΅es em mΓΊltiplos domΓ­nios em curto espaΓ§o
211
- const recentOps = this.operations.filter(o => {
212
- const timeDiff = new Date(operacao.timestamp) - new Date(o.timestamp);
213
- return timeDiff < 60000; // ΓΊltimos 60s
214
- });
215
 
216
  if (recentOps.length > 5) return true;
217
-
218
- // Scan agressivo
219
  if (operacao.tipoOperacao === 'NMAP_SCAN' && operacao.risco === 'ALTO') return true;
220
-
221
- // MΓΊltiplas tentativas de SQL injection
222
  if (operacao.tipoOperacao === 'SQLMAP_TEST' && operacao.resultado === 'VULNERÁVEL') return true;
223
 
224
- // Breach search repetido
225
- if (operacao.tipoOperacao === 'BREACH_SEARCH') {
226
- const recent = recentOps.filter(o => o.tipoOperacao === 'BREACH_SEARCH');
227
- if (recent.length > 3) return true;
228
- }
229
-
230
  return false;
231
  }
232
 
233
  _getSuspiciousReason(operacao) {
234
- const razoes = [];
235
 
236
- if (operacao.tipoOperacao === 'NMAP_SCAN') {
237
- razoes.push('Port scan detectado');
238
- }
239
 
240
- if (operacao.tipoOperacao === 'SQLMAP_TEST') {
241
- razoes.push('Teste de SQL Injection');
242
- }
243
-
244
- if (operacao.risco === 'CRÍTICO') {
245
- razoes.push('Risco crΓ­tico detectado');
246
- }
247
-
248
- return razoes.length > 0 ? razoes.join(', ') : 'Atividade incomum';
249
  }
250
 
251
- /**
252
- * FUNÇÕES AUXILIARES
253
- */
254
-
255
- _loadJSON(filepath, defaultValue = {}) {
256
  try {
257
- if (fs.existsSync(filepath)) {
258
- return JSON.parse(fs.readFileSync(filepath, 'utf8'));
259
  }
260
- } catch (e) {
261
- console.warn(`Erro ao carregar ${filepath}:`, e);
262
- }
263
- return defaultValue;
264
  }
265
 
266
- _saveJSON(filepath, data) {
267
  try {
268
- fs.writeFileSync(filepath, JSON.stringify(data, null, 2));
269
  } catch (e) {
270
- console.error(`Erro ao salvar ${filepath}:`, e);
271
  }
272
  }
273
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  const fs = require('fs');
2
  const path = require('path');
3
 
4
  class SecurityLogger {
5
+ constructor(config = {}) {
6
  this.config = config;
7
+
8
+ /**
9
+ * Detecta ambiente
10
+ * HF Spaces β†’ filesystem root read-only
11
+ * Railway / Docker β†’ usar volume persistente
12
+ */
13
+ const isHF = !!process.env.SPACE_ID;
14
+ const basePath = isHF
15
+ ? '/tmp/akira_data'
16
+ : process.env.DATA_PATH || path.resolve('data');
17
+
18
+ this.logsPath = path.join(basePath, 'security_logs');
19
  this.alertsPath = path.join(this.logsPath, 'alerts.json');
20
  this.opsPath = path.join(this.logsPath, 'operations.json');
21
+
 
22
  try {
23
+ fs.mkdirSync(this.logsPath, { recursive: true });
24
+ console.log(`βœ… SecurityLogger: DiretΓ³rio ativo: ${this.logsPath}`);
25
+ } catch (err) {
26
+ console.error('❌ SecurityLogger: Falha ao criar diretório:', err.message);
27
+ this.logsPath = null;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
28
  }
29
 
 
30
  this.operations = this.logsPath ? this._loadJSON(this.opsPath, []) : [];
31
  this.alerts = this.logsPath ? this._loadJSON(this.alertsPath, []) : [];
32
 
33
  console.log('βœ… SecurityLogger inicializado');
34
  }
35
 
 
 
 
36
  logOperation(operacao) {
37
+ if (!this.logsPath) return;
38
+
39
  try {
40
  const entry = {
41
  id: `${Date.now()}_${Math.random().toString(36).slice(2, 9)}`,
 
50
  duracao: operacao.duracao || 0
51
  };
52
 
 
53
  this.operations.push(entry);
54
  this._saveJSON(this.opsPath, this.operations);
55
 
 
56
  if (this._isSuspicious(entry)) {
57
  this._createAlert(entry);
58
  }
59
 
60
+ console.log(`πŸ“‹ [SECURITY] ${entry.tipoOperacao} β†’ ${entry.alvo}`);
61
  return entry;
62
  } catch (e) {
63
  console.error('Erro ao logar operaΓ§Γ£o:', e);
64
  }
65
  }
66
 
 
 
 
67
  _createAlert(operacao) {
68
+ const alert = {
69
+ id: `alert_${Date.now()}`,
70
+ timestamp: new Date().toISOString(),
71
+ severidade: 'ALTO',
72
+ operacaoId: operacao.id,
73
+ usuario: operacao.usuario,
74
+ descricao: `OperaΓ§Γ£o suspeita: ${operacao.tipoOperacao}`,
75
+ motivo: this._getSuspiciousReason(operacao),
76
+ status: 'NOVO'
77
+ };
78
+
79
+ this.alerts.push(alert);
80
+ this._saveJSON(this.alertsPath, this.alerts);
81
+
82
+ console.log(`🚨 [SECURITY ALERT] ${alert.descricao}`);
83
+ return alert;
 
 
 
 
84
  }
85
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
86
  _isSuspicious(operacao) {
87
+ const recentOps = this.operations.filter(o =>
88
+ new Date(operacao.timestamp) - new Date(o.timestamp) < 60000
89
+ );
 
 
90
 
91
  if (recentOps.length > 5) return true;
 
 
92
  if (operacao.tipoOperacao === 'NMAP_SCAN' && operacao.risco === 'ALTO') return true;
 
 
93
  if (operacao.tipoOperacao === 'SQLMAP_TEST' && operacao.resultado === 'VULNERÁVEL') return true;
94
 
 
 
 
 
 
 
95
  return false;
96
  }
97
 
98
  _getSuspiciousReason(operacao) {
99
+ const reasons = [];
100
 
101
+ if (operacao.tipoOperacao === 'NMAP_SCAN') reasons.push('Port scan');
102
+ if (operacao.tipoOperacao === 'SQLMAP_TEST') reasons.push('SQL Injection');
103
+ if (operacao.risco === 'CRÍTICO') reasons.push('Risco crítico');
104
 
105
+ return reasons.join(', ') || 'Atividade incomum';
 
 
 
 
 
 
 
 
106
  }
107
 
108
+ _loadJSON(file, fallback) {
 
 
 
 
109
  try {
110
+ if (fs.existsSync(file)) {
111
+ return JSON.parse(fs.readFileSync(file, 'utf8'));
112
  }
113
+ } catch {}
114
+ return fallback;
 
 
115
  }
116
 
117
+ _saveJSON(file, data) {
118
  try {
119
+ fs.writeFileSync(file, JSON.stringify(data, null, 2));
120
  } catch (e) {
121
+ console.error(`Erro ao salvar ${file}:`, e.message);
122
  }
123
  }
124
  }