В кибербезопасности honeypot — это обманная система, созданная для привлечения и обнаружения потенциальных атакующих, пытающихся скомпрометировать систему. Так же, как горшок с медом, выставленный на открытом воздухе, привлекает мух.

Думайте о этих honeypots как о камерах безопасности для вашей системы. Так же как камера безопасности помогает нам понять, кто пытается проникнуть в здание и как они это делают, эти honeypots помогут вам понять, кто пытается атаковать вашу систему и какие методы они используют.

К концу этого учебного пособия вы сможете написать демонстрационный honeypot на Python и понять, как работают honeypots.

Содержание

Понимание типов хонипотов

Прежде чем начать проектировать наш собственный хонипот, давайте быстро разберемся в их различных типах:

  1. Производственные хонипоты: Эти типы хонипотов размещаются в реальной производственной среде и используются для обнаружения настоящих атак на безопасность. Они, как правило, просты по конструкции, легки в обслуживании и развертывании, и предлагают ограниченное взаимодействие для снижения рисков.

  2. Исследовательские хонипоты: Это более сложные системы, созданные исследователями безопасности для изучения паттернов атак, проведения эмпирического анализа этих паттернов, сбора образцов вредоносного ПО и понимания новых техник атак, которые ранее не были обнаружены. Они часто эмулируют целые операционные системы или сети, а не ведут себя как приложение в производственной среде.

В этом учебном пособии мы будем создавать ловушку со средним уровнем взаимодействия, которая будет записывать попытки подключения и базовое поведение атакующих.

Как настроить вашу среду разработки

Начнем с настройки вашей среды разработки на Python. Выполните следующие команды:

import socket
import sys
import datetime
import json
import threading
from pathlib import Path

# Настройка директории для логов
LOG_DIR = Path("honeypot_logs")
LOG_DIR.mkdir(exist_ok=True)

Мы будем использовать встроенные библиотеки, поэтому не потребуется устанавливать внешние зависимости. Мы будем хранить наши логи в директории honeypot_logs.

Как построить основную ловушку

Наша базовая ловушка будет состоять из трех компонентов:

  1. Сетевой слушатель, который принимает подключения

  2. Система логирования для записи активности

  3. Базовый эмуляционный сервис для взаимодействия с атакующими

Теперь давайте начнем с инициализации основного класса ловушки:

class Honeypot:
    def __init__(self, bind_ip="0.0.0.0", ports=None):
        self.bind_ip = bind_ip
        self.ports = ports or [21, 22, 80, 443]  # Порт по умолчанию для мониторинга
        self.active_connections = {}
        self.log_file = LOG_DIR / f"honeypot_{datetime.datetime.now().strftime('%Y%m%d')}.json"

    def log_activity(self, port, remote_ip, data):
        """Log suspicious activity with timestamp and details"""
        activity = {
            "timestamp": datetime.datetime.now().isoformat(),
            "remote_ip": remote_ip,
            "port": port,
            "data": data.decode('utf-8', errors='ignore')
        }

        with open(self.log_file, 'a') as f:
            json.dump(activity, f)
            f.write('\n')

    def handle_connection(self, client_socket, remote_ip, port):
        """Handle individual connections and emulate services"""
        service_banners = {
            21: "220 FTP server ready\r\n",
            22: "SSH-2.0-OpenSSH_8.2p1 Ubuntu-4ubuntu0.1\r\n",
            80: "HTTP/1.1 200 OK\r\nServer: Apache/2.4.41 (Ubuntu)\r\n\r\n",
            443: "HTTP/1.1 200 OK\r\nServer: Apache/2.4.41 (Ubuntu)\r\n\r\n"
        }

        try:
            # Отправить соответствующий баннер для сервиса
            if port in service_banners:
                client_socket.send(service_banners[port].encode())

            # Получить данные от атакующего
            while True:
                data = client_socket.recv(1024)
                if not data:
                    break

                self.log_activity(port, remote_ip, data)

                # Отправить ложный ответ
                client_socket.send(b"Command not recognized.\r\n")

        except Exception as e:
            print(f"Error handling connection: {e}")
        finally:
            client_socket.close()

В этом классе содержится много важной информации, поэтому давайте рассмотрим каждую функцию по очереди.

