espilon-source/tools/C3PO/hp_dashboard/static/hp/js/credentials.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

78 lines
3.3 KiB
JavaScript

/* ESPILON Honeypot Dashboard — Credentials Tab */
import { S } from './state.js';
import { $id, escHtml, maskPassword, svcIcon, emptyState, skeletonRows } from './utils.js';
import { api } from './api.js';
export async function renderCredentials() {
const ml = $id('main-list');
if (!ml) return;
ml.innerHTML = skeletonRows(5);
if (!S.credentials) {
S.credentials = await api('/api/honeypot/credentials');
}
const c = S.credentials;
if (!c) {
ml.innerHTML = emptyState('\uD83D\uDD12', 'No credential data', 'Captured credentials will be shown here');
return;
}
let html = '<div class="ov-2col">';
// Top Usernames
html += '<div class="sb-section"><div class="sb-header">Top Usernames</div><div class="sb-body">';
html += '<table class="ov-table"><tr><th>#</th><th>Username</th><th>Count</th><th>Services</th></tr>';
const users = c.top_usernames || [];
for (let i = 0; i < users.length; i++) {
const u = users[i];
html += '<tr><td>' + (i + 1) + '</td>'
+ '<td class="font-mono">' + escHtml(u.username) + '</td>'
+ '<td>' + u.cnt + '</td>'
+ '<td>' + escHtml(Array.isArray(u.services) ? u.services.join(', ') : (u.services || '')) + '</td></tr>';
}
html += '</table></div></div>';
// Top Passwords
html += '<div class="sb-section"><div class="sb-header">Top Passwords</div><div class="sb-body">';
html += '<table class="ov-table"><tr><th>#</th><th>Password</th><th>Count</th><th>Services</th></tr>';
const passwords = c.top_passwords || [];
for (let i = 0; i < passwords.length; i++) {
const p = passwords[i];
const masked = maskPassword(p.password);
html += '<tr><td>' + (i + 1) + '</td>'
+ '<td class="font-mono">' + escHtml(masked) + '</td>'
+ '<td>' + p.cnt + '</td>'
+ '<td>' + escHtml(Array.isArray(p.services) ? p.services.join(', ') : (p.services || '')) + '</td></tr>';
}
html += '</table></div></div>';
// Top Combos
html += '<div class="sb-section"><div class="sb-header">Top Combos</div><div class="sb-body">';
html += '<table class="ov-table"><tr><th>#</th><th>Username:Password</th><th>Count</th><th>Service</th></tr>';
const combos = c.top_combos || [];
for (let i = 0; i < combos.length; i++) {
const cb = combos[i];
html += '<tr><td>' + (i + 1) + '</td>'
+ '<td class="font-mono">' + escHtml(cb.username) + ':' + escHtml(maskPassword(cb.password)) + '</td>'
+ '<td>' + cb.cnt + '</td>'
+ '<td>' + escHtml(cb.service || '') + '</td></tr>';
}
html += '</table></div></div>';
// By Service
html += '<div class="sb-section"><div class="sb-header">By Service</div><div class="sb-body">';
html += '<table class="ov-table"><tr><th>Service</th><th>Unique Users</th><th>Total Attempts</th></tr>';
const bySvc = c.by_service || [];
for (let i = 0; i < bySvc.length; i++) {
const sv = bySvc[i];
html += '<tr><td>' + svcIcon(sv.service) + ' ' + escHtml(sv.service) + '</td>'
+ '<td>' + sv.unique_users + '</td>'
+ '<td>' + sv.total_attempts + '</td></tr>';
}
html += '</table></div></div>';
html += '</div>';
ml.innerHTML = html;
}