secubox-openwrt/package/secubox/luci-app-secubox-p2p/htdocs/luci-static/resources/view/secubox-p2p/threat-hub.js
CyberMind-FR e58f479cd4 feat(waf): Update WAF scenarios with 2024-2025 CVEs and OWASP threats
Add detection patterns for latest actively exploited vulnerabilities:
- CVE-2025-55182 (React2Shell, CVSS 10.0)
- CVE-2025-8110 (Gogs RCE), CVE-2025-53770 (SharePoint)
- CVE-2025-52691 (SmarterMail), CVE-2025-40551 (SolarWinds)
- CVE-2024-47575 (FortiManager), CVE-2024-21887 (Ivanti)
- CVE-2024-3400, CVE-2024-0012, CVE-2024-9474 (PAN-OS)

New attack categories based on OWASP Top 10 2025:
- HTTP Request Smuggling (TE.CL/CL.TE conflicts)
- AI/LLM Prompt Injection (ChatML, instruction markers)
- WAF Bypass techniques (Unicode normalization, double encoding)
- Supply Chain attacks (CI/CD poisoning, dependency confusion)
- Extended SSTI (Jinja2, Freemarker, Velocity, Thymeleaf)
- API Abuse (BOLA/IDOR, mass assignment)

CrowdSec scenarios split into 11 separate files for reliability.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-12 05:02:57 +01:00

408 lines
16 KiB
JavaScript

