From a0f10d2c0066ac2ff86d18742f11883c105f441a Mon Sep 17 00:00:00 2001 From: anti Date: Wed, 20 May 2026 22:15:02 -0400 Subject: [PATCH] feat(ui): add renderers for ja4h, http2/3 settings, ja4-quic fingerprints FingerprintGroup switch fell through to FpGeneric (raw JSON dump) for all four new fingerprint_type values the ingester now produces. Add FpJa4h, FpHttpSettings, FpJa4Quic components and wire them into the dispatcher; also register their labels and icons in fpTypeLabel/fpTypeIcon. --- .../AttackerDetail/fingerprints/helpers.tsx | 8 ++ .../AttackerDetail/fingerprints/renderers.tsx | 76 +++++++++++++++++++ 2 files changed, 84 insertions(+) diff --git a/decnet_web/src/components/AttackerDetail/fingerprints/helpers.tsx b/decnet_web/src/components/AttackerDetail/fingerprints/helpers.tsx index e1de32eb..9076c5e3 100644 --- a/decnet_web/src/components/AttackerDetail/fingerprints/helpers.tsx +++ b/decnet_web/src/components/AttackerDetail/fingerprints/helpers.tsx @@ -6,12 +6,16 @@ import { export const fpTypeLabel: Record = { ja3: 'TLS FINGERPRINT', ja4l: 'LATENCY (JA4L)', + ja4h: 'JA4H (HTTP)', + ja4_quic: 'JA4-QUIC', tls_resumption: 'SESSION RESUMPTION', tls_certificate: 'CERTIFICATE', tls_certificate_active: 'CERTIFICATE (ACTIVE PROBE)', tls_certificate_passive: 'CERTIFICATE', http_useragent: 'HTTP USER-AGENT', http_quirks: 'HTTP HEADER QUIRKS', + http2_settings: 'HTTP/2 SETTINGS', + http3_settings: 'HTTP/3 SETTINGS', spoofed_source: 'SPOOFED SOURCE IP', vnc_client_version: 'VNC CLIENT', jarm: 'JARM', @@ -22,12 +26,16 @@ export const fpTypeLabel: Record = { export const fpTypeIcon: Record = { ja3: , ja4l: , + ja4h: , + ja4_quic: , tls_resumption: , tls_certificate: , tls_certificate_active: , tls_certificate_passive: , http_useragent: , http_quirks: , + http2_settings: , + http3_settings: , spoofed_source: , vnc_client_version: , jarm: , diff --git a/decnet_web/src/components/AttackerDetail/fingerprints/renderers.tsx b/decnet_web/src/components/AttackerDetail/fingerprints/renderers.tsx index eb62cf49..a65c3a25 100644 --- a/decnet_web/src/components/AttackerDetail/fingerprints/renderers.tsx +++ b/decnet_web/src/components/AttackerDetail/fingerprints/renderers.tsx @@ -207,6 +207,77 @@ export const FpTcpStack: React.FC<{ p: any }> = ({ p }) => ( ); +export const FpJa4h: React.FC<{ p: any }> = ({ p }) => ( +
+ +
+ {p.protocol && {String(p.protocol).toUpperCase()}} + {p.method && {String(p.method).toUpperCase()}} + {p.path && {String(p.path)}} + {p.remote_port && :{p.remote_port}} +
+
+); + +export const FpHttpSettings: React.FC<{ p: any }> = ({ p }) => { + let entries: [string, unknown][] = []; + if (p.settings) { + try { + const parsed = typeof p.settings === 'string' ? JSON.parse(p.settings) : p.settings; + entries = Object.entries(parsed as Record); + } catch { /* leave entries empty */ } + } + let frameOrder: string[] = []; + if (p.frame_order) { + try { + const parsed = typeof p.frame_order === 'string' ? JSON.parse(p.frame_order) : p.frame_order; + if (Array.isArray(parsed)) frameOrder = parsed.map(String); + } catch { /* leave empty */ } + } + return ( +
+
+ {p.protocol && {String(p.protocol).toUpperCase()}} + {p.remote_port && :{p.remote_port}} +
+ {entries.length > 0 && ( +
+ {entries.map(([k, v]) => ( +
+ + {k.replace(/_/g, ' ')} + + + {String(v)} + +
+ ))} +
+ )} + {frameOrder.length > 0 && ( +
+ + FRAME ORDER + +
+ {frameOrder.map((f, i) => {f})} +
+
+ )} +
+ ); +}; + +export const FpJa4Quic: React.FC<{ p: any }> = ({ p }) => ( +
+ +
+ {p.sni && SNI: {p.sni}} + {p.alpn && ALPN: {p.alpn}} +
+
+); + export const FpGeneric: React.FC<{ p: any }> = ({ p }) => (
{p.value ? ( @@ -353,6 +424,11 @@ export const FingerprintGroup: React.FC<{ fpType: string; items: any[] }> = ({ f case 'http_quirks': return ; case 'http_useragent': return ; case 'spoofed_source': return ; + case 'ja4h': return ; + case 'http2_settings': + case 'http3_settings': + return ; + case 'ja4_quic': return ; default: return ; } })}