Функция __init__ записывает IP-адрес и номер порта, на которых мы будем размещать honeypot, а также путь / имя файла журнала. Мы также будем вести учет общего числа активных подключений к honeypot.

Функция log_activity будет получать информацию об IP, данных и порте, к которому IP пытался подключиться. Затем мы добавим эту информацию в наш журнал в формате JSON.

Функция handle_connection будет имитировать эти сервисы, которые будут работать на различных портах. У нас будет honeypot, работающий на портах 21, 22, 80 и 443. Эти сервисы предназначены для FTP, SSH, HTTP и HTTPS соответственно. Поэтому любой атакующий, пытающийся взаимодействовать с honeypot, должен ожидать эти сервисы на указанных портах.

Чтобы имитировать поведение этих сервисов, мы будем использовать баннеры сервисов, которые они используют на самом деле. Эта функция сначала отправит соответствующий баннер, когда атакующий подключится, а затем получит данные и запишет их. Honeypot также отправит ложный ответ “Команда не распознана” обратно атакующему.

Реализуйте сетевые слушатели

Теперь давайте реализуем сетевые слушатели, которые будут обрабатывать входящие соединения. Для этого мы будем использовать простое программирование сокетов. Если вы не знаете, как работает программирование сокетов, ознакомьтесь с этой статьей, которая объясняет некоторые связанные концепции.

def start_listener(self, port):
    """Start a listener on specified port"""
    try:
        server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        server.bind((self.bind_ip, port))
        server.listen(5)

        print(f"[*] Listening on {self.bind_ip}:{port}")

        while True:
            client, addr = server.accept()
            print(f"[*] Accepted connection from {addr[0]}:{addr[1]}")

            # Обработка соединения в отдельном потоке
            client_handler = threading.Thread(
                target=self.handle_connection,
                args=(client, addr[0], port)
            )
            client_handler.start()

    except Exception as e:
        print(f"Error starting listener on port {port}: {e}")

Функция start_listener запустит сервер и будет слушать на указанном порту. bind_ip для нас будет 0.0.0.0, что означает, что сервер будет слушать на всех сетевых интерфейсах.

Теперь мы будем обрабатывать каждое новое соединение в отдельном потоке, так как могут быть случаи, когда несколько атакующих пытаются взаимодействовать с хонипотом или атакующий скрипт или инструмент сканирует хонипот. Если вы не знаете, как работает потоковая обработка, вы можете ознакомиться с этой статьей, которая объясняет потоки и параллелизм в Python.

Кроме того, убедитесь, что вы поместили эту функцию в основной класс Honeypot.

Запустите хонипот

Теперь давайте создадим функцию main, которая запустит наш хонипот.

def main():
    honeypot = Honeypot()

    # Запустите слушатели для каждого порта в отдельных потоках
    for port in honeypot.ports:
        listener_thread = threading.Thread(
            target=honeypot.start_listener,
            args=(port,)
        )
        listener_thread.daemon = True
        listener_thread.start()

    try:
        # Держите главный поток активным
        while True:
            time.sleep(1)
    except KeyboardInterrupt:
        print("\n[*] Shutting down honeypot...")
        sys.exit(0)

if __name__ == "__main__":
    main()

Эта функция создает экземпляр класса Honeypot и запускает слушателей для каждого из наших определенных портов (21, 22, 80, 443) в отдельном потоке. Теперь мы будем поддерживать наш основной поток, который выполняет нашу фактическую программу, живым, помещая его в бесконечный цикл. Соберите это все в скрипт и выполните его.

Напишите Симулятор Атак на Ловушку

Теперь давайте попробуем смоделировать несколько сценариев атак и нацелиться на нашу ловушку, чтобы мы могли собрать данные в нашем JSON лог-файле.

Этот симулятор поможет нам продемонстрировать несколько важных аспектов о ловушках:

  1. Реалистичные паттерны атак: Симулятор будет имитировать общие паттерны атак, такие как сканирование портов, попытки грубой силы и эксплойты, специфичные для служб.

  2. Переменная интенсивность: Симулятор будет регулировать интенсивность симуляции, чтобы проверить, как ваша ловушка справляется с разными нагрузками.

  3. Несколько типов атак: Он продемонстрирует различные типы атак, которые могут попытаться совершить реальные злоумышленники, помогая вам понять, как ваша ловушка реагирует на каждую из них.

  4. Одновременные соединения: Симулятор будет использовать потоки для тестирования того, как ваш honeypot обрабатывает несколько одновременных соединений.

