Skip to content

Commit ab44111

Browse files
author
Blake Jacobs
committed
Fixed a bug with the ETA, it would not produce the correct results.
1 parent 947c0d6 commit ab44111

File tree

5 files changed

+21
-119
lines changed

5 files changed

+21
-119
lines changed

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
name = "pathbuster"
33
authors = ["zoid", "<[email protected]>"]
44
description = "A path-normalization pentesting tool."
5-
version = "0.4.9"
5+
version = "0.5.0"
66
edition = "2021"
77
license = "MIT"
88
repository = "https://github.com/ethicalhackingplayground/pathbuster"

src/bruteforcer/mod.rs

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ pub async fn run_bruteforcer(
101101
let job_url = job.url.unwrap();
102102
let job_word = job.word.unwrap();
103103
let job_url_new = job_url.clone();
104-
104+
pb.inc(1);
105105
let mut web_root_url: String = String::from("");
106106
let mut internal_web_root_url: String = String::from(job_url);
107107
let url = match reqwest::Url::parse(&job_url_new) {
@@ -185,12 +185,12 @@ pub async fn run_bruteforcer(
185185
};
186186

187187
let public_resp_text = match public_resp.text().await {
188-
Ok(public_cl) => public_cl,
188+
Ok(public_resp_text) => public_resp_text,
189189
Err(_) => continue,
190190
};
191191

192192
let internal_resp_text = match internal_resp.text().await {
193-
Ok(internal_cl) => internal_cl,
193+
Ok(internal_resp_text) => internal_resp_text,
194194
Err(_) => continue,
195195
};
196196

@@ -210,7 +210,7 @@ pub async fn run_bruteforcer(
210210

211211
let (ok, distance_between_responses) =
212212
utils::get_response_change(&internal_resp_text, &public_resp_text);
213-
if ok && resp.status().as_str() == "200" || resp.status().as_str() == "401" {
213+
if ok && (resp.status().as_str() == "200" || resp.status().as_str() == "401") {
214214
let internal_resp_text_lines = internal_resp_text.lines().collect::<Vec<_>>();
215215
let public_resp_text_lines = public_resp_text.lines().collect::<Vec<_>>();
216216
let character_differences =
@@ -270,10 +270,9 @@ pub async fn run_bruteforcer(
270270
if let Err(_) = tx.send(result_msg).await {
271271
continue;
272272
}
273-
273+
pb.inc_length(1);
274274
return result;
275275
}
276-
pb.inc(1);
277276
}
278277
return BruteResult {
279278
data: "".to_string(),

src/detector/mod.rs

Lines changed: 6 additions & 105 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,13 @@
11
use std::{error::Error, process::exit, time::Duration};
22

33
use colored::Colorize;
4-
use differ::{Differ, Tag};
54
use governor::{Quota, RateLimiter};
65
use indicatif::ProgressBar;
76
use itertools::iproduct;
87
use regex::Regex;
98
use reqwest::{redirect, Proxy};
109
use tokio::{fs::File, io::AsyncWriteExt, sync::mpsc};
1110

12-
use crate::utils;
13-
1411
// the Job struct which will be used to define our settings for the detection jobs
1512
#[derive(Clone, Debug)]
1613
pub struct JobSettings {
@@ -149,7 +146,6 @@ pub async fn run_tester(
149146
let new_url = String::from(&job_url);
150147
let mut track_status_codes = 0;
151148
for _ in 0..path_cnt {
152-
let job_url_without_path = job_url_without_path.clone();
153149
let mut new_url = new_url.clone();
154150
if !new_url.as_str().ends_with("/") {
155151
new_url.push_str("/");
@@ -195,19 +191,6 @@ pub async fn run_tester(
195191
continue;
196192
}
197193
};
198-
let pub_get = client.get(job_url_without_path);
199-
let pub_req = match pub_get.build() {
200-
Ok(pub_req) => pub_req,
201-
Err(_) => {
202-
continue;
203-
}
204-
};
205-
let pub_resp = match client.execute(pub_req).await {
206-
Ok(pub_resp) => pub_resp,
207-
Err(_) => {
208-
continue;
209-
}
210-
};
211194

212195
let content_length = match resp.content_length() {
213196
Some(content_length) => content_length.to_string(),
@@ -251,38 +234,8 @@ pub async fn run_tester(
251234
}
252235
};
253236

254-
let internal_get = client.get(backonemore);
255-
256-
let internal_req = match internal_get.build() {
257-
Ok(internal_req) => internal_req,
258-
Err(_) => {
259-
continue;
260-
}
261-
};
262-
let internal_resp = match client.execute(internal_req).await {
263-
Ok(internal_resp) => internal_resp,
264-
Err(_) => {
265-
continue;
266-
}
267-
};
268-
269-
let internal_cl = match internal_resp.text().await {
270-
Ok(internal_cl) => internal_cl,
271-
Err(_) => continue,
272-
};
273-
274-
let public_cl = match pub_resp.text().await {
275-
Ok(public_cl) => public_cl,
276-
Err(_) => continue,
277-
};
278-
279237
// we hit the internal doc root.
280-
let (ok, distance_between_responses) =
281-
utils::get_response_change(&internal_cl, &public_cl);
282-
if response.status().as_str() != "400"
283-
&& ok
284-
&& result_url.contains(&job_payload_new)
285-
{
238+
if response.status().as_str() != "400" && result_url.contains(&job_payload_new) {
286239
// track the status codes
287240
if job_settings.drop_after_fail == response.status().as_str() {
288241
track_status_codes += 1;
@@ -314,41 +267,9 @@ pub async fn run_tester(
314267
},
315268
None => "Unknown",
316269
};
317-
318-
let internal_resp_text_lines = internal_cl.lines().collect::<Vec<_>>();
319-
let public_resp_text_lines = public_cl.lines().collect::<Vec<_>>();
320-
let character_differences =
321-
Differ::new(&public_resp_text_lines, &internal_resp_text_lines);
322-
if character_differences.spans().len() > 0 {
323-
pb.println(format!(
324-
"\n{}{}{} {}",
325-
"(".bold().white(),
326-
"*".bold().blue(),
327-
")".bold().white(),
328-
"found some response changes:".bold().green(),
329-
));
330-
for span in character_differences.spans() {
331-
match span.tag {
332-
Tag::Equal => (), // ignore
333-
Tag::Insert => (), // ignore
334-
Tag::Delete => (), // ignore
335-
Tag::Replace => {
336-
for line in &internal_resp_text_lines[span.b_start..span.b_end]
337-
{
338-
if line.to_string() == "" {
339-
pb.println(format!("\n{}", line.bold().white(),));
340-
} else {
341-
pb.println(format!("{}", line.bold().white(),));
342-
}
343-
}
344-
}
345-
}
346-
}
347-
}
348-
pb.println(format!("\n"));
349270
if response.status().is_client_error() {
350271
pb.println(format!(
351-
"{}{}{} {}{}{}\n{}{}{} {}\n\t {} {}{}{}\n\t {} {}{}{}\n\t {} {}{}{}\n\t {} {}{}{}\n\t {} {}{}{}\n\t {} {}{}{}\n\t",
272+
"{}{}{} {}{}{}\n{}{}{} {}\n\t {} {}{}{}\n\t {} {}{}{}\n\t {} {}{}{}\n\t {} {}{}{}\n\t {} {}{}{}\n\t",
352273
"[".bold().white(),
353274
"OK".bold().green(),
354275
"]".bold().white(),
@@ -379,15 +300,11 @@ pub async fn run_tester(
379300
"[".bold().white(),
380301
title.bold().purple(),
381302
"]".bold().white(),
382-
"deviation:".bold().white(),
383-
"[".bold().white(),
384-
distance_between_responses.to_string().bold().purple(),
385-
"]".bold().white(),
386303
));
387304
}
388305
if response.status().is_success() {
389306
pb.println(format!(
390-
"{}{}{} {}{}{}\n{}{}{} {}\n\t {} {}{}{}\n\t {} {}{}{}\n\t {} {}{}{}\n\t {} {}{}{}\n\t {} {}{}{}\n\t {} {}{}{}\n\t",
307+
"{}{}{} {}{}{}\n{}{}{} {}\n\t {} {}{}{}\n\t {} {}{}{}\n\t {} {}{}{}\n\t {} {}{}{}\n\t {} {}{}{}\n\t",
391308
"[".bold().white(),
392309
"OK".bold().green(),
393310
"]".bold().white(),
@@ -418,15 +335,11 @@ pub async fn run_tester(
418335
"[".bold().white(),
419336
title.bold().purple(),
420337
"]".bold().white(),
421-
"deviation:".bold().white(),
422-
"[".bold().white(),
423-
distance_between_responses.to_string().bold().purple(),
424-
"]".bold().white(),
425338
));
426339
}
427340
if response.status().is_redirection() {
428341
pb.println(format!(
429-
"{}{}{} {}{}{}\n{}{}{} {}\n\t {} {}{}{}\n\t {} {}{}{}\n\t {} {}{}{}\n\t {} {}{}{}\n\t {} {}{}{}\n\t {} {}{}{}\n\t",
342+
"{}{}{} {}{}{}\n{}{}{} {}\n\t {} {}{}{}\n\t {} {}{}{}\n\t {} {}{}{}\n\t {} {}{}{}\n\t {} {}{}{}\n\t",
430343
"[".bold().white(),
431344
"OK".bold().green(),
432345
"]".bold().white(),
@@ -457,15 +370,11 @@ pub async fn run_tester(
457370
"[".bold().white(),
458371
title.bold().purple(),
459372
"]".bold().white(),
460-
"deviation:".bold().white(),
461-
"[".bold().white(),
462-
distance_between_responses.to_string().bold().purple(),
463-
"]".bold().white(),
464373
));
465374
}
466375
if response.status().is_server_error() {
467376
pb.println(format!(
468-
"{}{}{} {}{}{}\n{}{}{} {}\n\t {} {}{}{}\n\t {} {}{}{}\n\t {} {}{}{}\n\t {} {}{}{}\n\t {} {}{}{}\n\t {} {}{}{}\n\t",
377+
"{}{}{} {}{}{}\n{}{}{} {}\n\t {} {}{}{}\n\t {} {}{}{}\n\t {} {}{}{}\n\t {} {}{}{}\n\t {} {}{}{}\n\t",
469378
"[".bold().white(),
470379
"OK".bold().green(),
471380
"]".bold().white(),
@@ -496,15 +405,11 @@ pub async fn run_tester(
496405
"[".bold().white(),
497406
title.bold().purple(),
498407
"]".bold().white(),
499-
"deviation:".bold().white(),
500-
"[".bold().white(),
501-
distance_between_responses.to_string().bold().purple(),
502-
"]".bold().white(),
503408
));
504409
}
505410
if response.status().is_informational() {
506411
pb.println(format!(
507-
"{}{}{} {}{}{}\n{}{}{} {}\n\t {} {}{}{}\n\t {} {}{}{}\n\t {} {}{}{}\n\t {} {}{}{}\n\t {} {}{}{}\n\t {} {}{}{}\n\t",
412+
"{}{}{} {}{}{}\n{}{}{} {}\n\t {} {}{}{}\n\t {} {}{}{}\n\t {} {}{}{}\n\t {} {}{}{}\n\t {} {}{}{}\n\t",
508413
"[".bold().white(),
509414
"OK".bold().green(),
510415
"]".bold().white(),
@@ -535,10 +440,6 @@ pub async fn run_tester(
535440
"[".bold().white(),
536441
title.bold().purple(),
537442
"]".bold().white(),
538-
"deviation:".bold().white(),
539-
"[".bold().white(),
540-
distance_between_responses.to_string().bold().purple(),
541-
"]".bold().white(),
542443
));
543444
}
544445
// send the result message through the channel to the workers.

src/main.rs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ fn print_banner() {
3838
/ /_/ / /_/ / /_/ / / / /_/ / /_/ (__ ) /_/ __/ /
3939
/ .___/\__,_/\__/_/ /_/_.___/\__,_/____/\__/\___/_/
4040
/_/
41-
v0.4.9
41+
v0.5.0
4242
------
4343
path normalization pentesting tool
4444
"#;
@@ -80,7 +80,7 @@ async fn main() -> Result<(), Box<dyn Error + Send + Sync + 'static>> {
8080

8181
// parse the cli arguments
8282
let matches = App::new("pathbuster")
83-
.version("0.4.9")
83+
.version("0.5.0")
8484
.author("Blake Jacobs <[email protected]>")
8585
.about("path-normalization pentesting tool")
8686
.arg(
@@ -445,8 +445,10 @@ async fn main() -> Result<(), Box<dyn Error + Send + Sync + 'static>> {
445445
}
446446
};
447447
let out_pb = out_pb.clone();
448-
let bar_length = (pb_results.len() * wordlist.len() + w) as u64;
448+
let bar_length = (pb_results.len() * wordlist.len()) as u64;
449449
out_pb.set_length(bar_length);
450+
out_pb.set_position(0);
451+
let brute_pb = out_pb.clone();
450452
let brute_wordlist = brute_wordlist.clone();
451453
let (brute_job_tx, brute_job_rx) = spmc::channel::<BruteJob>();
452454
let (brute_result_tx, brute_result_rx) = mpsc::channel::<BruteResult>(w);
@@ -464,7 +466,7 @@ async fn main() -> Result<(), Box<dyn Error + Send + Sync + 'static>> {
464466
let http_proxy = http_proxy.clone();
465467
let brx = brute_job_rx.clone();
466468
let btx: mpsc::Sender<BruteResult> = brute_result_tx.clone();
467-
let bpb = job_pb.clone();
469+
let bpb = brute_pb.clone();
468470
workers.push(task::spawn(async move {
469471
bruteforcer::run_bruteforcer(bpb, brx, btx, timeout, http_proxy).await
470472
}));

src/utils/mod.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,12 @@ struct Threshold {
88
}
99
// make it global :)
1010
const CHANGE: Threshold = Threshold {
11-
threshold_start: 50.0,
12-
threshold_end: 50000.0,
11+
threshold_start: 500.0,
12+
threshold_end: 500000.0,
1313
};
1414
// uses the sift3 alogirthm to find the differences between to str inputs.
1515
pub fn get_response_change(a: &str, b: &str) -> (bool, f32) {
16-
let s = sift3(b, a);
16+
let s = sift3(a, b);
1717
if s > CHANGE.threshold_start && s < CHANGE.threshold_end {
1818
return (true, s);
1919
}

0 commit comments

Comments
 (0)