Skip to content

Commit 55525e6

Browse files
author
zoidex
committed
fixed the waf detection
1 parent ef10f47 commit 55525e6

File tree

2 files changed

+73
-93
lines changed

2 files changed

+73
-93
lines changed

src/resolver/mod.rs

Lines changed: 33 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -155,12 +155,6 @@ pub async fn run_resolver(
155155
}
156156
};
157157

158-
// Check if a Web Application Firewall (WAF) is detected for the specified host with port
159-
if waf::detect_waf(ip_host).await {
160-
// If a WAF is detected, skip to the next iteration of the loop
161-
continue;
162-
}
163-
164158
// Build a request with the GET method and the parsed URL
165159
let mut request = Request::new(Method::GET, ip_url);
166160

@@ -172,6 +166,22 @@ pub async fn run_resolver(
172166
HeaderValue::from_str("localhost").unwrap(),
173167
);
174168

169+
// Create a clone of the `request` object and assign it to `request_clone`
170+
let request_clone = match request.try_clone() {
171+
// If the `try_clone()` method returns `Some`, which means the cloning was successful,
172+
// assign the cloned object to `rc`
173+
Some(rc) => rc,
174+
// If the `try_clone()` method returns `None`, which means the cloning failed,
175+
// skip to the next iteration of the loop
176+
None => continue,
177+
};
178+
179+
// Check if a Web Application Firewall (WAF) is detected for the specified `ip_host` with `request_clone`
180+
if waf::detect_waf(ip_host, request_clone).await {
181+
// If a WAF is detected, skip to the next iteration of the loop
182+
continue;
183+
}
184+
175185
// Make a request with the modified headers using the 'client' object
176186
let response = match client.execute(request).await {
177187
// If the request is successful, assign the response to 'response'
@@ -283,12 +293,6 @@ pub async fn run_resolver(
283293
let main_page = ip_str.clone();
284294
let main_site = main_page.clone();
285295

286-
// Check if a Web Application Firewall (WAF) is detected for the specified host with port
287-
if waf::detect_waf(main_site).await {
288-
// If a WAF is detected, skip to the next iteration of the loop
289-
continue;
290-
}
291-
292296
// Parse the job IP address into a URL
293297
let ip_url = match reqwest::Url::parse(&ip_str.to_string()) {
294298
// If parsing succeeds, assign the parsed URL to 'ip_url'
@@ -307,6 +311,23 @@ pub async fn run_resolver(
307311
reqwest::header::HOST,
308312
HeaderValue::from_str(&unresolved_host).unwrap(),
309313
);
314+
315+
// Create a clone of the `request` object and assign it to `request_clone`
316+
let request_clone = match request.try_clone() {
317+
// If the `try_clone()` method returns `Some`, which means the cloning was successful,
318+
// assign the cloned object to `rc`
319+
Some(rc) => rc,
320+
// If the `try_clone()` method returns `None`, which means the cloning failed,
321+
// skip to the next iteration of the loop
322+
None => continue,
323+
};
324+
325+
// Check if a Web Application Firewall (WAF) is detected for the specified host with port
326+
if waf::detect_waf(main_site, request_clone).await {
327+
// If a WAF is detected, skip to the next iteration of the loop
328+
continue;
329+
}
330+
310331
// Make a request with the modified headers using the 'client' object
311332
let response = match client.execute(request).await {
312333
// If the request is successful, assign the response to 'response'

src/waf/mod.rs

Lines changed: 40 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use std::time::Duration;
55
use regex::Regex;
66

77
// Importing the `redirect` function from the `reqwest` crate.
8-
use reqwest::redirect;
8+
use reqwest::{redirect, Request};
99

1010
// Importing the `Value` enum from the `serde_json` crate.
1111
use serde_json::Value;
@@ -508,7 +508,7 @@ const WAF_SIGS: &str = r#"
508508
]
509509
"#;
510510

511-
pub async fn detect_waf(host: String) -> bool {
511+
pub async fn detect_waf(host: String, request: Request) -> bool {
512512
// Parse the string of data into serde_json::Value.
513513
let signature: Value = match serde_json::from_str(&WAF_SIGS) {
514514
Ok(v) => v, // If parsing is successful, assign the parsed value to `signature`.
@@ -518,15 +518,6 @@ pub async fn detect_waf(host: String) -> bool {
518518
}
519519
};
520520

521-
// Parse the host string into a reqwest::Url.
522-
let url = match reqwest::Url::parse(&host) {
523-
Ok(url) => url, // If parsing is successful, assign the parsed URL to `url`.
524-
Err(_) => {
525-
// If parsing fails, print the error message and return `false`.
526-
return false;
527-
}
528-
};
529-
530521
// Create a new header map.
531522
let mut headers = reqwest::header::HeaderMap::new();
532523
headers.insert(
@@ -546,88 +537,56 @@ pub async fn detect_waf(host: String) -> bool {
546537
.build()
547538
.unwrap();
548539

549-
// Create a GET request using the client and the parsed URL.
550-
let get = client.get(url);
551-
let req = match get.build() {
552-
Ok(r) => r, // If building the request is successful, assign the request to `req`.
553-
Err(_) => return false, // If building the request fails, return `false`.
554-
};
555-
556540
// Execute the request and get the response.
557-
let response = match client.execute(req).await {
541+
let response = match client.execute(request).await {
558542
Ok(r) => r, // If executing the request is successful, assign the response to `response`.
559543
Err(_) => return false, // If executing the request fails, return `false`.
560544
};
561545

562-
// Get the headers from the response and iterate over them.
563-
let mut is_matched = false;
564-
565-
// Get the regex pattern from the `signature` value.
566-
let pattern = match signature[0]["REGEX"].as_str() {
567-
Some(p) => String::from(format!("(?i){}", p.to_string())), // If the pattern exists, assign it to `pattern`.
568-
None => "".to_string(), // If the pattern doesn't exist, skip to the next header.
569-
};
570-
571-
// Split the `pattern` string by ":" and store the parts in `regex_parts`.
572-
let mut regex_parts = pattern.split(":");
573-
574-
// Extract the first part of `regex_parts` and assign it to `header_name`.
575-
let header_name = match regex_parts.next() {
576-
Some(p) => p.replace("^", ""), // If the first part exists, remove any "^" characters and assign it to `header_name`.
577-
None => "".to_string(), // If the first part doesn't exist, assign an empty string to `header_name`.
546+
let signatures = match signature.as_array() {
547+
Some(s) => s,
548+
None => return false, // If executing the request fails, return `false`.
578549
};
579550

580-
// Clone the value of `header_name` and assign it to `header_map_key`.
581-
let header_map_key = header_name.clone();
551+
for sig in signatures {
552+
// Get the regex pattern from the `signature` value.
553+
let pattern = match sig["REGEX"].as_str() {
554+
Some(p) => String::from(format!("(?i){}", p.to_string())), // If the pattern exists, assign it to `pattern`.
555+
None => "".to_string(), // If the pattern doesn't exist, skip to the next header.
556+
};
582557

583-
// Get the headers from the `response` object.
584-
let headers = response.headers();
558+
// Get the headers from the `response` object.
559+
let headers = response.headers();
560+
let mut header_str = String::from("");
561+
for header in headers {
562+
let header_name = header.0.to_string();
563+
let header_value = match header.1.to_str() {
564+
Ok(r) => r.to_string(), // If creating the regex is successful, assign it to `re`.
565+
Err(_) => "".to_string(), // If creating the regex fails, skip to the next header.
566+
};
585567

586-
// Get the regex pattern from the `signature` value.
587-
let pattern = match signature[0]["REGEX"].as_str() {
588-
Some(p) => String::from(format!("(?i){}", p.to_string())), // If the pattern exists, assign it to `pattern`.
589-
None => return false, // If the pattern doesn't exist, skip to the next header.
590-
};
591-
592-
// Print the chosen WAF signature pattern and the header being checked.
593-
eprintln!("[-] Detecting WAF with signature: {}", pattern);
594-
595-
// Get the value of the header with the name `header_name`.
596-
let get_header_value = match headers.get(header_name) {
597-
Some(n) => match n.to_str() {
598-
Ok(v) => v.to_string(), // If the header value can be converted to a string, assign it to `get_header_value`.
599-
Err(_) => "".to_string(), // If an error occurs while converting the header value to a string, assign an empty string to `get_header_value`.
600-
},
601-
None => "".to_string(), // If the header doesn't exist, assign an empty string to `get_header_value`.
602-
};
603-
604-
// Check if the value of `get_header_value` is empty
605-
if get_header_value.is_empty() {
606-
// If it is empty, return false
607-
return false;
608-
}
568+
header_str.push_str(&format!("{}: {}\n", header_name, header_value));
569+
}
609570

610-
// Create the header string by formatting the `header_map_key` and `header_map_value` variables.
611-
let header = String::from(format!("{}: {}", header_map_key, get_header_value));
571+
// Get the WAF name from the `signature` value.
572+
let waf_name = match sig["WAF_NAME"].as_str() {
573+
Some(p) => p, // If the WAF name exists, assign it to `waf_name`.
574+
None => return false, // If the WAF name doesn't exist, skip to the next header.
575+
};
612576

613-
// Get the WAF name from the `signature` value.
614-
let waf_name = match signature[0]["WAF_NAME"].as_str() {
615-
Some(p) => p, // If the WAF name exists, assign it to `waf_name`.
616-
None => return false, // If the WAF name doesn't exist, skip to the next header.
617-
};
577+
// Create a regular expression object from the pattern.
578+
let re = match Regex::new(&pattern) {
579+
Ok(r) => r, // If creating the regex is successful, assign it to `re`.
580+
Err(_) => return false, // If creating the regex fails, skip to the next header.
581+
};
618582

619-
// Create a regular expression object from the pattern.
620-
let re = match Regex::new(&pattern) {
621-
Ok(r) => r, // If creating the regex is successful, assign it to `re`.
622-
Err(_) => return false, // If creating the regex fails, skip to the next header.
623-
};
624-
625-
// Check if the header value matches the regex pattern.
626-
if re.is_match(&header) {
627-
// Print that a WAF has been detected on the host.
628-
eprintln!("[+] WAF detected {} on host: {}", waf_name, host);
629-
is_matched = true;
583+
// Check if the header value matches the regex pattern.
584+
if re.is_match(&header_str) {
585+
// Print that a WAF has been detected on the host.
586+
eprintln!("[+] WAF detected {} on host: {}", waf_name, host);
587+
return true;
588+
}
630589
}
631590

632-
return is_matched; // If no header matches the regex pattern, return `false`.
591+
return false; // If no header matches the regex pattern, return `false`.
633592
}

0 commit comments

Comments
 (0)