# honeypot_simulator.py

import socket
import time
import random
import threading
from concurrent.futures import ThreadPoolExecutor
import argparse

class HoneypotSimulator:
    """
    A class to simulate different types of connections and attacks against our honeypot.
    This helps in testing the honeypot's logging and response capabilities.
    """

    def __init__(self, target_ip="127.0.0.1", intensity="medium"):
        # Конфигурация для симулятора
        self.target_ip = target_ip
        self.intensity = intensity

        # Общие порты, которые часто проверяют злоумышленники
        self.target_ports = [21, 22, 23, 25, 80, 443, 3306, 5432]

        # Словарь общих команд, используемых злоумышленниками для различных сервисов
        self.attack_patterns = {
            21: [  # Команды FTP
                "USER admin\r\n",
                "PASS admin123\r\n",
                "LIST\r\n",
                "STOR malware.exe\r\n"
            ],
            22: [  # Попытки SSH
                "SSH-2.0-OpenSSH_7.9\r\n",
                "admin:password123\n",
                "root:toor\n"
            ],
            80: [  # HTTP-запросы
                "GET / HTTP/1.1\r\nHost: localhost\r\n\r\n",
                "POST /admin HTTP/1.1\r\nHost: localhost\r\nContent-Length: 0\r\n\r\n",
                "GET /wp-admin HTTP/1.1\r\nHost: localhost\r\n\r\n"
            ]
        }

        # Настройки интенсивности влияют на частоту и объем симулируемых атак
        self.intensity_settings = {
            "low": {"max_threads": 2, "delay_range": (1, 3)},
            "medium": {"max_threads": 5, "delay_range": (0.5, 1.5)},
            "high": {"max_threads": 10, "delay_range": (0.1, 0.5)}
        }

    def simulate_connection(self, port):
        """
        Simulates a connection attempt to a specific port with realistic attack patterns
        """
        try:
            # Создать новое соединение сокета
            sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            sock.settimeout(3)

            print(f"[*] Attempting connection to {self.target_ip}:{port}")
            sock.connect((self.target_ip, port))

            # Получить баннер, если он есть
            banner = sock.recv(1024)
            print(f"[+] Received banner from port {port}: {banner.decode('utf-8', 'ignore').strip()}")

            # Отправить шаблоны атак в зависимости от порта
            if port in self.attack_patterns:
                for command in self.attack_patterns[port]:
                    print(f"[*] Sending command to port {port}: {command.strip()}")
                    sock.send(command.encode())

                    # Ждать ответа
                    try:
                        response = sock.recv(1024)
                        print(f"[+] Received response: {response.decode('utf-8', 'ignore').strip()}")
                    except socket.timeout:
                        print(f"[-] No response received from port {port}")

                    # Добавить реалистичную задержку между командами
                    time.sleep(random.uniform(*self.intensity_settings[self.intensity]["delay_range"]))

            sock.close()

        except ConnectionRefusedError:
            print(f"[-] Connection refused on port {port}")
        except socket.timeout:
            print(f"[-] Connection timeout on port {port}")
        except Exception as e:
            print(f"[-] Error connecting to port {port}: {e}")

    def simulate_port_scan(self):
        """
        Simulates a basic port scan across common ports
        """
        print(f"\n[*] Starting port scan simulation against {self.target_ip}")
        for port in self.target_ports:
            self.simulate_connection(port)
            time.sleep(random.uniform(0.1, 0.3))

    def simulate_brute_force(self, port):
        """
        Simulates a brute force attack against a specific service
        """
        common_usernames = ["admin", "root", "user", "test"]
        common_passwords = ["password123", "admin123", "123456", "root"]

        print(f"\n[*] Starting brute force simulation against port {port}")

        for username in common_usernames:
            for password in common_passwords:
                try:
                    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
                    sock.settimeout(2)
                    sock.connect((self.target_ip, port))

                    if port == 21:  # FTP
                        sock.send(f"USER {username}\r\n".encode())
                        sock.recv(1024)
                        sock.send(f"PASS {password}\r\n".encode())
                    elif port == 22:  # SSH
                        sock.send(f"{username}:{password}\n".encode())

                    sock.close()
                    time.sleep(random.uniform(0.1, 0.3))

                except Exception as e:
                    print(f"[-] Error in brute force attempt: {e}")

    def run_continuous_simulation(self, duration=300):
        """
        Runs a continuous simulation for a specified duration
        """
        print(f"\n[*] Starting continuous simulation for {duration} seconds")
        print(f"[*] Intensity level: {self.intensity}")

        end_time = time.time() + duration

        with ThreadPoolExecutor(
            max_workers=self.intensity_settings[self.intensity]["max_threads"]
        ) as executor:
            while time.time() < end_time:
                # Смешанные шаблоны атак
                simulation_choices = [
                    lambda: self.simulate_port_scan(),
                    lambda: self.simulate_brute_force(21),
                    lambda: self.simulate_brute_force(22),
                    lambda: self.simulate_connection(80)
                ]

                # Случайным образом выбрать и выполнить шаблон атаки
                executor.submit(random.choice(simulation_choices))
                time.sleep(random.uniform(*self.intensity_settings[self.intensity]["delay_range"]))

