[SHEHZADE//ABDULLAH ANSARI]
Red Team Consultant @ Google | MS in Cybersecurity @ NYU
● Notice //GitHub (@shehzade) is temporarily suspended pending an automated false-positive review. All tools are hosted on this Code Mirror and available on request (contact); GitHub links will return once reinstated.
PUBLIC MIRRORGo v1.0
Multi-protocol network egress assessment and DLP verification framework featuring automated L4 sweeps, corporate proxy traversal, and covert protocol smuggling across 20+ channels.
$
git clone https://shehzade.io/repos/contraband.git
Copy
Source ZIP (1.93 MB)
402 lines · 11.2 KB
| 1 | package live |
| 2 | |
| 3 | import ( |
| 4 | "context" |
| 5 | "encoding/json" |
| 6 | "fmt" |
| 7 | "sync" |
| 8 | "time" |
| 9 | |
| 10 | "github.com/shehzade/contraband/pkg/common" |
| 11 | "github.com/shehzade/contraband/pkg/report" |
| 12 | ) |
| 13 | |
| 14 | // StoredReport retains an uploaded client assessment report with its pre-rendered artifacts. |
| 15 | type StoredReport struct { |
| 16 | ID string `json:"id"` |
| 17 | Report *report.AssessmentReport `json:"report"` |
| 18 | RawHTML []byte `json:"-"` |
| 19 | RawJSON []byte `json:"-"` |
| 20 | RawSARIF []byte `json:"-"` |
| 21 | Remediation []byte `json:"-"` |
| 22 | NetworkZone string `json:"network_zone"` |
| 23 | ClientHost string `json:"client_host"` |
| 24 | ClientIP string `json:"client_ip"` |
| 25 | UploadedAt time.Time `json:"uploaded_at"` |
| 26 | } |
| 27 | |
| 28 | // LiveHub coordinates SSE subscribers, real-time metrics, and report storage. |
| 29 | type LiveHub struct { |
| 30 | startOnce sync.Once |
| 31 | metrics *MetricsTracker |
| 32 | subMu sync.RWMutex |
| 33 | subscribers map[chan LiveEvent]bool |
| 34 | |
| 35 | repMu sync.RWMutex |
| 36 | reports map[string]*StoredReport |
| 37 | |
| 38 | ctx context.Context |
| 39 | cancel context.CancelFunc |
| 40 | } |
| 41 | |
| 42 | // NewLiveHub creates and returns an initialized hub. |
| 43 | func NewLiveHub() *LiveHub { |
| 44 | return &LiveHub{ |
| 45 | metrics: NewMetricsTracker(), |
| 46 | subscribers: make(map[chan LiveEvent]bool), |
| 47 | reports: make(map[string]*StoredReport), |
| 48 | } |
| 49 | } |
| 50 | |
| 51 | // Start begins background telemetry calculation, rate ticks, and heartbeat broadcasts. |
| 52 | func (h *LiveHub) Start(ctx context.Context) { |
| 53 | h.startOnce.Do(func() { |
| 54 | h.ctx, h.cancel = context.WithCancel(ctx) |
| 55 | |
| 56 | go func() { |
| 57 | ticker := time.NewTicker(1 * time.Second) |
| 58 | defer ticker.Stop() |
| 59 | |
| 60 | for { |
| 61 | select { |
| 62 | case <-h.ctx.Done(): |
| 63 | return |
| 64 | case <-ticker.C: |
| 65 | h.metrics.TickWindow() |
| 66 | |
| 67 | snapshot := h.metrics.Snapshot() |
| 68 | now := time.Now() |
| 69 | nowMS := float64(now.UnixNano()) / 1e6 |
| 70 | |
| 71 | // 1. Broadcast sliding window rate tick |
| 72 | h.Broadcast(LiveEvent{ |
| 73 | ID: fmt.Sprintf("tick-%d", now.UnixMilli()), |
| 74 | Type: EventRateTick, |
| 75 | Timestamp: now, |
| 76 | TimestampMS: nowMS, |
| 77 | Message: fmt.Sprintf("Rate tick: %.2f MB/s (peak: %.2f MB/s, streams: %d)", snapshot.Global.InstantThroughputMBs, snapshot.Global.PeakThroughputMBs, snapshot.Global.ActiveStreams), |
| 78 | Data: RateTickData{ |
| 79 | InstantThroughputMBs: snapshot.Global.InstantThroughputMBs, |
| 80 | PeakThroughputMBs: snapshot.Global.PeakThroughputMBs, |
| 81 | ActiveStreams: snapshot.Global.ActiveStreams, |
| 82 | TotalBytes: snapshot.Global.TotalBytesSmuggled, |
| 83 | TimestampMS: nowMS, |
| 84 | }, |
| 85 | }) |
| 86 | |
| 87 | // 2. Broadcast periodic heartbeat with complete snapshot |
| 88 | h.Broadcast(LiveEvent{ |
| 89 | ID: fmt.Sprintf("hb-%d", now.UnixMilli()), |
| 90 | Type: EventHeartbeat, |
| 91 | Timestamp: now, |
| 92 | TimestampMS: nowMS, |
| 93 | Message: "Heartbeat update", |
| 94 | Data: snapshot, |
| 95 | }) |
| 96 | } |
| 97 | } |
| 98 | }() |
| 99 | }) |
| 100 | } |
| 101 | |
| 102 | // Stop shuts down the hub and disconnects subscribers. |
| 103 | func (h *LiveHub) Stop() { |
| 104 | if h.cancel != nil { |
| 105 | h.cancel() |
| 106 | } |
| 107 | h.subMu.Lock() |
| 108 | defer h.subMu.Unlock() |
| 109 | for ch := range h.subscribers { |
| 110 | close(ch) |
| 111 | delete(h.subscribers, ch) |
| 112 | } |
| 113 | } |
| 114 | |
| 115 | // Subscribe registers a new SSE event listener. |
| 116 | func (h *LiveHub) Subscribe() chan LiveEvent { |
| 117 | ch := make(chan LiveEvent, 256) |
| 118 | h.subMu.Lock() |
| 119 | h.subscribers[ch] = true |
| 120 | h.subMu.Unlock() |
| 121 | return ch |
| 122 | } |
| 123 | |
| 124 | // Unsubscribe removes an SSE event listener. |
| 125 | func (h *LiveHub) Unsubscribe(ch chan LiveEvent) { |
| 126 | h.subMu.Lock() |
| 127 | defer h.subMu.Unlock() |
| 128 | if _, ok := h.subscribers[ch]; ok { |
| 129 | delete(h.subscribers, ch) |
| 130 | close(ch) |
| 131 | } |
| 132 | } |
| 133 | |
| 134 | // Broadcast sends an event to all subscribers without blocking callers. |
| 135 | func (h *LiveHub) Broadcast(event LiveEvent) { |
| 136 | h.subMu.RLock() |
| 137 | defer h.subMu.RUnlock() |
| 138 | |
| 139 | for ch := range h.subscribers { |
| 140 | select { |
| 141 | case ch <- event: |
| 142 | default: |
| 143 | // Non-blocking drop for slow consumers to prevent stalling the hub |
| 144 | } |
| 145 | } |
| 146 | } |
| 147 | |
| 148 | // RecordConnectionOpen registers a new client connection arrival and broadcasts connection_open. |
| 149 | func (h *LiveHub) RecordConnectionOpen(zone, host, ip, proto string, port int, sessionID string) { |
| 150 | now := time.Now() |
| 151 | nowMS := float64(now.UnixNano()) / 1e6 |
| 152 | if zone == "" { |
| 153 | zone = ClassifyNetworkZone(ip) |
| 154 | } |
| 155 | if host == "" { |
| 156 | host = ip |
| 157 | } |
| 158 | |
| 159 | h.Broadcast(LiveEvent{ |
| 160 | ID: fmt.Sprintf("conn-%d", now.UnixNano()), |
| 161 | Type: EventConnectionOpen, |
| 162 | Timestamp: now, |
| 163 | TimestampMS: nowMS, |
| 164 | SessionID: sessionID, |
| 165 | NetworkZone: zone, |
| 166 | ClientHost: host, |
| 167 | ClientIP: ip, |
| 168 | Protocol: proto, |
| 169 | Message: fmt.Sprintf("[%s] Connection opened from %s (%s:%d)", proto, host, ip, port), |
| 170 | Data: ConnectionOpenData{ |
| 171 | SessionID: sessionID, |
| 172 | NetworkZone: zone, |
| 173 | ClientHost: host, |
| 174 | ClientIP: ip, |
| 175 | Protocol: proto, |
| 176 | Port: port, |
| 177 | TimestampMS: nowMS, |
| 178 | }, |
| 179 | }) |
| 180 | } |
| 181 | |
| 182 | // RecordChunk registers an incoming payload chunk and broadcasts chunk_received. |
| 183 | func (h *LiveHub) RecordChunk(p SessionProgressData, chunkSize int64) { |
| 184 | h.metrics.RecordChunk(p, chunkSize) |
| 185 | |
| 186 | now := time.Now() |
| 187 | nowMS := float64(now.UnixNano()) / 1e6 |
| 188 | h.Broadcast(LiveEvent{ |
| 189 | ID: fmt.Sprintf("chk-%s-%d", SafePrefix(p.SessionID, 8), p.Sequence), |
| 190 | Type: EventChunkReceived, |
| 191 | Timestamp: now, |
| 192 | TimestampMS: nowMS, |
| 193 | SessionID: p.SessionID, |
| 194 | NetworkZone: p.NetworkZone, |
| 195 | ClientHost: p.ClientHost, |
| 196 | ClientIP: p.ClientIP, |
| 197 | Protocol: p.Protocol, |
| 198 | Message: fmt.Sprintf("[%s] Chunk %d/%d received (%.2f MB/s)", p.Protocol, p.Sequence, p.TotalChunks, p.InstantMBs), |
| 199 | Data: p, |
| 200 | }) |
| 201 | } |
| 202 | |
| 203 | // RecordSessionComplete registers session finalization and broadcasts session_complete. |
| 204 | func (h *LiveHub) RecordSessionComplete(sc SessionCompleteData) { |
| 205 | h.metrics.RecordSessionComplete(sc) |
| 206 | |
| 207 | now := time.Now() |
| 208 | nowMS := float64(now.UnixNano()) / 1e6 |
| 209 | h.Broadcast(LiveEvent{ |
| 210 | ID: fmt.Sprintf("done-%s", SafePrefix(sc.SessionID, 8)), |
| 211 | Type: EventSessionComplete, |
| 212 | Timestamp: now, |
| 213 | TimestampMS: nowMS, |
| 214 | SessionID: sc.SessionID, |
| 215 | NetworkZone: sc.NetworkZone, |
| 216 | ClientHost: sc.ClientHost, |
| 217 | ClientIP: sc.ClientIP, |
| 218 | Protocol: sc.Protocol, |
| 219 | Message: fmt.Sprintf("[%s] Session completed with verdict %s (%s in %.2fms)", sc.Protocol, sc.Verdict, FormatBytes(sc.TotalBytes), sc.DurationMS), |
| 220 | Data: sc, |
| 221 | }) |
| 222 | } |
| 223 | |
| 224 | // RecordProbe registers an individual reflection/sweep probe result and broadcasts probe_received. |
| 225 | func (h *LiveHub) RecordProbe(p common.ProbeResult) { |
| 226 | h.metrics.RecordProbe(p) |
| 227 | |
| 228 | now := time.Now() |
| 229 | nowMS := float64(now.UnixNano()) / 1e6 |
| 230 | zone := ClassifyNetworkZone(p.TargetHost) |
| 231 | |
| 232 | h.Broadcast(LiveEvent{ |
| 233 | ID: fmt.Sprintf("prb-%d", now.UnixNano()), |
| 234 | Type: EventProbeReceived, |
| 235 | Timestamp: now, |
| 236 | TimestampMS: nowMS, |
| 237 | NetworkZone: zone, |
| 238 | ClientHost: p.TargetHost, |
| 239 | ClientIP: p.LocalAddr, |
| 240 | Protocol: p.Protocol, |
| 241 | Message: fmt.Sprintf("[%s] Probe recorded for %s:%d: %s", p.Protocol, p.TargetHost, p.TargetPort, p.Verdict), |
| 242 | Data: ProbeData{ |
| 243 | ProbeID: p.ID, |
| 244 | NetworkZone: zone, |
| 245 | ClientHost: p.TargetHost, |
| 246 | ClientIP: p.LocalAddr, |
| 247 | Protocol: p.Protocol, |
| 248 | TargetPort: p.TargetPort, |
| 249 | Verdict: p.Verdict, |
| 250 | TimestampMS: nowMS, |
| 251 | }, |
| 252 | }) |
| 253 | } |
| 254 | |
| 255 | // StoreReport saves an uploaded assessment report bundle and broadcasts notification. |
| 256 | func (h *LiveHub) StoreReport(rep *report.AssessmentReport, rawHTML, rawJSON, rawSARIF, remediation []byte, zone, host, ip string) string { |
| 257 | reportID := rep.ID |
| 258 | if reportID == "" { |
| 259 | reportID = fmt.Sprintf("rep-%d", time.Now().UnixMilli()) |
| 260 | rep.ID = reportID |
| 261 | } |
| 262 | |
| 263 | stored := &StoredReport{ |
| 264 | ID: reportID, |
| 265 | Report: rep, |
| 266 | RawHTML: rawHTML, |
| 267 | RawJSON: rawJSON, |
| 268 | RawSARIF: rawSARIF, |
| 269 | Remediation: remediation, |
| 270 | NetworkZone: zone, |
| 271 | ClientHost: host, |
| 272 | ClientIP: ip, |
| 273 | UploadedAt: time.Now(), |
| 274 | } |
| 275 | |
| 276 | h.repMu.Lock() |
| 277 | const maxRetainedReports = 50 |
| 278 | if len(h.reports) >= maxRetainedReports { |
| 279 | for oldID := range h.reports { |
| 280 | delete(h.reports, oldID) |
| 281 | break |
| 282 | } |
| 283 | } |
| 284 | h.reports[reportID] = stored |
| 285 | h.repMu.Unlock() |
| 286 | |
| 287 | summary := ReportUploadData{ |
| 288 | ReportID: reportID, |
| 289 | TargetHost: rep.TargetHost, |
| 290 | NetworkZone: zone, |
| 291 | ClientHost: host, |
| 292 | ClientIP: ip, |
| 293 | EEIScore: rep.Summary.EEIScore, |
| 294 | Posture: string(rep.Summary.Posture), |
| 295 | TotalProbes: rep.Summary.TotalProbes, |
| 296 | SuccessCount: rep.Summary.SuccessCount, |
| 297 | BlockedL4: rep.Summary.BlockedL4, |
| 298 | BlockedL7: rep.Summary.BlockedL7, |
| 299 | BlockedDLP: rep.Summary.BlockedDLP, |
| 300 | UploadedAt: time.Now().UTC().Format(time.RFC3339), |
| 301 | } |
| 302 | |
| 303 | h.metrics.RecordReportUpload(summary) |
| 304 | |
| 305 | now := time.Now() |
| 306 | h.Broadcast(LiveEvent{ |
| 307 | ID: fmt.Sprintf("rep-event-%s", SafePrefix(reportID, 8)), |
| 308 | Type: EventReportUploaded, |
| 309 | Timestamp: now, |
| 310 | TimestampMS: float64(now.UnixNano()) / 1e6, |
| 311 | NetworkZone: zone, |
| 312 | ClientHost: host, |
| 313 | ClientIP: ip, |
| 314 | Message: fmt.Sprintf("New Assessment Report uploaded: %s (EEI: %.2f%%)", SafePrefix(reportID, 8), rep.Summary.EEIScore), |
| 315 | Data: summary, |
| 316 | }) |
| 317 | |
| 318 | return reportID |
| 319 | } |
| 320 | |
| 321 | // GetReport retrieves a stored report by ID. |
| 322 | func (h *LiveHub) GetReport(id string) (*StoredReport, bool) { |
| 323 | h.repMu.RLock() |
| 324 | defer h.repMu.RUnlock() |
| 325 | rep, ok := h.reports[id] |
| 326 | return rep, ok |
| 327 | } |
| 328 | |
| 329 | // ListReports returns summaries of all uploaded reports. |
| 330 | func (h *LiveHub) ListReports() []ReportUploadData { |
| 331 | h.repMu.RLock() |
| 332 | defer h.repMu.RUnlock() |
| 333 | |
| 334 | list := make([]ReportUploadData, 0, len(h.reports)) |
| 335 | for _, r := range h.reports { |
| 336 | list = append(list, ReportUploadData{ |
| 337 | ReportID: r.ID, |
| 338 | TargetHost: r.Report.TargetHost, |
| 339 | NetworkZone: r.NetworkZone, |
| 340 | ClientHost: r.ClientHost, |
| 341 | ClientIP: r.ClientIP, |
| 342 | EEIScore: r.Report.Summary.EEIScore, |
| 343 | Posture: string(r.Report.Summary.Posture), |
| 344 | TotalProbes: r.Report.Summary.TotalProbes, |
| 345 | SuccessCount: r.Report.Summary.SuccessCount, |
| 346 | BlockedL4: r.Report.Summary.BlockedL4, |
| 347 | BlockedL7: r.Report.Summary.BlockedL7, |
| 348 | BlockedDLP: r.Report.Summary.BlockedDLP, |
| 349 | UploadedAt: r.UploadedAt.UTC().Format(time.RFC3339), |
| 350 | }) |
| 351 | } |
| 352 | return list |
| 353 | } |
| 354 | |
| 355 | // GetMetricsSnapshot returns the current state of metrics. |
| 356 | func (h *LiveHub) GetMetricsSnapshot() MetricsState { |
| 357 | return h.metrics.Snapshot() |
| 358 | } |
| 359 | |
| 360 | // AddLog appends a live terminal log. |
| 361 | func (h *LiveHub) AddLog(level, zone, host, proto, msg string) { |
| 362 | now := time.Now() |
| 363 | entry := TerminalLogEntry{ |
| 364 | Timestamp: FormatTimestampMS(now), |
| 365 | TimestampMS: float64(now.UnixNano()) / 1e6, |
| 366 | Level: level, |
| 367 | Zone: zone, |
| 368 | Host: host, |
| 369 | Protocol: proto, |
| 370 | Message: msg, |
| 371 | } |
| 372 | h.metrics.AddLog(entry) |
| 373 | } |
| 374 | |
| 375 | // Reset clears all metrics, active sessions, logs, and stored reports, and broadcasts EventDashboardReset. |
| 376 | func (h *LiveHub) Reset(deletedFiles bool, evidenceDir string) { |
| 377 | h.metrics.Reset() |
| 378 | |
| 379 | h.repMu.Lock() |
| 380 | h.reports = make(map[string]*StoredReport) |
| 381 | h.repMu.Unlock() |
| 382 | |
| 383 | now := time.Now() |
| 384 | nowMS := float64(now.UnixNano()) / 1e6 |
| 385 | h.Broadcast(LiveEvent{ |
| 386 | ID: fmt.Sprintf("reset-%d", now.UnixMilli()), |
| 387 | Type: EventDashboardReset, |
| 388 | Timestamp: now, |
| 389 | TimestampMS: nowMS, |
| 390 | Message: "Dashboard telemetry and metrics reset by operator", |
| 391 | Data: DashboardResetData{ |
| 392 | DeletedFiles: deletedFiles, |
| 393 | EvidenceDir: evidenceDir, |
| 394 | TimestampMS: nowMS, |
| 395 | }, |
| 396 | }) |
| 397 | } |
| 398 | |
| 399 | // MarshalJSON marshals current metrics snapshot for API endpoints. |
| 400 | func (h *LiveHub) MarshalJSON() ([]byte, error) { |
| 401 | return json.Marshal(h.metrics.Snapshot()) |
| 402 | } |