@@ -5,7 +5,7 @@ use std::time::Duration;
55use 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.
1111use 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