def main():
    """
    Main function to run the honeypot simulator with command-line arguments
    """
    parser = argparse.ArgumentParser(description="Honeypot Attack Simulator")
    parser.add_argument("--target", default="127.0.0.1", help="Target IP address")
    parser.add_argument(
        "--intensity",
        choices=["low", "medium", "high"],
        default="medium",
        help="Simulation intensity level"
    )
    parser.add_argument(
        "--duration",
        type=int,
        default=300,
        help="Simulation duration in seconds"
    )

    args = parser.parse_args()

    simulator = HoneypotSimulator(args.target, args.intensity)

    try:
        simulator.run_continuous_simulation(args.duration)
    except KeyboardInterrupt:
        print("\n[*] Simulation interrupted by user")
    except Exception as e:
        print(f"[-] Simulation error: {e}")
    finally:
        print("\n[*] Simulation complete")

if __name__ == "__main__":
    main()

В этом скрипте симуляции много всего, поэтому давайте разберем его по частям. Я также добавил комментарии к каждой функции и операции, чтобы сделать код более читаемым.

Сначала у нас есть наш утилитарный класс под названием HoneypotSimulator. В этом классе у нас есть функция __init__, которая настраивает базовую конфигурацию для нашего симулятора. Она принимает два параметра: целевой IP-адрес (по умолчанию localhost) и уровень интенсивности (по умолчанию “средний”).

Мы также определяем три важных компонента: целевые порты для сканирования (распространенные сервисы, такие как FTP, SSH, HTTP), модели атак, специфичные для каждого сервиса (например, попытки входа и команды), и настройки интенсивности, которые контролируют, насколько агрессивной будет наша симуляция через количество потоков и временные задержки.

Функция simulate_connection обрабатывает индивидуальные попытки подключения к конкретному порту. Она создает сокет-соединение, пытается получить любые баннеры сервисов (например, информацию о версии SSH), а затем отправляет соответствующие команды атаки в зависимости от типа сервиса. Мы добавили обработку ошибок для распространенных сетевых проблем и также добавили реалистичные задержки между командами, чтобы имитировать человеческое взаимодействие.

Наша функция simulate_port_scan действует как инструмент разведки, который систематически проверяет каждый порт в нашем целевом списке. Это похоже на то, как работают инструменты, такие как nmap – проходя по портам один за другим, чтобы увидеть, какие сервисы доступны. Для каждого порта она вызывает функцию simulate_connection и добавляет небольшие случайные задержки, чтобы сделать паттерн сканирования более естественным.

Функция simulate_brute_force поддерживает списки общих имен пользователей и паролей, пытаясь разные комбинации против таких сервисов, как FTP и SSH. Для каждой попытки она создает новое соединение, отправляет учетные данные в правильном формате для этого сервиса, а затем закрывает соединение. Это помогает нам проверить, насколько хорошо ловушка для хакеров обнаруживает и фиксирует атаки с использованием краденых учетных данных.

Функция run_continuous_simulation работает в течение заданного времени, случайным образом выбирая разные типы атак, такие как сканирование портов, брутфорс или атаки на конкретные сервисы. Она использует ThreadPoolExecutor из Python для одновременного выполнения нескольких атак в зависимости от заданного уровня интенсивности.

