/* ESPILON Honeypot Dashboard — MITRE ATT&CK Matrix */ import { $id, escHtml, emptyState, skeletonRows } from './utils.js'; import { api } from './api.js'; // MITRE ATT&CK tactics in kill chain order var TACTICS = [ 'Reconnaissance', 'Resource Development', 'Initial Access', 'Execution', 'Persistence', 'Credential Access', 'Discovery', 'Lateral Movement', 'Collection', 'Command and Control', 'Exfiltration', 'Impact' ]; // Technique metadata: id -> { name, tactic } var TECHNIQUES = { 'T1498.001': { name: 'Direct Network Flood', tactic: 'Impact' }, 'T1595.001': { name: 'Scanning IP Blocks', tactic: 'Reconnaissance' }, 'T1557.002': { name: 'ARP Cache Poisoning', tactic: 'Credential Access' }, 'T1557': { name: 'Adversary-in-the-Middle', tactic: 'Credential Access' }, 'T1046': { name: 'Network Service Discovery', tactic: 'Discovery' }, 'T1018': { name: 'Remote System Discovery', tactic: 'Discovery' }, 'T1021': { name: 'Remote Services', tactic: 'Lateral Movement' }, 'T1110': { name: 'Brute Force', tactic: 'Credential Access' }, 'T1059': { name: 'Command Interpreter', tactic: 'Execution' }, 'T1059.004': { name: 'Unix Shell', tactic: 'Execution' }, 'T1059.006': { name: 'Python', tactic: 'Execution' }, 'T1190': { name: 'Exploit Public-Facing App', tactic: 'Initial Access' }, 'T1071.001': { name: 'Web Protocols', tactic: 'Command and Control' }, 'T1071.004': { name: 'DNS', tactic: 'Command and Control' }, 'T1083': { name: 'File and Directory Discovery', tactic: 'Discovery' }, 'T1005': { name: 'Data from Local System', tactic: 'Collection' }, 'T1105': { name: 'Ingress Tool Transfer', tactic: 'Command and Control' }, 'T1048.003': { name: 'Exfil Over Non-C2', tactic: 'Exfiltration' }, 'T1583.005': { name: 'Botnet', tactic: 'Resource Development' }, 'T1053': { name: 'Scheduled Task/Job', tactic: 'Persistence' }, 'T1020': { name: 'Automated Exfiltration', tactic: 'Exfiltration' }, 'T1565.001': { name: 'Stored Data Manipulation', tactic: 'Impact' } }; // ── Render MITRE Tab ──────────────────────────────────────── export async function renderMitre() { var ml = $id('main-list'); if (!ml) return; ml.innerHTML = skeletonRows(6); var data = await api('/api/honeypot/mitre'); if (!data || !data.techniques || Object.keys(data.techniques).length === 0) { ml.innerHTML = emptyState('🛡', 'No MITRE ATT&CK coverage yet', 'Events will be mapped to techniques as they arrive'); return; } var techniques = data.techniques; var tactics = data.tactics; var maxCount = 0; for (var k in techniques) { if (techniques[k] > maxCount) maxCount = techniques[k]; } // Group techniques by tactic var byTactic = {}; TACTICS.forEach(function(t) { byTactic[t] = []; }); for (var tid in techniques) { var meta = TECHNIQUES[tid]; if (meta) { byTactic[meta.tactic].push({ id: tid, name: meta.name, count: techniques[tid] }); } } // Summary stats var totalTechniques = Object.keys(techniques).length; var totalTactics = Object.keys(tactics).length; var totalHits = 0; for (var t in techniques) totalHits += techniques[t]; var html = ''; // Summary cards html += '
'; html += '
' + totalTechniques + 'Techniques
'; html += '
' + totalTactics + 'Tactics
'; html += '
' + totalHits + 'Total Hits
'; html += '
' + Math.round(totalTactics / TACTICS.length * 100) + '%Coverage
'; html += '
'; // Matrix grid html += '
'; TACTICS.forEach(function(tactic) { var techs = byTactic[tactic]; var tacticCount = tactics[tactic] || 0; var hasHits = tacticCount > 0; html += '
'; html += '
'; html += '
' + escHtml(tactic) + '
'; if (hasHits) { html += '
' + tacticCount + '
'; } html += '
'; if (techs.length > 0) { techs.sort(function(a, b) { return b.count - a.count; }); techs.forEach(function(t) { var intensity = Math.min(t.count / Math.max(maxCount, 1), 1); var hue = 270 - intensity * 270; // purple(270) -> red(0) as intensity increases var bg = 'hsla(' + hue + ', 70%, 50%, ' + (0.15 + intensity * 0.35) + ')'; html += '
'; html += '
' + escHtml(t.id) + '
'; html += '
' + escHtml(t.name) + '
'; html += '
' + t.count + '
'; html += '
'; }); } else { html += '
No coverage
'; } html += '
'; }); html += '
'; ml.innerHTML = html; }