use crate::types::{Cookie, Result};
use serde::{Deserialize, Serialize};
#[derive(Debug)]
pub struct ZeroDayDetector {
#[allow(dead_code)]
signatures: Vec<ZeroDaySignature>,
}
impl ZeroDayDetector {
#[must_use]
pub fn new() -> Self {
Self {
signatures: Vec::new(),
}
}
pub fn detect(&self, cookies: &[Cookie]) -> Result<Vec<Cookie>> {
let mut suspicious = Vec::new();
for cookie in cookies {
if Self::is_zero_day_candidate(cookie) {
suspicious.push(cookie.clone());
}
}
Ok(suspicious)
}
fn is_zero_day_candidate(cookie: &Cookie) -> bool {
Self::has_unusual_structure(cookie)
|| Self::has_obfuscation(cookie)
|| Self::has_shellcode_patterns(cookie)
}
fn has_unusual_structure(cookie: &Cookie) -> bool {
cookie.value.len() > 4096 ||
cookie.value.matches("base64").count() > 2 ||
cookie.value.bytes().any(|b| b < 32 && b != b'\n' && b != b'\r' && b != b'\t')
}
#[allow(clippy::cast_precision_loss)] fn has_obfuscation(cookie: &Cookie) -> bool {
let special_chars = cookie
.value
.chars()
.filter(|c| !c.is_alphanumeric())
.count();
let ratio = special_chars as f64 / cookie.value.len() as f64;
ratio > 0.5
}
fn has_shellcode_patterns(cookie: &Cookie) -> bool {
cookie.value.contains("\\x") ||
cookie.value.contains("%u") ||
cookie.value.contains("\\x90\\x90")
}
}
impl Default for ZeroDayDetector {
fn default() -> Self {
Self::new()
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ZeroDaySignature {
pub name: String,
pub heuristic: String,
pub confidence: f64,
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_zero_day_detector_creation() {
let detector = ZeroDayDetector::new();
assert!(detector.signatures.is_empty());
}
}