Наконец, у нас есть функция main, которая предоставляет интерфейс командной строки для симулятора. Она использует argparse для обработки аргументов командной строки, позволяя пользователям указывать целевой IP, уровень интенсивности и продолжительность симуляции. Она создает экземпляр класса HoneypotSimulator и управляет общей реализацией, включая правильную обработку прерываний и ошибок со стороны пользователя.

После того как код симулятора помещен в отдельный скрипт, запустите его с помощью следующей команды:

# Запустите с настройками по умолчанию (средняя интенсивность, localhost, 5 минут)
python honeypot_simulator.py

# Запустите с пользовательскими настройками
python honeypot_simulator.py --target 192.168.1.100 --intensity high --duration 600

Поскольку мы запускаем honeypot, а также симулятор на одной машине локально, целевой адрес будет localhost. Но в реальной ситуации или если вы запускаете honeypot в виртуальной машине или на другой машине, это может быть что-то другое – поэтому убедитесь, что вы подтвердили IP-адрес перед запуском симулятора.

Как анализировать данные honeypot

Давайте быстро напишем вспомогательную функцию, которая позволит нам анализировать все данные, собранные honeypot. Поскольку мы сохранили это в файле журнала JSON, мы можем удобно разобрать его, используя встроенный пакет JSON.

import datetime
import json

def analyze_logs(log_file):
    """Enhanced honeypot log analysis with temporal and behavioral patterns"""
    ip_analysis = {}
    port_analysis = {}
    hourly_attacks = {}
    data_patterns = {}

    # Отслеживание паттернов сессий
    ip_sessions = {}
    attack_timeline = []

    with open(log_file, 'r') as f:
        for line in f:
            try:
                activity = json.loads(line)
                timestamp = datetime.datetime.fromisoformat(activity['timestamp'])
                ip = activity['remote_ip']
                port = activity['port']
                data = activity['data']

                # Инициализация отслеживания IP, если новый
                if ip not in ip_analysis:
                    ip_analysis[ip] = {
                        'total_attempts': 0,
                        'first_seen': timestamp,
                        'last_seen': timestamp,
                        'targeted_ports': set(),
                        'unique_payloads': set(),
                        'session_count': 0
                    }

                # Обновление статистики IP
                ip_analysis[ip]['total_attempts'] += 1
                ip_analysis[ip]['last_seen'] = timestamp
                ip_analysis[ip]['targeted_ports'].add(port)
                ip_analysis[ip]['unique_payloads'].add(data.strip())

                # Отслеживание часовых паттернов
                hour = timestamp.hour
                hourly_attacks[hour] = hourly_attacks.get(hour, 0) + 1

                # Анализ паттернов нацеливания по портам
                if port not in port_analysis:
                    port_analysis[port] = {
                        'total_attempts': 0,
                        'unique_ips': set(),
                        'unique_payloads': set()
                    }
                port_analysis[port]['total_attempts'] += 1
                port_analysis[port]['unique_ips'].add(ip)
                port_analysis[port]['unique_payloads'].add(data.strip())

                # Отслеживание паттернов нагрузки
                if data.strip():
                    data_patterns[data.strip()] = data_patterns.get(data.strip(), 0) + 1

                # Отслеживание временной линии атак
                attack_timeline.append({
                    'timestamp': timestamp,
                    'ip': ip,
                    'port': port
                })

            except (json.JSONDecodeError, KeyError) as e:
                continue

    # Генерация отчета анализа
    print("\n=== Honeypot Analysis Report ===")

    # 1. Анализ на основе IP
    print("\nTop 10 Most Active IPs:")
    sorted_ips = sorted(ip_analysis.items(), 
                       key=lambda x: x[1]['total_attempts'], 
                       reverse=True)[:10]
    for ip, stats in sorted_ips:
        duration = stats['last_seen'] - stats['first_seen']
        print(f"\nIP: {ip}")
        print(f"Total Attempts: {stats['total_attempts']}")
        print(f"Active Duration: {duration}")
        print(f"Unique Ports Targeted: {len(stats['targeted_ports'])}")
        print(f"Unique Payloads: {len(stats['unique_payloads'])}")

    # 2. Анализ портов
    print("\nPort Targeting Analysis:")
    sorted_ports = sorted(port_analysis.items(),
                         key=lambda x: x[1]['total_attempts'],
                         reverse=True)
    for port, stats in sorted_ports:
        print(f"\nPort {port}:")
        print(f"Total Attempts: {stats['total_attempts']}")
        print(f"Unique Attackers: {len(stats['unique_ips'])}")
        print(f"Unique Payloads: {len(stats['unique_payloads'])}")

    # 3. Темпоральный анализ
    print("\nHourly Attack Distribution:")
    for hour in sorted(hourly_attacks.keys()):
        print(f"Hour {hour:02d}: {hourly_attacks[hour]} attempts")

    # 4. Анализ сложности атак
    print("\nAttacker Sophistication Analysis:")
    for ip, stats in sorted_ips:
        sophistication_score = (
            len(stats['targeted_ports']) * 0.4 +  # Разнообразие портов
            len(stats['unique_payloads']) * 0.6   # Разнообразие нагрузки
        )
        print(f"IP {ip}: Sophistication Score {sophistication_score:.2f}")

    # 5. Общие паттерны нагрузки
    print("\nTop 10 Most Common Payloads:")
    sorted_payloads = sorted(data_patterns.items(),
                            key=lambda x: x[1],
                            reverse=True)[:10]
    for payload, count in sorted_payloads:
        if len(payload) > 50:  # Обрезка длинных нагрузок
            payload = payload[:50] + "..."
        print(f"Count {count}: {payload}")

