espilon-source/tools/C3PO/hp_dashboard/static/hp/js/mitre.js
Eun0us 79c2a4d4bf c3po: full server rewrite with modular routes and honeypot dashboard
Replace monolithic CLI and web server with route-based Flask API.
New routes: api_commands, api_build, api_can, api_monitor, api_ota,
api_tunnel. Add honeypot security dashboard with real-time SSE,
MITRE ATT&CK mapping, kill chain analysis.

New TUI with commander/help modules. Add session management,
tunnel proxy core, CAN bus data store. Docker support.
2026-02-28 20:12:27 +01:00

123 lines
5.7 KiB
JavaScript

/* 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 += '<div class="mitre-summary">';
html += '<div class="mitre-stat"><span class="mitre-stat-val text-accent">' + totalTechniques + '</span><span class="mitre-stat-label">Techniques</span></div>';
html += '<div class="mitre-stat"><span class="mitre-stat-val" style="color:#fbbf24">' + totalTactics + '</span><span class="mitre-stat-label">Tactics</span></div>';
html += '<div class="mitre-stat"><span class="mitre-stat-val text-crit">' + totalHits + '</span><span class="mitre-stat-label">Total Hits</span></div>';
html += '<div class="mitre-stat"><span class="mitre-stat-val" style="color:#4ade80">' + Math.round(totalTactics / TACTICS.length * 100) + '%</span><span class="mitre-stat-label">Coverage</span></div>';
html += '</div>';
// Matrix grid
html += '<div class="mitre-matrix">';
TACTICS.forEach(function(tactic) {
var techs = byTactic[tactic];
var tacticCount = tactics[tactic] || 0;
var hasHits = tacticCount > 0;
html += '<div class="mitre-col' + (hasHits ? ' active' : '') + '">';
html += '<div class="mitre-tactic-header">';
html += '<div class="mitre-tactic-name">' + escHtml(tactic) + '</div>';
if (hasHits) {
html += '<div class="mitre-tactic-count">' + tacticCount + '</div>';
}
html += '</div>';
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 += '<div class="mitre-technique" style="background:' + bg + '" title="' + escHtml(t.id + ': ' + t.name + ' (' + t.count + ' hits)') + '">';
html += '<div class="mitre-tech-id">' + escHtml(t.id) + '</div>';
html += '<div class="mitre-tech-name">' + escHtml(t.name) + '</div>';
html += '<div class="mitre-tech-count">' + t.count + '</div>';
html += '</div>';
});
} else {
html += '<div class="mitre-technique empty">No coverage</div>';
}
html += '</div>';
});
html += '</div>';
ml.innerHTML = html;
}