diff --git a/Cargo.lock b/Cargo.lock index 6f481f32..21bedec2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1455,7 +1455,6 @@ dependencies = [ "url", "urlencoding", "yaml-rust", - "yaml-validator", ] [[package]] @@ -2188,13 +2187,3 @@ checksum = "56c1936c4cc7a1c9ab21a1ebb602eb942ba868cbd44a99cb7cdc5892335e1c85" dependencies = [ "linked-hash-map", ] - -[[package]] -name = "yaml-validator" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "771599d11c5bbae95a86de26f063daf4e61d03050694a3e393fd6eb9461b902c" -dependencies = [ - "thiserror", - "yaml-rust", -] diff --git a/TODO.md b/TODO.md index 0ac76002..57b7f358 100644 --- a/TODO.md +++ b/TODO.md @@ -1,3 +1,3 @@ -* Create XSS payload generator -* Async Lua function -* Better error handling +* [x] Create XSS payload generator +* [] Async Lua function +* [] Better error handling diff --git a/scanners/Cargo.toml b/scanners/Cargo.toml index 07464d8b..11cffa59 100644 --- a/scanners/Cargo.toml +++ b/scanners/Cargo.toml @@ -17,4 +17,3 @@ scraper = "0.12.0" urlencoding = "2.1.0" fancy-regex = "0.8.0" yaml-rust = "0.4.5" -yaml-validator = "0.1.0" diff --git a/scanners/src/lib.rs b/scanners/src/lib.rs index cf195f6c..04ca6364 100644 --- a/scanners/src/lib.rs +++ b/scanners/src/lib.rs @@ -4,12 +4,6 @@ pub use urlencoding::encode as url_encode; #[cfg(test)] mod tests { - #[test] - fn it_works() { - let result = 2 + 2; - assert_eq!(result, 4); - } - #[test] fn test_urlencode() { let url = "http://www.google.com/search?q=rust+language"; diff --git a/scanners/src/scan/xss/mod.rs b/scanners/src/scan/xss/mod.rs index cdbc31b8..3924206a 100644 --- a/scanners/src/scan/xss/mod.rs +++ b/scanners/src/scan/xss/mod.rs @@ -6,9 +6,9 @@ use log::error; use scant3r_utils::{ random_str, requests::{Curl, Msg}, - Injector::{Injector, Urlinjector}, + injector::{Injector, Urlinjector}, }; -use std::collections::HashMap; +use console::style; mod parser; use parser::{html_parse, html_search}; @@ -16,6 +16,11 @@ use parser::{html_parse, html_search}; mod bypass; pub use bypass::{PayloadGen, XssPayloads}; + +pub fn print_poc(report: &Report) { + println!("{} Valid XSS\n{} URL: {}\n{} CURL: {}\n{} MATCH: {}\n{} PAYLOAD: \"{}\"", style("[+]").green(), style("[!]").yellow(), report.url, style("[!]").yellow(),report.curl,style("[!]").yellow(),report.match_payload,style("[!]").yellow(),report.payload.replace("\"","\\\"")); +} + pub struct Xss<'t> { request: &'t Msg, injector: Injector, @@ -127,19 +132,25 @@ impl XssUrlParamsValue for Xss<'_> { Ok(resp) => { let d = html_search(resp.body.as_str(), &pay.search); if d.len() > count.len() { - _prog.println(format!( + /*_prog.println(format!( "FOUND XSS \nReflect: {:?}\nPayload: {}\nMatch: {}\nCURL: \n{}", reflect, pay.payload, d, req.curl() - )); - _found.push(Report{ + ));*/ + print_poc(&Report{ url: req.url.to_string(), match_payload: d, payload: pay.payload.to_string(), curl: req.curl(), }); + /*_found.push(Report{ + url: req.url.to_string(), + match_payload: d, + payload: pay.payload.to_string(), + curl: req.curl(), + });*/ break; } } diff --git a/scripting/src/func.rs b/scripting/src/func.rs index 0a1bb617..82ffdda8 100644 --- a/scripting/src/func.rs +++ b/scripting/src/func.rs @@ -1,10 +1,21 @@ extern crate scant3r_utils; use hlua::{ Lua, - function1, function3, + function1 }; +use scant3r_utils::requests::{Msg,Settings}; use std::fs::File; +fn sender(url: String) -> String { + let req = Msg::new() + .url(url) + .method("GET".to_string()); + match req.send() { + Ok(test) => println!("TEST"), + Err(e) => println!("ERR"), + } + String::from("TES") +} fn bruh(name: String) -> String { format!("YEAH BOOYAH {}",name) } diff --git a/utils/src/injector.rs b/utils/src/injector.rs index 2876917d..fdc2d887 100644 --- a/utils/src/injector.rs +++ b/utils/src/injector.rs @@ -8,12 +8,12 @@ pub struct Injector { } pub trait Urlinjector { - fn url_value(&self, _payload: &str) -> HashMap>; - fn set_urlvalue(&self, param: &str, _payload: &str) -> Url; + fn url_value(&self, payload: &str) -> HashMap>; + fn set_urlvalue(&self, param: &str, payload: &str) -> Url; } impl Urlinjector for Injector { - fn set_urlvalue(&self, param: &str, _payload: &str) -> Url { + fn set_urlvalue(&self, param: &str, payload: &str) -> Url { let mut url = self.request.clone(); let mut final_params = HashMap::new(); @@ -25,9 +25,9 @@ impl Urlinjector for Injector { if k == param { final_params.insert(k.to_string(), { if self.keep_value == true { - format!("{}{}", v.to_string(), _payload) + format!("{}{}", v.to_string(), payload) } else { - format!("{}", _payload) + format!("{}", payload) } }); } else { @@ -39,32 +39,22 @@ impl Urlinjector for Injector { url } - /// Set the payload to every GET parameter in the url - /// * example : - /// ```rust - /// let injector = Injector { - /// request: Url::parse("http://example.com/index.php?param1=value1¶m2=value2").unwrap(), - /// }; - /// let mut urls = injector.url_value("hacker"); - /// assert_eq!(urls.len(),2); - /// {"param1":url::Url::parse("http://example.com/index.php?param1=value1hacker¶m2=value2").unwrap(),"param2":url::Url::parse("http://example.com/index.php?param1=value1¶m2=value2hacker").unwrap()} - /// ``` - fn url_value(&self, _payload: &str) -> HashMap> { + fn url_value(&self, payload: &str) -> HashMap> { let url = self.request.clone(); - let _params: HashMap<_, _> = url.query_pairs().collect::>(); + let params: HashMap<_, _> = url.query_pairs().collect::>(); let mut scan_params = HashMap::new(); - let mut bruh: HashMap> = HashMap::new(); + let mut result: HashMap> = HashMap::new(); let mut param_list = Vec::new(); - _params.iter().for_each(|(key, value)| { + params.iter().for_each(|(key, value)| { scan_params.insert(key.to_string(), value.to_string()); param_list.push(key.to_string()); }); - drop(_params); + drop(params); scan_params.iter().for_each(|(key, value)| { - let mut p = Vec::new(); + let mut edit_params = Vec::new(); - _payload.split("\n").into_iter().for_each(|payload| { + payload.split("\n").into_iter().for_each(|payload| { let mut new_params = scan_params.clone(); new_params.insert(key.to_string(), value.as_str().to_owned() + payload); let mut new_url = url.clone(); @@ -72,11 +62,11 @@ impl Urlinjector for Injector { new_url.query_pairs_mut().extend_pairs(&new_params); - p.push(new_url); + edit_params.push(new_url); }); - bruh.insert(key.to_string(), p); + result.insert(key.to_string(), edit_params); }); - bruh + result } } diff --git a/utils/src/lib.rs b/utils/src/lib.rs index 62c2fef3..8e14d573 100644 --- a/utils/src/lib.rs +++ b/utils/src/lib.rs @@ -1,7 +1,4 @@ -#[allow(non_snake_case)] -#[path = "./injector.rs"] -pub mod Injector; -pub mod poc; +pub mod injector; pub mod requests; use rand::distributions::Alphanumeric; use rand::{thread_rng, Rng}; @@ -12,7 +9,7 @@ use urlencoding::encode as url_encode; pub fn urlencode(s: &str, many: Option) -> String { let mut after_encode = String::from(s); for _ in 0..many.unwrap_or(1) { - after_encode = url_encode(s).to_string(); + after_encode = url_encode(&after_encode).to_string(); } after_encode } @@ -47,14 +44,38 @@ pub fn extract_headers_vec(header: Vec) -> HashMap { #[cfg(test)] mod tests { + use reqwest::Url; + use std::collections::HashMap; + use crate::injector::{self, Urlinjector}; + #[test] - fn it_works() { + fn check_headers() { let result = super::extract_headers("Content-Type: application/json".to_string()); assert_eq!(result.get("Content-Type").unwrap(), "application/json"); } #[test] fn check_urlencode() { - let result = super::urlencode("http://www.google.com", None); + let result = super::urlencode("http://www.google.com", Some(2)); assert_eq!(result, "http%3A%2F%2Fwww.google.com"); } + #[test] + fn check_header_vec() { + let mut test_result = HashMap::new(); + test_result.insert("Server".to_string(), "Nginx".to_string()); + let result = super::extract_headers_vec(vec!["Server: Nginx".to_string()]); + assert_eq!(test_result,result); + } + #[test] + fn check_url_injector_keepvalue() { + let mut test_params = HashMap::new(); + test_params.insert("test".to_string(), vec![Url::parse("http://google.com/?test=1hello").unwrap()]); + let inj = injector::Injector{ + request: Url::parse("http://google.com/?test=1").unwrap(), + keep_value: true + }; + let newparam_value = inj.set_urlvalue("test", "hello"); + let inject_payload = inj.url_value("hello"); + assert_eq!(newparam_value.as_str(),"http://google.com/?test=1hello"); + assert_eq!(inject_payload, test_params); + } } diff --git a/utils/src/poc.rs b/utils/src/poc.rs deleted file mode 100644 index 85c3d053..00000000 --- a/utils/src/poc.rs +++ /dev/null @@ -1,60 +0,0 @@ -#[path = "requests.rs"] -mod requests; -use crate::requests::Msg; - -pub struct Poc<'a> { - pub name: String, - pub payload: String, - pub request: &'a Msg, -} - -pub trait Curl { - fn curl(&self) -> String; -} - -impl Curl for Poc<'_> { - fn curl(&self) -> String { - // convert isahc request to curl - let mut curl = String::from("curl "); - // extract headers - self.request.headers.iter().for_each(|(key, value)| { - curl.push_str(&format!("-H \"{}: {}\" ", key, value.replace("\"", "\\\""))); - }); - // extract body - if self.request.body.as_ref().unwrap().len() > 0 { - curl.push_str(&format!( - "-d \"{:?}\" ", - self.request.body.as_ref().unwrap() - )); - } - // extract url - curl.push_str(&format!("\"{}\"", self.request.url)); - // extract method - curl.push_str(&format!(" -X {}", self.request.method)); - // proxy - if self.request.proxy.as_ref().unwrap_or(&"".to_string()).len() > 0 { - curl.push_str(&format!(" -x {}", self.request.proxy.as_ref().unwrap())); - } - curl - } -} - -pub trait Plain { - fn plain(&self) -> String; -} - -impl Plain for Poc<'_> { - fn plain(&self) -> String { - String::from("") - } -} - -pub trait Json { - fn json(&self) -> String; -} - -impl Json for Poc<'_> { - fn json(&self) -> String { - String::from("") - } -} diff --git a/utils/src/requests.rs b/utils/src/requests.rs index d268d502..47b982db 100644 --- a/utils/src/requests.rs +++ b/utils/src/requests.rs @@ -1,8 +1,9 @@ #![allow(dead_code)] use reqwest::blocking::ClientBuilder; -use reqwest::header::HeaderMap; -use reqwest::header::HeaderName; -use reqwest::header::HeaderValue; +use reqwest::header::{ + HeaderMap, + HeaderName, + HeaderValue}; use reqwest::redirect::Policy; use reqwest::Proxy; use reqwest::StatusCode; @@ -112,7 +113,8 @@ impl Msg { self.headers.iter().for_each(|(k, v)| { headers.append( HeaderName::from_bytes(k.as_bytes()).unwrap(), - HeaderValue::from_str(v.as_str()).unwrap()); + HeaderValue::from_str(v.as_str()).unwrap(), + ); }); if headers.len() > 0 { resp = resp.default_headers(headers);