Вы можете разместить это в отдельном скриптовом файле и вызвать функцию на JSON логах. Эта функция предоставит нам всесторонние данные из JSON файла на основе собранной информации.

Наш анализ начинается с группировки данных по нескольким категориям, таким как статистика на основе IP, модели целевых портов, распределение атак по часам и характеристики полезных нагрузок. Для каждого IP мы отслеживаем общее количество попыток, время первого и последнего появления, целевые порты и уникальные полезные нагрузки. Это поможет нам создать уникальные профили для атакующих.

Мы также исследуем модели атак на основе портов, которые отслеживают наиболее часто целевые порты и количество уникальных атакующих. Мы также проводим анализ сложности атак, который помогает нам идентифицировать целевых атакующих, учитывая такие факторы, как целевые порты и используемые уникальные полезные нагрузки. Этот анализ используется для разделения простых сканирующих действий и сложных атак.

Временной анализ помогает нам выявить шаблоны в попытках атак по часам, раскрывая модели в времени атак и потенциальные автоматизированные кампании нацеливания. Наконец, мы публикуем часто встречающиеся полезные нагрузки, чтобы идентифицировать часто встречающиеся строки атак или команды.

Соображения по безопасности

При развертывании этого honeypot убедитесь, что вы учитываете следующие меры безопасности:

  1. Запускайте ваш honeypot в изолированной среде. Обычно внутри виртуальной машины или на вашем локальном компьютере, который находится за NAT и файрволом.

  2. Запускайте honeypot с минимальными системными привилегиями (обычно не как root), чтобы уменьшить риск в случае компрометации.

  3. Будьте осторожны с собранными данными, если вы планируете когда-либо использовать их в качестве продукционного или исследовательского honeypot, так как они могут содержать вредоносное ПО или конфиденциальную информацию.

  4. Реализуйте надежные механизмы мониторинга для обнаружения попыток выхода из среды honeypot.

Заключение

С этим мы создали наш honeypot, написали симулятор для моделирования атак на наш honeypot и проанализировали данные из логов нашего honeypot, чтобы сделать несколько простых выводов. Это отличный способ понять как атакующие, так и защитные концепции безопасности. Вы можете рассмотреть возможность построения на этом для создания более сложных систем обнаружения и подумать о добавлении таких функций, как:

  1. Динамическое эмуляция сервисов на основе поведения атак

  2. Интеграция с системами разведки угроз, которые будут выполнять более качественный анализ выводов этих собранных логов honeypot

  3. Сбор даже более обширных логов помимо IP, порта и сетевых данных с помощью продвинутых механизмов логирования

  4. Добавьте возможности машинного обучения для обнаружения шаблонов атак

Помните, что хотя ловушки для злоумышленников являются мощными инструментами безопасности, они должны быть частью комплексной стратегии защитной безопасности, а не единственной линией обороны.

Надеюсь, вы узнали о том, как работают ловушки для злоумышленников, в чем их цель, а также немного о программировании на Python!