Skip to main content

aster/security/
patterns.rs

1use lazy_static::lazy_static;
2use regex::Regex;
3use std::collections::HashMap;
4
5/// Security threat patterns for command injection detection
6/// These patterns detect dangerous shell commands and injection attempts
7#[derive(Debug, Clone)]
8pub struct ThreatPattern {
9    pub name: &'static str,
10    pub pattern: &'static str,
11    pub description: &'static str,
12    pub risk_level: RiskLevel,
13    pub category: ThreatCategory,
14}
15
16#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
17pub enum RiskLevel {
18    Low,      // Minor security issue
19    Medium,   // Moderate security concern
20    High,     // Significant security risk
21    Critical, // Immediate system compromise risk
22}
23
24#[derive(Debug, Clone, PartialEq)]
25pub enum ThreatCategory {
26    FileSystemDestruction,
27    RemoteCodeExecution,
28    DataExfiltration,
29    SystemModification,
30    NetworkAccess,
31    ProcessManipulation,
32    PrivilegeEscalation,
33    CommandInjection,
34}
35
36impl RiskLevel {
37    pub fn confidence_score(&self) -> f32 {
38        match self {
39            RiskLevel::Critical => 0.95,
40            RiskLevel::High => 0.75,
41            RiskLevel::Medium => 0.60,
42            RiskLevel::Low => 0.45,
43        }
44    }
45}
46
47/// Comprehensive list of dangerous command patterns
48pub const THREAT_PATTERNS: &[ThreatPattern] = &[
49    // Critical filesystem destruction patterns
50    ThreatPattern {
51        name: "rm_rf_root",
52        pattern: r"rm\s+(-[rf]*[rf][rf]*|--recursive|--force).*[/\\]",
53        description: "Recursive file deletion with rm -rf",
54        risk_level: RiskLevel::High,
55        category: ThreatCategory::FileSystemDestruction,
56    },
57    ThreatPattern {
58        name: "rm_rf_system",
59        pattern: r"rm\s+(-[rf]*[rf][rf]*|--recursive|--force).*(bin|etc|usr|var|sys|proc|dev|boot|lib|opt|srv|tmp)",
60        description: "Recursive deletion of system directories",
61        risk_level: RiskLevel::Critical,
62        category: ThreatCategory::FileSystemDestruction,
63    },
64    ThreatPattern {
65        name: "dd_destruction",
66        pattern: r"dd\s+.*if=/dev/(zero|random|urandom).*of=/dev/[sh]d[a-z]",
67        description: "Disk destruction using dd command",
68        risk_level: RiskLevel::Critical,
69        category: ThreatCategory::FileSystemDestruction,
70    },
71    ThreatPattern {
72        name: "format_drive",
73        pattern: r"(format|mkfs\.[a-z]+)\s+[/\\]dev[/\\][sh]d[a-z]",
74        description: "Formatting system drives",
75        risk_level: RiskLevel::Critical,
76        category: ThreatCategory::FileSystemDestruction,
77    },
78    // Remote code execution patterns
79    ThreatPattern {
80        name: "curl_bash_execution",
81        pattern: r"(curl|wget)\s+.*\|\s*(bash|sh|zsh|fish|csh|tcsh)",
82        description: "Remote script execution via curl/wget piped to shell",
83        risk_level: RiskLevel::Critical,
84        category: ThreatCategory::RemoteCodeExecution,
85    },
86    ThreatPattern {
87        name: "bash_process_substitution",
88        pattern: r"bash\s*<\s*\(\s*(curl|wget)",
89        description: "Bash process substitution with remote content",
90        risk_level: RiskLevel::High,
91        category: ThreatCategory::RemoteCodeExecution,
92    },
93    ThreatPattern {
94        name: "python_remote_exec",
95        pattern: r"python[23]?\s+-c\s+.*urllib|requests.*exec",
96        description: "Python remote code execution",
97        risk_level: RiskLevel::High,
98        category: ThreatCategory::RemoteCodeExecution,
99    },
100    ThreatPattern {
101        name: "powershell_download_exec",
102        pattern: r"powershell.*DownloadString.*Invoke-Expression",
103        description: "PowerShell remote script execution",
104        risk_level: RiskLevel::High,
105        category: ThreatCategory::RemoteCodeExecution,
106    },
107    // Data exfiltration patterns
108    ThreatPattern {
109        name: "ssh_key_exfiltration",
110        pattern: r"(curl|wget).*-d.*\.ssh/(id_rsa|id_ed25519|id_ecdsa)",
111        description: "SSH key exfiltration",
112        risk_level: RiskLevel::High,
113        category: ThreatCategory::DataExfiltration,
114    },
115    ThreatPattern {
116        name: "password_file_access",
117        pattern: r"(cat|grep|awk|sed).*(/etc/passwd|/etc/shadow|\.password|\.env)",
118        description: "Password file access",
119        risk_level: RiskLevel::High,
120        category: ThreatCategory::DataExfiltration,
121    },
122    ThreatPattern {
123        name: "history_exfiltration",
124        pattern: r"(curl|wget).*-d.*\.(bash_history|zsh_history|history)",
125        description: "Command history exfiltration",
126        risk_level: RiskLevel::High,
127        category: ThreatCategory::DataExfiltration,
128    },
129    // System modification patterns
130    ThreatPattern {
131        name: "crontab_modification",
132        pattern: r"(crontab\s+-e|echo.*>.*crontab|.*>\s*/var/spool/cron)",
133        description: "Crontab modification for persistence",
134        risk_level: RiskLevel::High,
135        category: ThreatCategory::SystemModification,
136    },
137    ThreatPattern {
138        name: "systemd_service_creation",
139        pattern: r"systemctl.*enable|.*\.service.*>/etc/systemd",
140        description: "Systemd service creation",
141        risk_level: RiskLevel::High,
142        category: ThreatCategory::SystemModification,
143    },
144    ThreatPattern {
145        name: "hosts_file_modification",
146        pattern: r"echo.*>.*(/etc/hosts|hosts\.txt)",
147        description: "Hosts file modification",
148        risk_level: RiskLevel::Medium,
149        category: ThreatCategory::SystemModification,
150    },
151    // Network access patterns
152    ThreatPattern {
153        name: "netcat_listener",
154        pattern: r"nc\s+(-l|-p)\s+\d+",
155        description: "Netcat listener creation",
156        risk_level: RiskLevel::High,
157        category: ThreatCategory::NetworkAccess,
158    },
159    ThreatPattern {
160        name: "reverse_shell",
161        pattern: r"(nc|netcat|bash|sh).*-e\s*(bash|sh|/bin/bash|/bin/sh)",
162        description: "Reverse shell creation",
163        risk_level: RiskLevel::Critical,
164        category: ThreatCategory::NetworkAccess,
165    },
166    ThreatPattern {
167        name: "ssh_tunnel",
168        pattern: r"ssh\s+.*-[LRD]\s+\d+:",
169        description: "SSH tunnel creation",
170        risk_level: RiskLevel::Medium,
171        category: ThreatCategory::NetworkAccess,
172    },
173    // Process manipulation patterns
174    ThreatPattern {
175        name: "kill_security_process",
176        pattern: r"kill(all)?\s+.*\b(antivirus|firewall|defender|security|monitor)\b",
177        description: "Killing security processes",
178        risk_level: RiskLevel::High,
179        category: ThreatCategory::ProcessManipulation,
180    },
181    ThreatPattern {
182        name: "process_injection",
183        pattern: r"gdb\s+.*attach|ptrace.*PTRACE_POKETEXT",
184        description: "Process injection techniques",
185        risk_level: RiskLevel::High,
186        category: ThreatCategory::ProcessManipulation,
187    },
188    // Privilege escalation patterns
189    ThreatPattern {
190        name: "sudo_without_password",
191        pattern: r"echo.*NOPASSWD.*>.*sudoers",
192        description: "Sudo privilege escalation",
193        risk_level: RiskLevel::Critical,
194        category: ThreatCategory::PrivilegeEscalation,
195    },
196    ThreatPattern {
197        name: "suid_binary_creation",
198        pattern: r"chmod\s+[47][0-7][0-7][0-7]|chmod\s+\+s",
199        description: "SUID binary creation",
200        risk_level: RiskLevel::High,
201        category: ThreatCategory::PrivilegeEscalation,
202    },
203    // Command injection patterns
204    ThreatPattern {
205        name: "command_substitution",
206        pattern: r"\$\([^)]*[;&|><][^)]*\)|`[^`]*[;&|><][^`]*`",
207        description: "Command substitution with shell operators",
208        risk_level: RiskLevel::High,
209        category: ThreatCategory::CommandInjection,
210    },
211    ThreatPattern {
212        name: "shell_metacharacters",
213        pattern: r"[;&|`$(){}[\]\\]",
214        description: "Shell metacharacters in input",
215        risk_level: RiskLevel::Low,
216        category: ThreatCategory::CommandInjection,
217    },
218    ThreatPattern {
219        name: "encoded_commands",
220        pattern: r"(base64|hex|url).*decode.*\|\s*(bash|sh)",
221        description: "Encoded command execution",
222        risk_level: RiskLevel::High,
223        category: ThreatCategory::CommandInjection,
224    },
225    // Obfuscation and evasion patterns
226    ThreatPattern {
227        name: "base64_encoded_shell",
228        pattern: r"(echo|printf)\s+[A-Za-z0-9+/=]{20,}\s*\|\s*base64\s+-d\s*\|\s*(bash|sh|zsh)",
229        description: "Base64 encoded shell commands",
230        risk_level: RiskLevel::High,
231        category: ThreatCategory::CommandInjection,
232    },
233    ThreatPattern {
234        name: "hex_encoded_commands",
235        pattern: r"(echo|printf)\s+[0-9a-fA-F\\x]{20,}\s*\|\s*(xxd|od).*\|\s*(bash|sh)",
236        description: "Hex encoded command execution",
237        risk_level: RiskLevel::High,
238        category: ThreatCategory::CommandInjection,
239    },
240    ThreatPattern {
241        name: "string_concatenation_obfuscation",
242        pattern: r"(\$\{[^}]*\}|\$[A-Za-z_][A-Za-z0-9_]*){3,}",
243        description: "String concatenation obfuscation",
244        risk_level: RiskLevel::Medium,
245        category: ThreatCategory::CommandInjection,
246    },
247    ThreatPattern {
248        name: "character_escaping",
249        pattern: r"\\[x][0-9a-fA-F]{2}|\\[0-7]{3}|\\[nrtbfav\\]",
250        description: "Character escaping for obfuscation",
251        risk_level: RiskLevel::Low,
252        category: ThreatCategory::CommandInjection,
253    },
254    ThreatPattern {
255        name: "eval_with_variables",
256        pattern: r"eval\s+\$[A-Za-z_][A-Za-z0-9_]*|\beval\s+.*\$\{",
257        description: "Eval with variable substitution",
258        risk_level: RiskLevel::High,
259        category: ThreatCategory::CommandInjection,
260    },
261    ThreatPattern {
262        name: "indirect_command_execution",
263        pattern: r"\$\([^)]*\$\([^)]*\)[^)]*\)|`[^`]*`[^`]*`",
264        description: "Nested command substitution",
265        risk_level: RiskLevel::Medium,
266        category: ThreatCategory::CommandInjection,
267    },
268    ThreatPattern {
269        name: "environment_variable_abuse",
270        pattern: r"(export|env)\s+[A-Z_]+=.*[;&|]|PATH=.*[;&|]",
271        description: "Environment variable manipulation",
272        risk_level: RiskLevel::Medium,
273        category: ThreatCategory::SystemModification,
274    },
275    ThreatPattern {
276        name: "unicode_obfuscation",
277        pattern: r"\\u[0-9a-fA-F]{4}|\\U[0-9a-fA-F]{8}",
278        description: "Unicode character obfuscation",
279        risk_level: RiskLevel::Medium,
280        category: ThreatCategory::CommandInjection,
281    },
282    ThreatPattern {
283        name: "alternative_shell_invocation",
284        pattern: r"(/bin/|/usr/bin/|\./)?(bash|sh|zsh|fish|csh|tcsh|dash)\s+-c\s+.*[;&|]",
285        description: "Alternative shell invocation patterns",
286        risk_level: RiskLevel::Medium,
287        category: ThreatCategory::CommandInjection,
288    },
289    // Additional dangerous commands that might be missing
290    ThreatPattern {
291        name: "docker_privileged_exec",
292        pattern: r"docker\s+(run|exec).*--privileged",
293        description: "Docker privileged container execution",
294        risk_level: RiskLevel::High,
295        category: ThreatCategory::PrivilegeEscalation,
296    },
297    ThreatPattern {
298        name: "container_escape",
299        pattern: r"(chroot|unshare|nsenter).*--mount|--pid|--net",
300        description: "Container escape techniques",
301        risk_level: RiskLevel::High,
302        category: ThreatCategory::PrivilegeEscalation,
303    },
304    ThreatPattern {
305        name: "kernel_module_manipulation",
306        pattern: r"(insmod|rmmod|modprobe).*\.ko",
307        description: "Kernel module manipulation",
308        risk_level: RiskLevel::Critical,
309        category: ThreatCategory::SystemModification,
310    },
311    ThreatPattern {
312        name: "memory_dump",
313        pattern: r"(gcore|gdb.*dump|/proc/[0-9]+/mem)",
314        description: "Memory dumping techniques",
315        risk_level: RiskLevel::High,
316        category: ThreatCategory::DataExfiltration,
317    },
318    ThreatPattern {
319        name: "log_manipulation",
320        pattern: r"(>\s*/dev/null|truncate.*log|rm.*\.log|echo\s*>\s*/var/log)",
321        description: "Log file manipulation or deletion",
322        risk_level: RiskLevel::Medium,
323        category: ThreatCategory::SystemModification,
324    },
325    ThreatPattern {
326        name: "file_timestamp_manipulation",
327        pattern: r"touch\s+-[amt]\s+|utimes|futimes",
328        description: "File timestamp manipulation",
329        risk_level: RiskLevel::Low,
330        category: ThreatCategory::SystemModification,
331    },
332    ThreatPattern {
333        name: "steganography_tools",
334        pattern: r"\b(steghide|outguess|jphide|steganos)\b",
335        description: "Steganography tools usage",
336        risk_level: RiskLevel::Medium,
337        category: ThreatCategory::DataExfiltration,
338    },
339    ThreatPattern {
340        name: "network_scanning",
341        pattern: r"\b(nmap|masscan|zmap|unicornscan)\b.*-[sS]",
342        description: "Network scanning tools",
343        risk_level: RiskLevel::Medium,
344        category: ThreatCategory::NetworkAccess,
345    },
346    ThreatPattern {
347        name: "password_cracking_tools",
348        pattern: r"\b(john|hashcat|hydra|medusa|brutespray)\b",
349        description: "Password cracking tools",
350        risk_level: RiskLevel::High,
351        category: ThreatCategory::PrivilegeEscalation,
352    },
353];
354
355lazy_static! {
356    static ref COMPILED_PATTERNS: HashMap<&'static str, Regex> = {
357        let mut patterns = HashMap::new();
358        for threat in THREAT_PATTERNS {
359            if let Ok(regex) = Regex::new(&format!("(?i){}", threat.pattern)) {
360                patterns.insert(threat.name, regex);
361            }
362        }
363        patterns
364    };
365}
366
367/// Pattern matcher for detecting security threats
368pub struct PatternMatcher {
369    patterns: &'static HashMap<&'static str, Regex>,
370}
371
372impl PatternMatcher {
373    pub fn new() -> Self {
374        Self {
375            patterns: &COMPILED_PATTERNS,
376        }
377    }
378
379    pub fn scan_for_patterns(&self, text: &str) -> Vec<PatternMatch> {
380        let mut matches = Vec::new();
381
382        for threat in THREAT_PATTERNS {
383            if let Some(regex) = self.patterns.get(threat.name) {
384                if regex.is_match(text) {
385                    // Find all matches to get position information
386                    for regex_match in regex.find_iter(text) {
387                        matches.push(PatternMatch {
388                            threat: threat.clone(),
389                            matched_text: regex_match.as_str().to_string(),
390                            start_pos: regex_match.start(),
391                            end_pos: regex_match.end(),
392                        });
393                    }
394                }
395            }
396        }
397
398        // Sort by risk level (highest first), then by position in text
399        matches.sort_by_key(|m| (std::cmp::Reverse(m.threat.risk_level.clone()), m.start_pos));
400
401        matches
402    }
403
404    /// Get the highest risk level from matches
405    pub fn get_max_risk_level(&self, matches: &[PatternMatch]) -> Option<RiskLevel> {
406        matches.iter().map(|m| &m.threat.risk_level).max().cloned()
407    }
408
409    /// Check if any critical or high-risk patterns are detected
410    pub fn has_critical_threats(&self, matches: &[PatternMatch]) -> bool {
411        matches
412            .iter()
413            .any(|m| matches!(m.threat.risk_level, RiskLevel::Critical | RiskLevel::High))
414    }
415}
416
417#[derive(Debug, Clone)]
418pub struct PatternMatch {
419    pub threat: ThreatPattern,
420    pub matched_text: String,
421    pub start_pos: usize,
422    pub end_pos: usize,
423}
424
425impl Default for PatternMatcher {
426    fn default() -> Self {
427        Self::new()
428    }
429}