Skip to main content

wafrift_encoding/encoding/keyword/
space.rs

1//! Space-replacement strategies.
2
3use rand::seq::SliceRandom as _;
4
5const SQL_BLANK_CHARS: &[char] = &['\t', '\n', '\r', '\x0b', '\x0c'];
6
7/// Insert tab characters BETWEEN tokens by replacing spaces with tabs.
8///
9/// Preserves keyword integrity while breaking WAF regex matching on space-separated tokens.
10pub fn whitespace_insert(payload: &str) -> String {
11    payload.replace(' ', "\t")
12}
13
14/// Replace spaces with SQL comments (`/**/`).
15pub fn space_to_comment(payload: &str) -> String {
16    payload.replace(' ', "/**/")
17}
18
19/// Replace spaces with dash comments (`--\n`).
20pub fn space_to_dash(payload: &str) -> String {
21    payload.replace(' ', "--\n")
22}
23
24/// Replace spaces with hash comments (`#`).
25pub fn space_to_hash(payload: &str) -> String {
26    payload.replace(' ', "#")
27}
28
29/// Replace spaces with plus signs (`+`).
30pub fn space_to_plus(payload: &str) -> String {
31    payload.replace(' ', "+")
32}
33
34/// Replace spaces with random blank characters.
35pub fn space_to_random_blank(payload: &str) -> String {
36    let mut rng = rand::thread_rng();
37    payload
38        .chars()
39        .map(|c| {
40            if c == ' ' {
41                *SQL_BLANK_CHARS.choose(&mut rng).unwrap_or(&'\t')
42            } else {
43                c
44            }
45        })
46        .collect()
47}
48
49#[cfg(test)]
50mod tests {
51    use super::*;
52
53    #[test]
54    fn whitespace_insert_replaces_spaces() {
55        assert_eq!(whitespace_insert("SELECT * FROM"), "SELECT\t*\tFROM");
56    }
57
58    #[test]
59    fn space_to_comment_replaces_spaces() {
60        assert_eq!(space_to_comment("SELECT * FROM"), "SELECT/**/*/**/FROM");
61    }
62
63    #[test]
64    fn space_to_dash_replaces_spaces() {
65        assert_eq!(space_to_dash("SELECT * FROM"), "SELECT--\n*--\nFROM");
66    }
67
68    #[test]
69    fn space_to_hash_replaces_spaces() {
70        assert_eq!(space_to_hash("SELECT * FROM"), "SELECT#*#FROM");
71    }
72
73    #[test]
74    fn space_to_plus_replaces_spaces() {
75        assert_eq!(space_to_plus("SELECT * FROM"), "SELECT+*+FROM");
76    }
77
78    #[test]
79    fn space_to_random_blank_replaces_spaces() {
80        let result = space_to_random_blank("SELECT * FROM");
81        assert!(!result.contains(' '));
82        assert_eq!(result.len(), "SELECT * FROM".len());
83    }
84}