security_rust/protocol/
open_redirect.rs1use regex::Regex;
4use std::sync::LazyLock;
5
6use crate::{AttackCategory, DetectionResult, Detector, Severity};
7
8static PATTERNS: LazyLock<Vec<Regex>> = LazyLock::new(|| {
9 vec![
10 Regex::new(r"(?i)//[^/\s]+\.[a-z]{2,}").unwrap(),
11 Regex::new(r"(?i)javascript\s*:").unwrap(),
12 Regex::new(r"(?i)data\s*:\s*text/html").unwrap(),
13 Regex::new(r"(?i)data\s*:\s*text/plain").unwrap(),
14 ]
15});
16
17pub struct OpenRedirectDetector;
18
19impl Detector for OpenRedirectDetector {
20 fn name(&self) -> &'static str {
21 "open_redirect"
22 }
23
24 fn detect(&self, input: &str) -> Option<DetectionResult> {
25 for re in PATTERNS.iter() {
26 if let Some(m) = re.find(input) {
27 let start = m.start();
28 if start > 0 && input.as_bytes()[start - 1] == b':' {
30 continue;
31 }
32 return Some(DetectionResult {
33 attack_type: "open_redirect".into(),
34 category: AttackCategory::Protocol,
35 severity: Severity::Medium,
36 matched_pattern: m.as_str().to_string(),
37 offset: start,
38 message: "Open redirect detected".into(),
39 });
40 }
41 }
42 None
43 }
44}