Skip to content

Commit 7afd935

Browse files
committed
fix false positives
1 parent eba4bd9 commit 7afd935

File tree

2 files changed

+79
-27
lines changed

2 files changed

+79
-27
lines changed

Cargo.toml

+6-5
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,11 @@ path = "src/main.rs"
1414

1515
[dependencies]
1616
clap = "2.33"
17-
reqwest = { version = "0.11", features = ["json", "gzip", "brotli", "default-tls", "rustls-tls"] }
18-
tokio = { version = "1", features = ["full" ] }
1917
futures = "0.3"
20-
rand = "0.8"
18+
indicatif = "0.16"
2119
num_cpus = "1.13"
22-
indicatif = "0.17"
23-
colored = "2.0"
20+
rand = "0.8"
21+
reqwest = { version = "0.11", features = ["json", "gzip", "brotli", "deflate", "stream", "native-tls", "rustls-tls"] }
22+
tokio = { version = "1", features = ["macros", "rt-multi-thread", "time"] }
23+
colored = "2.0"
24+
scraper = "0.14"

src/main.rs

+73-22
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ use std::time::Duration;
1414
use tokio::sync::Semaphore;
1515
use tokio::time::timeout;
1616
use colored::*;
17+
use scraper::{Html, Selector};
1718

1819
#[tokio::main]
1920
async fn main() {
@@ -75,6 +76,7 @@ async fn main() {
7576
let ip_range = matches.value_of("iprange");
7677
let ua_file = matches.value_of("useragents");
7778
let timeout_secs: u64 = matches.value_of("timeout").unwrap().parse().unwrap();
79+
let timeout_duration = Duration::from_secs(timeout_secs);
7880
let aggressive = matches.is_present("aggressive");
7981

8082
let available_threads = num_cpus::get();
@@ -84,9 +86,8 @@ async fn main() {
8486
.map(|s| s.parse::<usize>().unwrap_or(available_threads))
8587
.unwrap_or(available_threads);
8688

87-
8889
println!(
89-
"Use of : {} threads",
90+
"Utilisation de : {} threads",
9091
format!("{}", max_threads).blue()
9192
);
9293

@@ -101,21 +102,19 @@ async fn main() {
101102
}
102103
}
103104
} else {
104-
eprintln!("You must specify either an IP addresses file or a range of IP addresses.");
105+
eprintln!("Vous devez spécifier soit un fichier d'adresses IP, soit une plage d'adresses IP.");
105106
return;
106107
};
107108

108109
if ips.is_empty() {
109-
eprintln!("No IP address found.");
110+
eprintln!("Aucune adresse IP trouvée.");
110111
return;
111112
}
112113

113114
let pb = ProgressBar::new(ips.len() as u64);
114115
pb.set_style(
115116
ProgressStyle::default_bar()
116-
.template("{spinner:.green} [{elapsed_precise}] [{bar:40.cyan/blue}] {pos}/{len} ({eta})")
117-
.expect("Progress bar template error")
118-
.progress_chars("#>-"),
117+
.template("{spinner:.green} [{elapsed_precise}] [{bar:40.cyan/blue}] {pos}/{len} ({eta})"),
119118
);
120119

121120
let user_agents = if let Some(ua_path) = ua_file {
@@ -129,6 +128,15 @@ async fn main() {
129128
vec!["Mozilla/5.0 (compatible; CloudFade/1.0; +https://example.com)".to_string()]
130129
};
131130

131+
// Extraction du motif unique du domaine cible
132+
let target_pattern = match get_target_pattern(domain, timeout_duration).await {
133+
Some(pattern) => pattern,
134+
None => {
135+
eprintln!("Impossible d'extraire un motif unique du domaine cible.");
136+
return;
137+
}
138+
};
139+
132140
let semaphore = Arc::new(Semaphore::new(max_threads));
133141

134142
let mut tasks = FuturesUnordered::new();
@@ -138,15 +146,23 @@ async fn main() {
138146
let domain = domain.to_string();
139147
let user_agents = user_agents.clone();
140148
let aggressive = aggressive;
141-
let timeout_duration = Duration::from_secs(timeout_secs);
149+
let timeout_duration = timeout_duration;
142150
let semaphore = semaphore.clone();
143151
let pb = pb.clone();
152+
let target_pattern = target_pattern.clone();
144153

145154
let permit = semaphore.acquire_owned().await.unwrap();
146155

147156
tasks.push(tokio::spawn(async move {
148-
let result =
149-
test_ip(ip, domain, user_agents, aggressive, timeout_duration).await;
157+
let result = test_ip(
158+
ip,
159+
domain,
160+
user_agents,
161+
aggressive,
162+
timeout_duration,
163+
target_pattern,
164+
)
165+
.await;
150166
drop(permit);
151167
pb.inc(1);
152168
result
@@ -161,15 +177,15 @@ async fn main() {
161177
}
162178
}
163179

164-
pb.finish_with_message("Scan completed");
180+
pb.finish_with_message("Scan terminé");
165181

166182
if possible_ips.is_empty() {
167183
println!(
168184
"{}",
169-
format!("No IPs found linked to {}", domain).red()
185+
format!("Aucune IP trouvée liée à {}", domain).red()
170186
);
171187
} else {
172-
println!("{}", "Potential IP addresses found :".green());
188+
println!("{}", "Adresses IP potentielles trouvées :".green());
173189
for ip in possible_ips {
174190
println!("{}", ip.green());
175191
}
@@ -182,11 +198,12 @@ async fn test_ip(
182198
user_agents: Vec<String>,
183199
aggressive: bool,
184200
timeout_duration: Duration,
201+
target_pattern: String,
185202
) -> Option<String> {
186203
let socket_addr: SocketAddr = match format!("{}:80", ip).parse() {
187204
Ok(addr) => addr,
188205
Err(_) => {
189-
eprintln!("Invalid IP address : {}", ip);
206+
eprintln!("Adresse IP invalide : {}", ip);
190207
return None;
191208
}
192209
};
@@ -219,46 +236,80 @@ async fn test_ip(
219236
if let Ok(Ok(resp)) = response {
220237
let status = resp.status().as_u16();
221238
if status == 200 || status == 301 || status == 302 {
222-
return Some(ip);
239+
if let Ok(text) = resp.text().await {
240+
if text.contains(&target_pattern) {
241+
return Some(ip);
242+
}
243+
}
223244
}
224245
}
225246
}
226247
}
227248
None
228249
}
229250

251+
async fn get_target_pattern(domain: &str, timeout_duration: Duration) -> Option<String> {
252+
let client = reqwest::Client::builder()
253+
.danger_accept_invalid_certs(true)
254+
.build()
255+
.unwrap();
256+
257+
let url = format!("http://{}/", domain);
258+
let request = client.get(&url);
259+
260+
let response = timeout(timeout_duration, request.send()).await;
261+
if let Ok(Ok(resp)) = response {
262+
if let Ok(text) = resp.text().await {
263+
if let Some(title) = extract_title(&text) {
264+
return Some(title);
265+
}
266+
}
267+
}
268+
None
269+
}
270+
271+
fn extract_title(html: &str) -> Option<String> {
272+
let document = Html::parse_document(html);
273+
let selector = Selector::parse("title").unwrap();
274+
275+
document.select(&selector).next().map(|element| element.inner_html())
276+
}
277+
230278
fn read_lines(filename: &str) -> Vec<String> {
231-
let file = File::open(filename).expect("Unable to open file");
279+
let file = File::open(filename).expect("Impossible d'ouvrir le fichier");
232280
let reader = BufReader::new(file);
233281
reader.lines().filter_map(Result::ok).collect()
234282
}
235283

236284
fn parse_ip_range(ip_range: &str) -> Result<Vec<String>, String> {
237285
let parts: Vec<&str> = ip_range.split('-').collect();
238286
if parts.len() != 2 {
239-
return Err("IP range format is invalid. Use 'start-end' format.".to_string());
287+
return Err("Le format de la plage IP est invalide. Utilisez le format 'début-fin'.".to_string());
240288
}
241289

242-
let start_ip = Ipv4Addr::from_str(parts[0]).map_err(|_| "Start IP address invalid.".to_string())?;
243-
let end_ip = Ipv4Addr::from_str(parts[1]).map_err(|_| "End IP address invalid.".to_string())?;
290+
let start_ip = Ipv4Addr::from_str(parts[0]).map_err(|_| "Adresse IP de début invalide.".to_string())?;
291+
let end_ip = Ipv4Addr::from_str(parts[1]).map_err(|_| "Adresse IP de fin invalide.".to_string())?;
244292

245293
let start: u32 = start_ip.into();
246294
let end: u32 = end_ip.into();
247295

248296
if start > end {
249-
return Err("The starting IP address is greater than the ending IP address.".to_string());
297+
return Err("L'adresse IP de début est supérieure à l'adresse IP de fin.".to_string());
250298
}
251299

252300
let max_ips = 1_000_000;
253301
let total_ips = end - start + 1;
254302

255303
if total_ips > max_ips {
256-
return Err(format!("The IP range is too large ({} addresses). Please specify a smaller range.", total_ips));
304+
return Err(format!(
305+
"La plage d'IP est trop grande ({} adresses). Veuillez spécifier une plage plus petite.",
306+
total_ips
307+
));
257308
}
258309

259310
let ips: Vec<String> = (start..=end)
260311
.map(|ip_num| Ipv4Addr::from(ip_num).to_string())
261312
.collect();
262313

263314
Ok(ips)
264-
}
315+
}

0 commit comments

Comments
 (0)