[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)
228 lines · 6.8 KB
| 1 | package report |
| 2 | |
| 3 | import ( |
| 4 | "math" |
| 5 | "time" |
| 6 | |
| 7 | "github.com/shehzade/contraband/pkg/common" |
| 8 | ) |
| 9 | |
| 10 | // PostureLevel classifies enterprise egress exposure risk. |
| 11 | type PostureLevel string |
| 12 | |
| 13 | const ( |
| 14 | PostureHardened PostureLevel = "Hardened" // 0.0% – 19.9% |
| 15 | PostureModerate PostureLevel = "Moderate" // 20.0% – 59.9% |
| 16 | PostureCritical PostureLevel = "Critical" // 60.0% – 100.0% |
| 17 | ) |
| 18 | |
| 19 | // PostureColor returns the associated hex color code for executive dashboards. |
| 20 | func (p PostureLevel) PostureColor() string { |
| 21 | switch p { |
| 22 | case PostureHardened: |
| 23 | return "#22c55e" // Green |
| 24 | case PostureModerate: |
| 25 | return "#eab308" // Yellow / Amber |
| 26 | case PostureCritical: |
| 27 | return "#ef4444" // Red |
| 28 | default: |
| 29 | return "#6b7280" // Gray |
| 30 | } |
| 31 | } |
| 32 | |
| 33 | // CategoryScore tracks metrics and calculated exposure for an individual assessment category. |
| 34 | type CategoryScore struct { |
| 35 | Category string `json:"category"` |
| 36 | Weight float64 `json:"weight"` // 0.30 for Port/DLP, 0.40 for Proto |
| 37 | TestedCount int `json:"tested_count"` // Total items tested |
| 38 | SuccessCount int `json:"success_count"` // Unfiltered / succeeded / leaked |
| 39 | BlockedCount int `json:"blocked_count"` // Blocked by L4/L7/DLP |
| 40 | RawScore float64 `json:"raw_score"` // Percentage 0.0 – 100.0 |
| 41 | WeightedScore float64 `json:"weighted_score"` // RawScore * Weight |
| 42 | Tested bool `json:"tested"` // True if TestedCount > 0 |
| 43 | } |
| 44 | |
| 45 | // EEIReport encapsulates the complete Egress Exposure Index calculation. |
| 46 | type EEIReport struct { |
| 47 | Score float64 `json:"eei_score"` // Normalized EEI (0.0 – 100.0) |
| 48 | RawScore float64 `json:"raw_eei_score"` // Unnormalized EEI |
| 49 | Posture PostureLevel `json:"posture"` // Hardened, Moderate, Critical |
| 50 | PostureColor string `json:"posture_color"` // Hex color code |
| 51 | PortScore CategoryScore `json:"port_score"` // Sport (0.30) |
| 52 | ProtoScore CategoryScore `json:"proto_score"` // Sproto (0.40) |
| 53 | DLPScore CategoryScore `json:"dlp_score"` // Sdlp (0.30) |
| 54 | TotalProbes int `json:"total_probes"` |
| 55 | SuccessProbes int `json:"success_probes"` |
| 56 | BlockedProbes int `json:"blocked_probes"` |
| 57 | GeneratedAt time.Time `json:"generated_at"` |
| 58 | } |
| 59 | |
| 60 | const ( |
| 61 | WeightPort = 0.30 |
| 62 | WeightProto = 0.40 |
| 63 | WeightDLP = 0.30 |
| 64 | |
| 65 | ThresholdHardenedMax = 19.99 |
| 66 | ThresholdModerateMax = 59.99 |
| 67 | ) |
| 68 | |
| 69 | // ClassifyPosture maps an exposure score to its posture classification. |
| 70 | func ClassifyPosture(score float64) PostureLevel { |
| 71 | if score < 0.0 { |
| 72 | score = 0.0 |
| 73 | } |
| 74 | if score > 100.0 { |
| 75 | score = 100.0 |
| 76 | } |
| 77 | rounded := math.Round(score*100) / 100 |
| 78 | |
| 79 | if rounded <= ThresholdHardenedMax { |
| 80 | return PostureHardened |
| 81 | } |
| 82 | if rounded <= ThresholdModerateMax { |
| 83 | return PostureModerate |
| 84 | } |
| 85 | return PostureCritical |
| 86 | } |
| 87 | |
| 88 | // CalculateEEI processes a list of probe results and calculates the Egress Exposure Index. |
| 89 | // It mitigates division-by-zero when categories are untested using Normalized Active Weighting. |
| 90 | func CalculateEEI(probes []common.ProbeResult) *EEIReport { |
| 91 | report := &EEIReport{ |
| 92 | GeneratedAt: time.Now().UTC(), |
| 93 | PortScore: CategoryScore{ |
| 94 | Category: "ports", |
| 95 | Weight: WeightPort, |
| 96 | }, |
| 97 | ProtoScore: CategoryScore{ |
| 98 | Category: "protocols", |
| 99 | Weight: WeightProto, |
| 100 | }, |
| 101 | DLPScore: CategoryScore{ |
| 102 | Category: "dlp", |
| 103 | Weight: WeightDLP, |
| 104 | }, |
| 105 | } |
| 106 | |
| 107 | report.TotalProbes = len(probes) |
| 108 | if len(probes) == 0 { |
| 109 | report.Score = 0.0 |
| 110 | report.RawScore = 0.0 |
| 111 | report.Posture = PostureHardened |
| 112 | report.PostureColor = report.Posture.PostureColor() |
| 113 | return report |
| 114 | } |
| 115 | |
| 116 | // 1. Accumulate Port Sweep Metrics |
| 117 | testedPorts := make(map[int]bool) |
| 118 | unfilteredPorts := make(map[int]bool) |
| 119 | |
| 120 | // 2. Accumulate Protocol Metrics |
| 121 | testedProtos := make(map[string]bool) |
| 122 | successfulProtos := make(map[string]bool) |
| 123 | |
| 124 | // 3. Accumulate DLP Metrics |
| 125 | dlpTested := 0 |
| 126 | dlpUninspected := 0 |
| 127 | dlpBlocked := 0 |
| 128 | |
| 129 | for _, p := range probes { |
| 130 | if p.Verdict.IsSuccess() { |
| 131 | report.SuccessProbes++ |
| 132 | } else { |
| 133 | report.BlockedProbes++ |
| 134 | } |
| 135 | |
| 136 | // Port Sweep Stage |
| 137 | if p.Stage == "sweep" || (p.Stage == "" && p.PayloadType == "" && p.TargetPort > 0) || p.Protocol == "tcp" || p.Protocol == "udp" { |
| 138 | if p.TargetPort > 0 { |
| 139 | testedPorts[p.TargetPort] = true |
| 140 | if p.Verdict.IsSuccess() { |
| 141 | unfilteredPorts[p.TargetPort] = true |
| 142 | } |
| 143 | } |
| 144 | } |
| 145 | |
| 146 | // Protocol Exfiltration Stage |
| 147 | if p.Stage == "exfil" || (p.Stage != "sweep" && p.Protocol != "" && p.Protocol != "tcp" && p.Protocol != "udp") { |
| 148 | testedProtos[p.Protocol] = true |
| 149 | if p.Verdict.IsSuccess() { |
| 150 | successfulProtos[p.Protocol] = true |
| 151 | } |
| 152 | } |
| 153 | |
| 154 | // Procedural DLP Stage |
| 155 | if p.PayloadType != "" || p.Stage == "dlp" { |
| 156 | dlpTested++ |
| 157 | if p.Verdict.IsSuccess() { |
| 158 | dlpUninspected++ |
| 159 | } else { |
| 160 | dlpBlocked++ |
| 161 | } |
| 162 | } |
| 163 | } |
| 164 | |
| 165 | // Calculate Category 1: Sport |
| 166 | report.PortScore.TestedCount = len(testedPorts) |
| 167 | report.PortScore.SuccessCount = len(unfilteredPorts) |
| 168 | report.PortScore.BlockedCount = len(testedPorts) - len(unfilteredPorts) |
| 169 | if report.PortScore.TestedCount > 0 { |
| 170 | report.PortScore.Tested = true |
| 171 | report.PortScore.RawScore = (float64(report.PortScore.SuccessCount) / float64(report.PortScore.TestedCount)) * 100.0 |
| 172 | report.PortScore.WeightedScore = report.PortScore.RawScore * WeightPort |
| 173 | } |
| 174 | |
| 175 | // Calculate Category 2: Sproto |
| 176 | report.ProtoScore.TestedCount = len(testedProtos) |
| 177 | report.ProtoScore.SuccessCount = len(successfulProtos) |
| 178 | report.ProtoScore.BlockedCount = len(testedProtos) - len(successfulProtos) |
| 179 | if report.ProtoScore.TestedCount > 0 { |
| 180 | report.ProtoScore.Tested = true |
| 181 | report.ProtoScore.RawScore = (float64(report.ProtoScore.SuccessCount) / float64(report.ProtoScore.TestedCount)) * 100.0 |
| 182 | report.ProtoScore.WeightedScore = report.ProtoScore.RawScore * WeightProto |
| 183 | } |
| 184 | |
| 185 | // Calculate Category 3: Sdlp |
| 186 | report.DLPScore.TestedCount = dlpTested |
| 187 | report.DLPScore.SuccessCount = dlpUninspected |
| 188 | report.DLPScore.BlockedCount = dlpBlocked |
| 189 | if report.DLPScore.TestedCount > 0 { |
| 190 | report.DLPScore.Tested = true |
| 191 | report.DLPScore.RawScore = (float64(report.DLPScore.SuccessCount) / float64(report.DLPScore.TestedCount)) * 100.0 |
| 192 | report.DLPScore.WeightedScore = report.DLPScore.RawScore * WeightDLP |
| 193 | } |
| 194 | |
| 195 | // Raw EEI: direct sum of weighted components |
| 196 | rawEEI := report.PortScore.WeightedScore + report.ProtoScore.WeightedScore + report.DLPScore.WeightedScore |
| 197 | report.RawScore = math.Round(rawEEI*100) / 100 |
| 198 | |
| 199 | // Normalized Active EEI (rebalancing when some categories are untested) |
| 200 | activeWeight := 0.0 |
| 201 | if report.PortScore.Tested { |
| 202 | activeWeight += WeightPort |
| 203 | } |
| 204 | if report.ProtoScore.Tested { |
| 205 | activeWeight += WeightProto |
| 206 | } |
| 207 | if report.DLPScore.Tested { |
| 208 | activeWeight += WeightDLP |
| 209 | } |
| 210 | |
| 211 | if activeWeight > 0.0 { |
| 212 | normalizedScore := rawEEI / activeWeight |
| 213 | if normalizedScore < 0.0 { |
| 214 | normalizedScore = 0.0 |
| 215 | } |
| 216 | if normalizedScore > 100.0 { |
| 217 | normalizedScore = 100.0 |
| 218 | } |
| 219 | report.Score = math.Round(normalizedScore*100) / 100 |
| 220 | } else { |
| 221 | report.Score = 0.0 |
| 222 | } |
| 223 | |
| 224 | report.Posture = ClassifyPosture(report.Score) |
| 225 | report.PostureColor = report.Posture.PostureColor() |
| 226 | |
| 227 | return report |
| 228 | } |