| | | 1 | | using Intentum.Core.Behavior; |
| | | 2 | | using Intentum.Core.Models; |
| | | 3 | | |
| | | 4 | | namespace Intentum.Core.UBA; |
| | | 5 | | |
| | | 6 | | /// <summary> |
| | | 7 | | /// Pre-built User Behavior Analytics (UBA) rules for detecting insider threats, |
| | | 8 | | /// anomalous access patterns, and data exfiltration attempts. |
| | | 9 | | /// </summary> |
| | | 10 | | public static class UserBehaviorRules |
| | | 11 | | { |
| | | 12 | | /// <summary> |
| | | 13 | | /// Detects potential insider threat: off-hours access + bulk data download + privilege escalation. |
| | | 14 | | /// </summary> |
| | | 15 | | public static Func<BehaviorSpace, RuleMatch?> InsiderThreat( |
| | 3 | 16 | | double confidence = 0.85) => space => |
| | 2 | 17 | | { |
| | 2 | 18 | | var bulkDownload = space.Events.Count(e => |
| | 9 | 19 | | e.Action.Contains("download", StringComparison.OrdinalIgnoreCase) || |
| | 9 | 20 | | e.Action.Contains("export", StringComparison.OrdinalIgnoreCase)); |
| | 2 | 21 | | var sensitiveAccess = space.Events.Count(e => |
| | 9 | 22 | | e.Action.Contains("sensitive", StringComparison.OrdinalIgnoreCase) || |
| | 9 | 23 | | e.Action.Contains("confidential", StringComparison.OrdinalIgnoreCase) || |
| | 9 | 24 | | e.Action.Contains("admin", StringComparison.OrdinalIgnoreCase)); |
| | 2 | 25 | | var hasPrivilegeEscalation = space.Events.Any(e => |
| | 8 | 26 | | e.Action.Contains("privilege", StringComparison.OrdinalIgnoreCase) || |
| | 8 | 27 | | e.Action.Contains("role.change", StringComparison.OrdinalIgnoreCase)); |
| | 3 | 28 | | |
| | 2 | 29 | | if (bulkDownload >= 3 && sensitiveAccess >= 2) |
| | 1 | 30 | | return new RuleMatch("InsiderThreat", confidence, |
| | 1 | 31 | | $"Bulk downloads: {bulkDownload}, sensitive access: {sensitiveAccess}, privilege escalation: {hasPrivile |
| | 1 | 32 | | if (hasPrivilegeEscalation && sensitiveAccess >= 1) |
| | 1 | 33 | | return new RuleMatch("InsiderThreat", confidence * 0.9, |
| | 1 | 34 | | $"Privilege escalation with sensitive access: {sensitiveAccess}"); |
| | 0 | 35 | | return null; |
| | 5 | 36 | | }; |
| | | 37 | | |
| | | 38 | | /// <summary> |
| | | 39 | | /// Detects data exfiltration: large file transfers, USB usage, email attachments. |
| | | 40 | | /// </summary> |
| | | 41 | | public static Func<BehaviorSpace, RuleMatch?> DataExfiltration( |
| | | 42 | | int minTransfers = 3, |
| | 2 | 43 | | double confidence = 0.8) => space => |
| | 1 | 44 | | { |
| | 1 | 45 | | var transfers = space.Events.Count(e => |
| | 4 | 46 | | e.Action.Contains("transfer", StringComparison.OrdinalIgnoreCase) || |
| | 4 | 47 | | e.Action.Contains("upload", StringComparison.OrdinalIgnoreCase) || |
| | 4 | 48 | | e.Action.Contains("usb", StringComparison.OrdinalIgnoreCase) || |
| | 4 | 49 | | e.Action.Contains("attachment", StringComparison.OrdinalIgnoreCase)); |
| | 2 | 50 | | |
| | 1 | 51 | | if (transfers >= minTransfers) |
| | 1 | 52 | | return new RuleMatch("DataExfiltration", confidence, |
| | 1 | 53 | | $"Suspicious transfers: {transfers}"); |
| | 0 | 54 | | return null; |
| | 3 | 55 | | }; |
| | | 56 | | |
| | | 57 | | /// <summary> |
| | | 58 | | /// Detects anomalous access patterns: unusual time, location, or resource access. |
| | | 59 | | /// </summary> |
| | | 60 | | public static Func<BehaviorSpace, RuleMatch?> AnomalousAccess( |
| | 2 | 61 | | double confidence = 0.7) => space => |
| | 1 | 62 | | { |
| | 1 | 63 | | var offHoursAccess = space.Events.Any(e => |
| | 2 | 64 | | e.Action.Contains("off-hours", StringComparison.OrdinalIgnoreCase) || |
| | 2 | 65 | | e.Action.Contains("weekend", StringComparison.OrdinalIgnoreCase)); |
| | 1 | 66 | | var newLocationAccess = space.Events.Any(e => |
| | 3 | 67 | | e.Action.Contains("new.location", StringComparison.OrdinalIgnoreCase) || |
| | 3 | 68 | | e.Action.Contains("vpn.new", StringComparison.OrdinalIgnoreCase)); |
| | 1 | 69 | | var unusualResource = space.Events.Any(e => |
| | 3 | 70 | | e.Action.Contains("first.access", StringComparison.OrdinalIgnoreCase) || |
| | 3 | 71 | | e.Action.Contains("unusual.resource", StringComparison.OrdinalIgnoreCase)); |
| | 2 | 72 | | |
| | 1 | 73 | | var anomalyCount = (offHoursAccess ? 1 : 0) + (newLocationAccess ? 1 : 0) + (unusualResource ? 1 : 0); |
| | 1 | 74 | | if (anomalyCount >= 2) |
| | 1 | 75 | | return new RuleMatch("AnomalousAccess", confidence, |
| | 1 | 76 | | $"Off-hours: {offHoursAccess}, new location: {newLocationAccess}, unusual resource: {unusualResource}"); |
| | 0 | 77 | | return null; |
| | 3 | 78 | | }; |
| | | 79 | | |
| | | 80 | | /// <summary> |
| | | 81 | | /// Returns all standard UBA rules in recommended evaluation order. |
| | | 82 | | /// </summary> |
| | | 83 | | public static IReadOnlyList<Func<BehaviorSpace, RuleMatch?>> AllRules() => |
| | 1 | 84 | | [ |
| | 1 | 85 | | InsiderThreat(), |
| | 1 | 86 | | DataExfiltration(), |
| | 1 | 87 | | AnomalousAccess() |
| | 1 | 88 | | ]; |
| | | 89 | | } |