diff --git a/user_scanner/__main__.py b/user_scanner/__main__.py index 60b6f260e..3c3b6b00d 100644 --- a/user_scanner/__main__.py +++ b/user_scanner/__main__.py @@ -10,6 +10,7 @@ from dataclasses import replace from user_scanner.cli.banner import print_banner +from user_scanner.cli.tips import print_loud_skip_tip, print_proxy_tip from user_scanner.core import formatter from user_scanner.core.cross_scan import ( DEFAULT_DEPTH, @@ -794,10 +795,9 @@ def main(): print(f"\n{R}[✘] No results found for the given target(s).{X}") else: print(f"\n{C}[i] Scan complete.\n Total hits:{X} {total_found}") - if total_skipped > 0: - print(f" {C}Skipped:{X} {total_skipped}") - print(f" {Y}Reason for skip: Module(s) notify{X} (but only if target exists there) {Y}the target with password reset email(s){X}") - print(f" {Y}Use {G}--allow-loud{X}{Y} to include those module(s) to be scanned{X}") + print_loud_skip_tip(total_skipped) + + print_proxy_tip(results, has_proxy=bool(args.proxy_file)) if __name__ == "__main__": main() diff --git a/user_scanner/cli/tips.py b/user_scanner/cli/tips.py new file mode 100644 index 000000000..9e26bcf11 --- /dev/null +++ b/user_scanner/cli/tips.py @@ -0,0 +1,83 @@ +"""CLI tips, intelligence service recommendations, and operational hints.""" + +from typing import Sequence + +from colorama import Fore, Style + +from user_scanner.core.result import Result, Status + +_BLOCKED_KEYWORDS = ( + "403", + "429", + "waf", + "cloudflare", + "timed out", + "timeout", + "curl: (28)", + "connection closed", + "rate limit", +) + +PROXY_SPONSOR_URL = "https://proxy-seller.com/?partner=A711D0DB08424F5A" +PROXY_PROMO_CODE = "KAIF15" + + +def print_proxy_tip(results: Sequence[Result], has_proxy: bool = False) -> None: + """Surface regional / WAF blocks and recommend proxy routing if not already configured.""" + if has_proxy: + return + + blocked_count = sum( + 1 + for r in results + if r.status == Status.ERROR + and any(kw in str(r.reason or "").lower() for kw in _BLOCKED_KEYWORDS) + ) + + if blocked_count > 0: + Y = Fore.YELLOW + G = Fore.GREEN + C = Fore.CYAN + B = Style.BRIGHT + RESET = Style.RESET_ALL + + print( + f"\n{Y}{B}[!] {blocked_count} site(s) were unreachable{RESET} due to regional blocks or rate limits {Y}(403/timeout){RESET}." + f"\n {C}{B}Tip:{RESET} Route scans with {G}{B}-P/--proxy-file{RESET} to get verdicts from blocked sites." + f"\n {B}Tested provider:{RESET} {C}{PROXY_SPONSOR_URL}{RESET} (use code {G}{B}{PROXY_PROMO_CODE}{RESET} for {G}{B}15% off{RESET})" + ) + + +def print_hudson_remediation_tip() -> None: + """Print security guidance when infostealer compromises are detected.""" + Y = Fore.YELLOW + B = Style.BRIGHT + C = Fore.CYAN + RESET = Style.RESET_ALL + + print( + f"\n{Y}{B}[!] Security Notice:{RESET} All credentials saved on infected computers are at risk." + ) + print( + f" {C}{B}Remediation tools:{RESET} Visit {C}https://www.hudsonrock.com/free-tools{RESET} for identity monitoring." + ) + + +def print_loud_skip_tip(skipped_count: int) -> None: + """Explain why loud modules were skipped and how to enable them.""" + if skipped_count <= 0: + return + + C = Fore.CYAN + Y = Fore.YELLOW + G = Fore.GREEN + B = Style.BRIGHT + RESET = Style.RESET_ALL + + print(f" {C}Skipped:{RESET} {skipped_count}") + print( + f" {Y}Reason for skip: Module(s) may notify the target with password reset emails.{RESET}" + ) + print( + f" {Y}Use {G}{B}--allow-loud{RESET}{Y} to include those module(s) in the scan.{RESET}" + ) diff --git a/user_scanner/core/hudson.py b/user_scanner/core/hudson.py index 66609992d..a2f1363dc 100644 --- a/user_scanner/core/hudson.py +++ b/user_scanner/core/hudson.py @@ -1,6 +1,7 @@ import httpx import json from colorama import Fore, Style +from user_scanner.cli.tips import print_hudson_remediation_tip from user_scanner.core.helpers import load_config, _get_config_path # Color configs @@ -93,8 +94,7 @@ def run_hudson_scan(target: str, is_email: bool = False): if top_logins: print(f" - Sample Logins Found: {', '.join(top_logins[:3])}...") - print(f"\n{Y}[!] Recommendation: All credentials saved on infected computers are at risk.{X}") - print(f"{Y}[!] Visit https://www.hudsonrock.com/free-tools for more info.{X}") + print_hudson_remediation_tip() elif response.status_code == 404: print(f"{G}[✔] No data found for this {param} in Hudson Rock database.{X}")