use super::bytes::contains_ci;
use super::decode::percent_decode_lower;
use super::{validate_input, DetectionError};
pub fn detect_obfuscated_js(input: &[u8]) -> Result<bool, DetectionError> {
validate_input(input)?;
let normalized = percent_decode_lower(input);
let eval = contains_ci(&normalized, b"eval(") || contains_ci(&normalized, b"settimeout(");
let decoder = contains_ci(&normalized, b"atob(") || contains_ci(&normalized, b"unescape(");
let charcode = contains_ci(&normalized, b"fromcharcode")
|| contains_ci(&normalized, br"\x")
|| contains_ci(&normalized, br"\u00");
Ok(eval && decoder && charcode)
}
pub fn detect_sql_injection(input: &[u8]) -> Result<bool, DetectionError> {
validate_input(input)?;
let s = percent_decode_lower(input);
let sql_words = contains_ci(&s, b"select ") && contains_ci(&s, b" from ");
let union_select = contains_ci(&s, b"union select");
let tautology = contains_ci(&s, b" or 1=1")
|| contains_ci(&s, b"' or '1'='1")
|| contains_ci(&s, b"\" or \"1\"=\"1")
|| contains_ci(&s, b" or true");
let comment = contains_ci(&s, b"--") || contains_ci(&s, b"/*") || contains_ci(&s, b"#");
let stacked = contains_ci(&s, b"; drop ") || contains_ci(&s, b"; select ");
Ok(union_select || (tautology && (comment || sql_words)) || stacked)
}
pub fn detect_xss(input: &[u8]) -> Result<bool, DetectionError> {
validate_input(input)?;
let s = percent_decode_lower(input);
Ok(contains_ci(&s, b"<script")
|| contains_ci(&s, b"javascript:")
|| contains_ci(&s, b"onerror=")
|| contains_ci(&s, b"onload=")
|| contains_ci(&s, b"<svg") && (contains_ci(&s, b"onload") || contains_ci(&s, b"script")))
}
pub fn detect_lfi(input: &[u8]) -> Result<bool, DetectionError> {
validate_input(input)?;
let s = percent_decode_lower(input);
Ok((contains_ci(&s, b"../") || contains_ci(&s, br"..\"))
&& (contains_ci(&s, b"/etc/passwd")
|| contains_ci(&s, b"boot.ini")
|| contains_ci(&s, b"win.ini")
|| contains_ci(&s, b"/proc/self/environ")))
}
pub fn detect_rfi(input: &[u8]) -> Result<bool, DetectionError> {
validate_input(input)?;
let s = percent_decode_lower(input);
let param = contains_ci(&s, b"file=")
|| contains_ci(&s, b"path=")
|| contains_ci(&s, b"page=")
|| contains_ci(&s, b"include=");
let remote = contains_ci(&s, b"http://") || contains_ci(&s, b"https://");
Ok(param && remote)
}
pub fn detect_command_injection(input: &[u8]) -> Result<bool, DetectionError> {
validate_input(input)?;
let s = percent_decode_lower(input);
let meta = contains_ci(&s, b";")
|| contains_ci(&s, b"&&")
|| contains_ci(&s, b"||")
|| contains_ci(&s, b"`")
|| contains_ci(&s, b"$(")
|| contains_ci(&s, b"|");
let command = contains_ci(&s, b" cat ")
|| contains_ci(&s, b" id")
|| contains_ci(&s, b" whoami")
|| contains_ci(&s, b" curl ")
|| contains_ci(&s, b" wget ")
|| contains_ci(&s, b" nc ")
|| contains_ci(&s, b" /bin/sh")
|| contains_ci(&s, b" powershell");
Ok(meta && command)
}
pub fn detect_ssrf(input: &[u8]) -> Result<bool, DetectionError> {
validate_input(input)?;
let s = percent_decode_lower(input);
let has_url = contains_ci(&s, b"http://") || contains_ci(&s, b"https://");
let target = contains_ci(&s, b"localhost")
|| contains_ci(&s, b"127.0.0.1")
|| contains_ci(&s, b"0.0.0.0")
|| contains_ci(&s, b"169.254.169.254")
|| contains_ci(&s, b"10.")
|| contains_ci(&s, b"192.168.")
|| contains_ci(&s, b"172.16.");
Ok(has_url && target)
}
pub fn detect_path_traversal(input: &[u8]) -> Result<bool, DetectionError> {
validate_input(input)?;
let s = percent_decode_lower(input);
Ok(contains_ci(&s, b"../")
|| contains_ci(&s, br"..\")
|| contains_ci(&s, b"..//")
|| contains_ci(&s, br"..\\"))
}
pub fn detect_xxe(input: &[u8]) -> Result<bool, DetectionError> {
validate_input(input)?;
let s = percent_decode_lower(input);
Ok(contains_ci(&s, b"<!doctype")
&& contains_ci(&s, b"<!entity")
&& (contains_ci(&s, b"system") || contains_ci(&s, b"public")))
}