|
1 |
| -/* |
2 |
| - * This file is part of Lotus Project, an Web Security Scanner written in Rust based on Lua Scripts |
3 |
| - * For details, please see https://github.com/rusty-sec/lotus/ |
4 |
| - * |
5 |
| - * Copyright (c) 2022 - Khaled Nassar |
6 |
| - * |
7 |
| - * Please note that this file was originally released under the |
8 |
| - * GNU General Public License as published by the Free Software Foundation; |
9 |
| - * either version 2 of the License, or (at your option) any later version. |
10 |
| - * |
11 |
| - * |
12 |
| - * Unless required by applicable law or agreed to in writing, software |
13 |
| - * distributed under the License is distributed on an "AS IS" BASIS, |
14 |
| - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
15 |
| - * See the License for the specific language governing permissions and |
16 |
| - * limitations under the License. |
17 |
| - */ |
| 1 | +use reqwest::header::HeaderMap; |
| 2 | +use reqwest::header::{HeaderName, HeaderValue}; |
| 3 | +use std::collections::HashMap; |
| 4 | +use std::path::PathBuf; |
| 5 | +use structopt::StructOpt; |
18 | 6 |
|
19 |
| -use clap::{App, Arg, ArgMatches}; |
20 |
| -mod validator; |
21 |
| -pub fn cmd_args() -> ArgMatches { |
22 |
| - App::new("Lotus") |
23 |
| - .version("0.3-beta") |
24 |
| - .author("Khaled Nassar <knassar702@gmail.com>") |
25 |
| - .about("Fast Web Security Scanner written in Rust based on Lua Scripts ") |
26 |
| - .arg( |
27 |
| - Arg::with_name("out_script") |
28 |
| - .help("Use Custom Lua for reporting") |
29 |
| - .long("--lua-report") |
30 |
| - .validator(validator::file_exists) |
31 |
| - .takes_value(true) |
32 |
| - .required_unless_present("output"), |
33 |
| - ) |
34 |
| - .arg( |
35 |
| - Arg::with_name("default_headers") |
36 |
| - .help("Default Request Headers") |
37 |
| - .validator(validator::valid_json) |
38 |
| - .takes_value(true) |
39 |
| - .default_value("{}") |
40 |
| - .long("headers"), |
41 |
| - ) |
42 |
| - .arg( |
43 |
| - Arg::with_name("redirects") |
44 |
| - .help("Set limit of http redirects") |
45 |
| - .long("redirects") |
46 |
| - .default_value("10"), |
47 |
| - ) |
48 |
| - .arg( |
49 |
| - Arg::with_name("timeout") |
50 |
| - .help("Set Connection timeout") |
51 |
| - .long("timeout") |
52 |
| - .default_value("10"), |
53 |
| - ) |
54 |
| - .arg( |
55 |
| - Arg::with_name("proxy") |
56 |
| - .help("Forward all connection through a proxy (eg: --proxy http://localhost:8080)") |
57 |
| - .required(false) |
58 |
| - .takes_value(true) |
59 |
| - .validator(url::Url::parse) |
60 |
| - .long("proxy"), |
61 |
| - ) |
62 |
| - .arg( |
63 |
| - Arg::with_name("workers") |
64 |
| - .help("Number of works of urls") |
65 |
| - .short('w') |
66 |
| - .takes_value(true) |
67 |
| - .default_value("10") |
68 |
| - .long("workers"), |
69 |
| - ) |
70 |
| - .arg( |
71 |
| - Arg::with_name("log") |
72 |
| - .help("Save all logs to custom file") |
73 |
| - .takes_value(true) |
74 |
| - .short('l') |
75 |
| - .long("log"), |
76 |
| - ) |
77 |
| - .arg( |
78 |
| - Arg::with_name("script_threads") |
79 |
| - .help("Workers for lua scripts") |
80 |
| - .short('t') |
81 |
| - .long("script-threads") |
82 |
| - .takes_value(true) |
83 |
| - .default_value("5"), |
84 |
| - ) |
85 |
| - .arg( |
86 |
| - Arg::with_name("scripts") |
87 |
| - .help("Path of scripts dir") |
88 |
| - .takes_value(true) |
89 |
| - .short('s') |
90 |
| - .long("scripts") |
91 |
| - .required(true), |
92 |
| - ) |
93 |
| - .arg( |
94 |
| - Arg::with_name("output") |
95 |
| - .help("Path of the JSON output fiel") |
96 |
| - .required_if_eq("out_script", "") |
97 |
| - .takes_value(true) |
98 |
| - .long("output") |
99 |
| - .short('o'), |
| 7 | +fn parse_headers(raw_headers: &str) -> Result<HeaderMap, serde_json::Error> { |
| 8 | + let parsed_json = serde_json::from_str::<HashMap<String, String>>(raw_headers); |
| 9 | + |
| 10 | + if parsed_json.is_err() { |
| 11 | + return Err(parsed_json.unwrap_err()); |
| 12 | + } |
| 13 | + let mut user_headers = HeaderMap::new(); |
| 14 | + user_headers.insert( |
| 15 | + HeaderName::from_bytes("User-agent".as_bytes()).unwrap(), |
| 16 | + HeaderValue::from_bytes( |
| 17 | + "Mozilla/5.0 (X11; Manjaro; Linux x86_64; rv:100.0) Gecko/20100101 Firefox/100.0" |
| 18 | + .as_bytes(), |
100 | 19 | )
|
101 |
| - .arg(Arg::with_name("nolog").help("no logging")) |
102 |
| - .get_matches() |
| 20 | + .unwrap(), |
| 21 | + ); |
| 22 | + parsed_json |
| 23 | + .unwrap() |
| 24 | + .iter() |
| 25 | + .for_each(|(headername, headervalue)| { |
| 26 | + user_headers.insert( |
| 27 | + HeaderName::from_bytes(headername.as_bytes()).unwrap(), |
| 28 | + HeaderValue::from_bytes(headervalue.as_bytes()).unwrap(), |
| 29 | + ); |
| 30 | + }); |
| 31 | + Ok(user_headers) |
| 32 | +} |
| 33 | + |
| 34 | +#[derive(Debug, StructOpt)] |
| 35 | +#[structopt( |
| 36 | + name = "Lotus", |
| 37 | + about = "Fast Web Security Scanner written in Rust based on Lua Scripts" |
| 38 | +)] |
| 39 | +pub struct Opts { |
| 40 | + // redirects limit |
| 41 | + #[structopt(short, long, default_value = "10")] |
| 42 | + pub redirects: u32, |
| 43 | + |
| 44 | + // threads |
| 45 | + #[structopt(short = "w", long = "workers", default_value = "10")] |
| 46 | + pub workers: usize, |
| 47 | + |
| 48 | + // timeout |
| 49 | + #[structopt(short = "t", long = "timeout", default_value = "10")] |
| 50 | + pub timeout: u64, |
| 51 | + |
| 52 | + /// Input file |
| 53 | + #[structopt(parse(from_os_str))] |
| 54 | + pub script_path: PathBuf, |
| 55 | + |
| 56 | + /// Output file, stdout if not present |
| 57 | + #[structopt(short = "o", long = "output", parse(from_os_str))] |
| 58 | + pub output: Option<PathBuf>, |
| 59 | + |
| 60 | + #[structopt(short = "p", long = "proxy")] |
| 61 | + pub proxy: Option<String>, |
| 62 | + |
| 63 | + #[structopt(long = "log")] |
| 64 | + pub log: Option<PathBuf>, |
| 65 | + |
| 66 | + #[structopt(long = "headers", parse(try_from_str = parse_headers), required = false, default_value = "{}")] |
| 67 | + pub headers: HeaderMap, |
103 | 68 | }
|
0 commit comments