'use strict';
'require view';
'require ui';
'require dom';
'require poll';
'require request';
'require secubox/kiss-theme';
var API_BASE = window.location.protocol + '//' + window.location.hostname + ':7331/api/threat-intel';
function fetchJSON(endpoint) {
return request.get(API_BASE + '/' + endpoint, { timeout: 10000 })
.then(function(res) {
try { return res.json(); }
catch(e) { return null; }
})
.catch(function() { return null; });
}
function postJSON(endpoint) {
return request.post(API_BASE + '/' + endpoint, null, { timeout: 15000 })
.then(function(res) {
try { return res.json(); }
catch(e) { return null; }
})
.catch(function() { return null; });
}
function timeAgo(ts) {
if (!ts || ts === 0) return 'Never';
var now = Math.floor(Date.now() / 1000);
var diff = now - ts;
if (diff < 60) return diff + 's ago';
if (diff < 3600) return Math.floor(diff / 60) + 'm ago';
if (diff < 86400) return Math.floor(diff / 3600) + 'h ago';
return Math.floor(diff / 86400) + 'd ago';
}
function severityBadge(severity) {
var colors = {
critical: '#e74c3c',
high: '#e67e22',
medium: '#f1c40f',
low: '#3498db'
};
var color = colors[severity] || '#95a5a6';
return E('span', {
'style': 'display:inline-block;padding:2px 8px;border-radius:4px;font-size:11px;font-weight:bold;color:#fff;background:' + color
}, severity || 'unknown');
}
function trustBadge(trust) {
var colors = {
direct: '#27ae60',
transitive: '#f39c12',
unknown: '#95a5a6',
self: '#3498db'
};
var icons = {
direct: '\u2714',
transitive: '\u2194',
unknown: '?',
self: '\u2605'
};
var color = colors[trust] || '#95a5a6';
return E('span', {
'style': 'display:inline-block;padding:2px 8px;border-radius:4px;font-size:11px;font-weight:bold;color:#fff;background:' + color
}, (icons[trust] || '') + ' ' + (trust || 'unknown'));
}
return view.extend({
status: null,
iocs: [],
peers: [],
load: function() {
return Promise.all([
fetchJSON('status'),
fetchJSON('iocs'),
fetchJSON('peers')
]);
},
render: function(data) {
this.status = data[0] || {};
this.iocs = data[1] || [];
this.peers = data[2] || [];
var self = this;
var content = E('div', { 'class': 'cbi-map', 'style': 'padding:20px;' }, [
this.renderHeader(),
this.renderSummaryCards(),
this.renderActions(),
this.renderPeerTable(),
this.renderIOCTable()
]);
poll.add(function() {
return Promise.all([
fetchJSON('status'),
fetchJSON('iocs'),
fetchJSON('peers')
]).then(function(fresh) {
self.status = fresh[0] || self.status;
self.iocs = fresh[1] || self.iocs;
self.peers = fresh[2] || self.peers;
self.updateCards();
self.updatePeerTable();
self.updateIOCTable();
});
}, 30);
return KissTheme.wrap(content, 'admin/secubox/p2p/threat-hub');
},
renderHeader: function() {
var enabled = this.status.enabled !== false;
return E('div', { 'style': 'margin-bottom:24px;' }, [
E('h2', { 'style': 'margin:0 0 8px;color:#ecf0f1;font-size:24px;' },
'Threat Intelligence Hub'),
E('p', { 'style': 'margin:0;color:#95a5a6;font-size:14px;' },
'Decentralized IOC sharing across mesh nodes via CrowdSec + mitmproxy'),
E('div', { 'style': 'margin-top:8px;' }, [
E('span', {
'style': 'display:inline-block;padding:4px 12px;border-radius:12px;font-size:12px;font-weight:bold;color:#fff;background:' + (enabled ? '#27ae60' : '#e74c3c')
}, enabled ? 'ACTIVE' : 'DISABLED'),
this.status.auto_apply ?
E('span', { 'style': 'display:inline-block;margin-left:8px;padding:4px 12px;border-radius:12px;font-size:12px;color:#fff;background:#2980b9;' }, 'Auto-Apply ON') : null
])
]);
},
renderSummaryCards: function() {
var s = this.status;
var cards = [
{ id: 'card-local', label: 'Local IOCs Shared', value: s.local_iocs || 0, icon: '\uD83D\uDCE4', color: '#3498db' },
{ id: 'card-received', label: 'Received from Mesh', value: s.received_iocs || 0, icon: '\uD83D\uDCE5', color: '#e67e22' },
{ id: 'card-applied', label: 'Applied to Firewall', value: s.applied_iocs || 0, icon: '\uD83D\uDEE1', color: '#27ae60' },
{ id: 'card-peers', label: 'Peer Contributors', value: s.peer_contributors || 0, icon: '\uD83D\uDC65', color: '#9b59b6' },
{ id: 'card-chain', label: 'Chain Blocks', value: s.chain_threat_blocks || 0, icon: '\u26D3', color: '#1abc9c' }
];
return E('div', {
'id': 'summary-cards',
'style': 'display:grid;grid-template-columns:repeat(auto-fill,minmax(180px,1fr));gap:16px;margin-bottom:24px;'
}, cards.map(function(c) {
return E('div', {
'id': c.id,
'style': 'background:rgba(255,255,255,0.05);border:1px solid rgba(255,255,255,0.1);border-radius:12px;padding:16px;text-align:center;border-left:4px solid ' + c.color + ';'
}, [
E('div', { 'style': 'font-size:28px;margin-bottom:4px;' }, c.icon),
E('div', {
'class': 'card-value',
'style': 'font-size:32px;font-weight:bold;color:' + c.color + ';'
}, String(c.value)),
E('div', { 'style': 'font-size:12px;color:#95a5a6;margin-top:4px;' }, c.label)
]);
}));
},
renderActions: function() {
var self = this;
var publishBtn = E('button', {
'class': 'cbi-button cbi-button-action',
'style': 'margin-right:12px;padding:8px 20px;',
'click': function() {
this.disabled = true;
this.textContent = 'Publishing...';
var btn = this;
postJSON('publish').then(function(res) {
btn.disabled = false;
btn.textContent = 'Publish Now';
if (res && res.success)
ui.addNotification(null, E('p', 'Published ' + (res.published || 0) + ' IOCs to chain'), 'info');
else
ui.addNotification(null, E('p', 'Publish failed'), 'error');
});
}
}, 'Publish Now');
var applyBtn = E('button', {
'class': 'cbi-button cbi-button-apply',
'style': 'padding:8px 20px;',
'click': function() {
this.disabled = true;
this.textContent = 'Applying...';
var btn = this;
postJSON('apply').then(function(res) {
btn.disabled = false;
btn.textContent = 'Apply Pending';
if (res && res.success)
ui.addNotification(null, E('p', 'Applied ' + (res.applied || 0) + ' IOCs, skipped ' + (res.skipped || 0)), 'info');
else
ui.addNotification(null, E('p', 'Apply failed'), 'error');
});
}
}, 'Apply Pending');
return E('div', { 'style': 'margin-bottom:24px;padding:16px;background:rgba(255,255,255,0.03);border-radius:8px;border:1px solid rgba(255,255,255,0.08);' }, [
E('h3', { 'style': 'margin:0 0 12px;color:#ecf0f1;font-size:16px;' }, 'Actions'),
E('div', {}, [publishBtn, applyBtn])
]);
},
renderPeerTable: function() {
var peers = this.peers || [];
var rows = peers.map(function(p) {
return E('tr', {}, [
E('td', { 'style': 'padding:8px 12px;border-bottom:1px solid rgba(255,255,255,0.05);font-family:monospace;font-size:13px;color:#ecf0f1;' },
(p.node || '').substring(0, 12) + '...'),
E('td', { 'style': 'padding:8px 12px;border-bottom:1px solid rgba(255,255,255,0.05);' },
trustBadge(p.trust)),
E('td', { 'style': 'padding:8px 12px;border-bottom:1px solid rgba(255,255,255,0.05);color:#ecf0f1;text-align:center;' },
String(p.ioc_count || 0)),
E('td', { 'style': 'padding:8px 12px;border-bottom:1px solid rgba(255,255,255,0.05);color:#ecf0f1;text-align:center;' },
String(p.applied_count || 0)),
E('td', { 'style': 'padding:8px 12px;border-bottom:1px solid rgba(255,255,255,0.05);color:#95a5a6;font-size:12px;' },
timeAgo(p.last_seen))
]);
});
if (rows.length === 0) {
rows = [E('tr', {}, [
E('td', { 'colspan': '5', 'style': 'padding:24px;text-align:center;color:#95a5a6;' },
'No peer contributions yet. IOCs from mesh nodes will appear here after sync.')
])];
}
return E('div', { 'style': 'margin-bottom:24px;' }, [
E('h3', { 'style': 'margin:0 0 12px;color:#ecf0f1;font-size:16px;' }, 'Peer Contributions'),
E('div', { 'style': 'overflow-x:auto;' }, [
E('table', {
'id': 'peer-table',
'class': 'table',
'style': 'width:100%;border-collapse:collapse;background:rgba(255,255,255,0.03);border-radius:8px;border:1px solid rgba(255,255,255,0.08);'
}, [
E('thead', {}, [
E('tr', { 'style': 'background:rgba(255,255,255,0.05);' }, [
E('th', { 'style': 'padding:10px 12px;text-align:left;color:#95a5a6;font-size:12px;text-transform:uppercase;' }, 'Node'),
E('th', { 'style': 'padding:10px 12px;text-align:left;color:#95a5a6;font-size:12px;text-transform:uppercase;' }, 'Trust'),
E('th', { 'style': 'padding:10px 12px;text-align:center;color:#95a5a6;font-size:12px;text-transform:uppercase;' }, 'IOCs'),
E('th', { 'style': 'padding:10px 12px;text-align:center;color:#95a5a6;font-size:12px;text-transform:uppercase;' }, 'Applied'),
E('th', { 'style': 'padding:10px 12px;text-align:left;color:#95a5a6;font-size:12px;text-transform:uppercase;' }, 'Last Seen')
])
]),
E('tbody', {}, rows)
])
])
]);
},
renderIOCTable: function() {
var iocs = this.iocs || [];
var rows = iocs.slice(0, 50).map(function(ioc) {
return E('tr', {}, [
E('td', { 'style': 'padding:8px 12px;border-bottom:1px solid rgba(255,255,255,0.05);font-family:monospace;font-size:13px;color:#ecf0f1;' },
ioc.ip || '-'),
E('td', { 'style': 'padding:8px 12px;border-bottom:1px solid rgba(255,255,255,0.05);' },
severityBadge(ioc.severity)),
E('td', { 'style': 'padding:8px 12px;border-bottom:1px solid rgba(255,255,255,0.05);color:#95a5a6;font-size:12px;' },
ioc.source || '-'),
E('td', { 'style': 'padding:8px 12px;border-bottom:1px solid rgba(255,255,255,0.05);color:#95a5a6;font-size:12px;' },
ioc.scenario || '-'),
E('td', { 'style': 'padding:8px 12px;border-bottom:1px solid rgba(255,255,255,0.05);font-family:monospace;font-size:11px;color:#7f8c8d;' },
(ioc.node || '').substring(0, 12)),
E('td', { 'style': 'padding:8px 12px;border-bottom:1px solid rgba(255,255,255,0.05);' },
trustBadge(ioc.trust)),
E('td', { 'style': 'padding:8px 12px;border-bottom:1px solid rgba(255,255,255,0.05);text-align:center;' },
ioc.applied ?
E('span', { 'style': 'color:#27ae60;font-weight:bold;' }, '\u2714') :
E('span', { 'style': 'color:#95a5a6;' }, '\u2013')),
E('td', { 'style': 'padding:8px 12px;border-bottom:1px solid rgba(255,255,255,0.05);color:#95a5a6;font-size:12px;' },
timeAgo(ioc.ts))
]);
});
if (rows.length === 0) {
rows = [E('tr', {}, [
E('td', { 'colspan': '8', 'style': 'padding:24px;text-align:center;color:#95a5a6;' },
'No IOCs received from mesh yet.')
])];
}
return E('div', {}, [
E('h3', { 'style': 'margin:0 0 4px;color:#ecf0f1;font-size:16px;' }, 'Received IOCs'),
E('p', { 'style': 'margin:0 0 12px;color:#7f8c8d;font-size:12px;' },
'Showing up to 50 most recent. Total: ' + (this.iocs || []).length),
E('div', { 'style': 'overflow-x:auto;' }, [
E('table', {
'id': 'ioc-table',
'class': 'table',
'style': 'width:100%;border-collapse:collapse;background:rgba(255,255,255,0.03);border-radius:8px;border:1px solid rgba(255,255,255,0.08);'
}, [
E('thead', {}, [
E('tr', { 'style': 'background:rgba(255,255,255,0.05);' }, [
E('th', { 'style': 'padding:10px 12px;text-align:left;color:#95a5a6;font-size:12px;text-transform:uppercase;' }, 'IP'),
E('th', { 'style': 'padding:10px 12px;text-align:left;color:#95a5a6;font-size:12px;text-transform:uppercase;' }, 'Severity'),
E('th', { 'style': 'padding:10px 12px;text-align:left;color:#95a5a6;font-size:12px;text-transform:uppercase;' }, 'Source'),
E('th', { 'style': 'padding:10px 12px;text-align:left;color:#95a5a6;font-size:12px;text-transform:uppercase;' }, 'Scenario'),
E('th', { 'style': 'padding:10px 12px;text-align:left;color:#95a5a6;font-size:12px;text-transform:uppercase;' }, 'Origin'),
E('th', { 'style': 'padding:10px 12px;text-align:left;color:#95a5a6;font-size:12px;text-transform:uppercase;' }, 'Trust'),
E('th', { 'style': 'padding:10px 12px;text-align:center;color:#95a5a6;font-size:12px;text-transform:uppercase;' }, 'Applied'),
E('th', { 'style': 'padding:10px 12px;text-align:left;color:#95a5a6;font-size:12px;text-transform:uppercase;' }, 'Age')
])
]),
E('tbody', {}, rows)
])
])
]);
},
updateCards: function() {
var s = this.status || {};
var mapping = {
'card-local': s.local_iocs || 0,
'card-received': s.received_iocs || 0,
'card-applied': s.applied_iocs || 0,
'card-peers': s.peer_contributors || 0,
'card-chain': s.chain_threat_blocks || 0
};
Object.keys(mapping).forEach(function(id) {
var card = document.getElementById(id);
if (card) {
var valEl = card.querySelector('.card-value');
if (valEl) valEl.textContent = String(mapping[id]);
}
});
},
updatePeerTable: function() {
var table = document.getElementById('peer-table');
if (!table) return;
var tbody = table.querySelector('tbody');
if (!tbody) return;
var peers = this.peers || [];
dom.content(tbody, peers.length === 0 ?
E('tr', {}, [
E('td', { 'colspan': '5', 'style': 'padding:24px;text-align:center;color:#95a5a6;' },
'No peer contributions yet.')
]) :
peers.map(function(p) {
return E('tr', {}, [
E('td', { 'style': 'padding:8px 12px;border-bottom:1px solid rgba(255,255,255,0.05);font-family:monospace;font-size:13px;color:#ecf0f1;' },
(p.node || '').substring(0, 12) + '...'),
E('td', { 'style': 'padding:8px 12px;border-bottom:1px solid rgba(255,255,255,0.05);' },
trustBadge(p.trust)),
E('td', { 'style': 'padding:8px 12px;border-bottom:1px solid rgba(255,255,255,0.05);color:#ecf0f1;text-align:center;' },
String(p.ioc_count || 0)),
E('td', { 'style': 'padding:8px 12px;border-bottom:1px solid rgba(255,255,255,0.05);color:#ecf0f1;text-align:center;' },
String(p.applied_count || 0)),
E('td', { 'style': 'padding:8px 12px;border-bottom:1px solid rgba(255,255,255,0.05);color:#95a5a6;font-size:12px;' },
timeAgo(p.last_seen))
]);
})
);
},
updateIOCTable: function() {
var table = document.getElementById('ioc-table');
if (!table) return;
var tbody = table.querySelector('tbody');
if (!tbody) return;
var iocs = (this.iocs || []).slice(0, 50);
var countEl = table.parentNode.parentNode.querySelector('p');
if (countEl) countEl.textContent = 'Showing up to 50 most recent. Total: ' + (this.iocs || []).length;
dom.content(tbody, iocs.length === 0 ?
E('tr', {}, [
E('td', { 'colspan': '8', 'style': 'padding:24px;text-align:center;color:#95a5a6;' },
'No IOCs received from mesh yet.')
]) :
iocs.map(function(ioc) {
return E('tr', {}, [
E('td', { 'style': 'padding:8px 12px;border-bottom:1px solid rgba(255,255,255,0.05);font-family:monospace;font-size:13px;color:#ecf0f1;' },
ioc.ip || '-'),
E('td', { 'style': 'padding:8px 12px;border-bottom:1px solid rgba(255,255,255,0.05);' },
severityBadge(ioc.severity)),
E('td', { 'style': 'padding:8px 12px;border-bottom:1px solid rgba(255,255,255,0.05);color:#95a5a6;font-size:12px;' },
ioc.source || '-'),
E('td', { 'style': 'padding:8px 12px;border-bottom:1px solid rgba(255,255,255,0.05);color:#95a5a6;font-size:12px;' },
ioc.scenario || '-'),
E('td', { 'style': 'padding:8px 12px;border-bottom:1px solid rgba(255,255,255,0.05);font-family:monospace;font-size:11px;color:#7f8c8d;' },
(ioc.node || '').substring(0, 12)),
E('td', { 'style': 'padding:8px 12px;border-bottom:1px solid rgba(255,255,255,0.05);' },
trustBadge(ioc.trust)),
E('td', { 'style': 'padding:8px 12px;border-bottom:1px solid rgba(255,255,255,0.05);text-align:center;' },
ioc.applied ?
E('span', { 'style': 'color:#27ae60;font-weight:bold;' }, '\u2714') :
E('span', { 'style': 'color:#95a5a6;' }, '\u2013')),
E('td', { 'style': 'padding:8px 12px;border-bottom:1px solid rgba(255,255,255,0.05);color:#95a5a6;font-size:12px;' },
timeAgo(ioc.ts))
]);
})
);
},
handleSaveApply: null,
handleSave: null,
handleReset: null
});