Skip to content

Commit

Permalink
Merge branch 'main' into dev
Browse files Browse the repository at this point in the history
  • Loading branch information
Sh1Yo committed Jul 25, 2021
2 parents 6567ed3 + 542bde8 commit 6ddcd9e
Show file tree
Hide file tree
Showing 5 changed files with 98 additions and 50 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ Host: example.com
```

# Test
Feel free to check whether the tool works as expected and compare it with other tools at https://4rt.one/.
Feel free to check whether the tool works as expected and compare it with other tools at https://4rt.one/index.html.
There are 2 reflected parameters, 4 parameters that change code/headers/body, and one extra parameter with a not random value.

# Usage
Expand Down
8 changes: 7 additions & 1 deletion src/args.rs
Original file line number Diff line number Diff line change
Expand Up @@ -240,6 +240,11 @@ pub fn get_config() -> (Config, usize) {
.long("http2")
.help("Prefer http/2 over http/1.1")
.conflicts_with("request")
)
.arg(
Arg::with_name("verify")
.long("verify")
.help("Verify found parameters one more time")
);

let args = app.clone().get_matches();
Expand Down Expand Up @@ -539,7 +544,8 @@ pub fn get_config() -> (Config, usize) {
learn_requests_count,
max,
concurrency,
http2: args.is_present("http2")
http2: args.is_present("http2"),
verify: args.is_present("verify")
};

config = if !request.is_empty() {
Expand Down
77 changes: 50 additions & 27 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -150,8 +150,8 @@ async fn run() {
if params.len() < max {
max = params.len();
if max == 0 {
writeln!(io::stderr(), "Parameter list is empty").ok();
std::process::exit(1)
params.push(String::from("something"));
max = 1;
}
}

Expand All @@ -163,18 +163,20 @@ async fn run() {
.matches(&query.values().next().unwrap().replace("%random%_", "").as_str())
.count() as usize;

writeln!(
io::stdout(),
"|{} {}\n|{} {}\n|{} {}\n|{} {}\n",
&"Code".magenta(),
&initial_response.code.to_string().green(),
&"Response Len".magenta(),
&initial_response.text.len().to_string().green(),
&"Reflections".magenta(),
&reflections_count.to_string().green(),
&"Words".magenta(),
&params.len().to_string().green(),
).ok();
if config.verbose > 0 {
writeln!(
io::stdout(),
"|{} {}\n|{} {}\n|{} {}\n|{} {}\n",
&"Code".magenta(),
&initial_response.code.to_string().green(),
&"Response Len".magenta(),
&initial_response.text.len().to_string().green(),
&"Reflections".magenta(),
&reflections_count.to_string().green(),
&"Words".magenta(),
&params.len().to_string().green(),
).ok();
}

//make a few requests and collect all persistent diffs, check for stability
let (mut diffs, stable) = empty_reqs(
Expand Down Expand Up @@ -310,9 +312,34 @@ async fn run() {
remaining_params = Vec::new()
}


found_params.sort();
found_params.dedup();

if config.verify {
let mut filtered_params = Vec::new();
for param in found_params {
let response = request(
&config, &client,
&make_hashmap(
&[param.clone()], config.value_size
),
reflections_count
).await;
let (is_code_the_same, new_diffs) = compare(&initial_response, &response);
let mut is_the_body_the_same = true;
for diff in new_diffs.iter() {
if !diffs.iter().any(|i| &i==&diff) {
is_the_body_the_same = false;
}
}
if !response.reflected_params.is_empty() || !is_the_body_the_same || !is_code_the_same {
filtered_params.push(param);
}
}
found_params = filtered_params;
}

if !config.replay_proxy.is_empty() {
let temp_config = Config{
disable_cachebuster: true,
Expand Down Expand Up @@ -346,19 +373,15 @@ async fn run() {
}
}

if !found_params.is_empty() {
let output = create_output(&config, found_params);
let output = create_output(&config, found_params);

if !config.output_file.is_empty() {
match std::fs::write(&config.output_file, &output) {
Ok(_) => (),
Err(err) => {
writeln!(io::stderr(), "[!] {}", err).ok();
}
};
}
write!(io::stdout(), "\n{}", &output).ok();
} else {
writeln!(io::stdout(), "nothing found").ok();
if !config.output_file.is_empty() {
match std::fs::write(&config.output_file, &output) {
Ok(_) => (),
Err(err) => {
writeln!(io::stderr(), "[!] {}", err).ok();
}
};
}
write!(io::stdout(), "\n{}", &output).ok();
}
3 changes: 2 additions & 1 deletion src/structs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,8 @@ pub struct Config {
pub learn_requests_count: usize,
pub max: usize,
pub concurrency: usize,
pub http2: bool
pub http2: bool,
pub verify: bool
}

#[derive(Debug)]
Expand Down
58 changes: 38 additions & 20 deletions src/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -423,20 +423,29 @@ where
pub fn create_output(config: &Config, found_params: Vec<String>) -> String {
match config.output_format.as_str() {
"url" => {
let mut line = match config.initial_url.contains('?') {
true => config.initial_url.to_owned()+"&",
false => config.initial_url.to_owned()+"?"
let mut line = if !found_params.is_empty() {
match config.initial_url.contains('?') {
true => config.initial_url.to_owned()+"&",
false => config.initial_url.to_owned()+"?"
}
} else {
config.initial_url.clone()
};

for param in &found_params {
line.push_str(&param);
if !param.contains('=') {
line.push('=');
line.push_str(&random_line(config.value_size));
if !found_params.is_empty() {

for param in &found_params {
line.push_str(&param);
if !param.contains('=') {
line.push('=');
line.push_str(&random_line(config.value_size));
}
line.push('&')
}
line.push('&')

line.pop();
}
line.pop();

line.push('\n');

line
Expand All @@ -448,26 +457,35 @@ pub fn create_output(config: &Config, found_params: Vec<String>) -> String {
&config.initial_url
);

for param in &found_params {
line.push('\"');
line.push_str(&param.replace("\"", "\\\""));
line.push('\"');
line.push_str(", ");
if !found_params.is_empty() {

for param in &found_params {
line.push('\"');
line.push_str(&param.replace("\"", "\\\""));
line.push('\"');
line.push_str(", ");
}

line = line[..line.len() - 2].to_string();
}

let mut line = line[..line.len() - 2].to_string();
line.push_str("]}\n");

line
},
_ => {
let mut line = format!("{} {} % ", &config.method, &config.initial_url);

for param in &found_params {
line.push_str(&param);
line.push_str(", ")
if !found_params.is_empty() {

for param in &found_params {
line.push_str(&param);
line.push_str(", ")
}

line = line[..line.len() - 2].to_string();
}

line = line[..line.len() - 2].to_string();
line.push('\n');
line
},
Expand Down

0 comments on commit 6ddcd9e

Please sign in to comment.