En cybersécurité, un pot de miel est un système leurre conçu pour attirer et détecter les éventuels attaquants tentant de compromettre le système. Tout comme un pot de miel laissé à découvert attirerait les mouches.
Pensez à ces pots de miel comme des caméras de sécurité pour votre système. Tout comme une caméra de sécurité nous aide à comprendre qui tente de s’introduire dans un bâtiment et comment, ces pots de miel vous aideront à comprendre qui tente d’attaquer votre système et quelles techniques ils utilisent.
À la fin de ce tutoriel, vous serez capable d’écrire un exemple de pot de miel en Python et comprendre comment les pots de miel fonctionnent.
Table des matières
Comprendre les types de honeypots
Avant de commencer à concevoir notre propre honeypot, comprenons rapidement leurs différents types :
-
Honeypots de production : Ces types de honeypots sont placés dans un environnement de production réel et sont utilisés pour détecter de véritables attaques de sécurité. Ils sont généralement simples dans leur conception, faciles à maintenir et à déployer, et offrent une interaction limitée pour réduire les risques.
-
Honeypots de recherche : Ce sont des systèmes plus complexes mis en place par des chercheurs en sécurité pour étudier les modèles d’attaque, effectuer une analyse empirique de ces modèles, collecter des échantillons de logiciels malveillants et comprendre de nouvelles techniques d’attaque qui n’ont pas été découvertes auparavant. Ils imitent souvent des systèmes d’exploitation ou des réseaux entiers plutôt que de se comporter comme une application dans l’environnement de production.
Pour ce tutoriel, nous allons construire un honeypot à interaction moyenne qui enregistre les tentatives de connexion et le comportement de base des attaquants.
Comment configurer votre environnement de développement
Commençons par configurer votre environnement de développement en Python. Exécutez les commandes suivantes :
import socket
import sys
import datetime
import json
import threading
from pathlib import Path
# Configurer le répertoire de journalisation
LOG_DIR = Path("honeypot_logs")
LOG_DIR.mkdir(exist_ok=True)
Nous allons nous en tenir aux bibliothèques intégrées, donc nous n’aurons pas besoin d’installer de dépendances externes. Nous allons stocker nos journaux dans le répertoire honeypot_logs
.
Comment construire le honeypot de base
Notre honeypot de base sera composé de trois composants :
-
Un écouteur réseau qui accepte les connexions
-
Un système de journalisation pour enregistrer les activités
-
Un service d’émulation de base pour interagir avec les attaquants
Maintenant, commençons par initialiser la classe de base du honeypot :
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] # Ports par défaut à surveiller
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:
# Envoyer la bannière appropriée pour le service
if port in service_banners:
client_socket.send(service_banners[port].encode())
# Recevoir des données de l'attaquant
while True:
data = client_socket.recv(1024)
if not data:
break
self.log_activity(port, remote_ip, data)
# Envoyer une réponse fausse
client_socket.send(b"Command not recognized.\r\n")
except Exception as e:
print(f"Error handling connection: {e}")
finally:
client_socket.close()
Cette classe contient beaucoup d’informations importantes, alors passons en revue chaque fonction une par une.
La fonction __init__
enregistre les adresses IP et les numéros de port sur lesquels nous hébergerons le honeypot, ainsi que le chemin / nom de fichier du fichier journal. Nous tiendrons également un enregistrement du nombre total de connexions actives que nous avons avec le honeypot.
La fonction log_activity
va recevoir des informations sur l’IP, les données et le port auquel l’IP a tenté de se connecter. Ensuite, nous ajouterons ces informations à notre fichier journal au format JSON.
La fonction handle_connection
va imiter ces services qui fonctionneront sur les différents ports que nous avons. Nous aurons le honeypot fonctionnant sur les ports 21, 22, 80 et 443. Ces services correspondent respectivement à FTP, SSH, HTTP et au protocole HTTPS. Donc, tout attaquant tentant d’interagir avec le honeypot devrait s’attendre à ces services sur ces ports.
Pour imiter le comportement de ces services, nous utiliserons les bannières de service qu’ils utilisent dans la réalité. Cette fonction enverra d’abord la bannière appropriée lorsque l’attaquant se connecte, puis recevra les données et les enregistrera. Le honeypot enverra également une réponse fausse “Commande non reconnue” à l’attaquant.
Implémenter les écouteurs réseau
Maintenant, mettons en œuvre les écouteurs réseau qui traiteront les connexions entrantes. Pour cela, nous allons utiliser une programmation de socket simple. Si vous n’êtes pas au courant de la façon dont fonctionne la programmation par socket, consultez cet article qui explique certains concepts liés à cela.
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]}")
# Gérer la connexion dans un thread séparé
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}")
La fonction start_listener
va démarrer le serveur et écouter sur le port fourni. L’bind_ip
pour nous sera 0.0.0.0
, ce qui indique que le serveur écoutera sur toutes les interfaces réseau.
Maintenant, nous allons gérer chaque nouvelle connexion dans un thread séparé, car il pourrait y avoir des cas où plusieurs attaquants tentent d’interagir avec le honeypot ou un script ou outil d’attaque scanne le honeypot. Si vous n’êtes pas au courant de la façon dont le threading fonctionne, vous pouvez consulter cet article qui explique le threading et la concurrence en Python.
De plus, assurez-vous de mettre cette fonction dans la classe principale Honeypot
.
Exécutez le Honeypot
Maintenant, créons la fonction main
qui démarrera notre honeypot.
def main():
honeypot = Honeypot()
# Démarrer les écouteurs pour chaque port dans des threads séparés
for port in honeypot.ports:
listener_thread = threading.Thread(
target=honeypot.start_listener,
args=(port,)
)
listener_thread.daemon = True
listener_thread.start()
try:
# Garder le thread principal en vie
while True:
time.sleep(1)
except KeyboardInterrupt:
print("\n[*] Shutting down honeypot...")
sys.exit(0)
if __name__ == "__main__":
main()
Cette fonction instancie la classe Honeypot
et démarre les écouteurs pour chacun de nos ports définis (21, 22, 80, 443) sous forme de fils séparés. Maintenant, nous allons garder notre fil principal qui exécute notre programme en vie en le mettant dans une boucle infinie. Mettez tout cela ensemble dans un script et exécutez-le.
Écrire le Simulateur d’Attaque Honeypot
Maintenant, essayons de simuler quelques scénarios d’attaque et de cibler notre honeypot afin que nous puissions collecter des données dans notre fichier journal JSON.
Ce simulateur nous aidera à démontrer quelques aspects importants des honeypots :
-
Modèles d’attaque réalistes : Le simulateur simulera des modèles d’attaque courants tels que le scan de ports, les tentatives de force brute et les exploits spécifiques aux services.
-
Intensité variable : Le simulateur ajustera l’intensité de la simulation pour tester comment votre honeypot gère différentes charges.
-
Plusieurs types d’attaques : Il démontrera différents types d’attaques que de véritables attaquants pourraient tenter, vous aidant à comprendre comment votre honeypot réagit à chacune d’entre elles.
-
Connexions simultanées : Le simulateur utilisera le multithreading pour tester la façon dont votre honeypot gère plusieurs connexions simultanées.
# 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"):
# Configuration du simulateur
self.target_ip = target_ip
self.intensity = intensity
# Ports communs que les attaquants explorent souvent
self.target_ports = [21, 22, 23, 25, 80, 443, 3306, 5432]
# Dictionnaire des commandes courantes utilisées par les attaquants pour différents services
self.attack_patterns = {
21: [ # Commandes FTP
"USER admin\r\n",
"PASS admin123\r\n",
"LIST\r\n",
"STOR malware.exe\r\n"
],
22: [ # Tentatives SSH
"SSH-2.0-OpenSSH_7.9\r\n",
"admin:password123\n",
"root:toor\n"
],
80: [ # Requêtes 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"
]
}
# Les paramètres d'intensité affectent la fréquence et le volume des attaques simulées
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:
# Créer une nouvelle connexion socket
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))
# Obtenir la bannière si disponible
banner = sock.recv(1024)
print(f"[+] Received banner from port {port}: {banner.decode('utf-8', 'ignore').strip()}")
# Envoyer des modèles d'attaque en fonction du port
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())
# Attendre la réponse
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}")
# Ajouter un délai réaliste entre les commandes
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:
# Mélange de différents modèles d'attaque
simulation_choices = [
lambda: self.simulate_port_scan(),
lambda: self.simulate_brute_force(21),
lambda: self.simulate_brute_force(22),
lambda: self.simulate_connection(80)
]
# Choisir et exécuter aléatoirement un modèle d'attaque
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()
Nous avons beaucoup de choses dans ce script de simulation, alors décomposons-le une par une. J’ai également ajouté des commentaires pour chaque fonction et opération afin de rendre le code un peu plus lisible.
Nous avons d’abord notre classe utilitaire appelée HoneypotSimulator
. Dans cette classe, nous avons la fonction __init__
qui configure les paramètres de base pour notre simulateur. Elle prend deux paramètres : une adresse IP cible (par défaut localhost) et un niveau d’intensité (par défaut « moyen »).
Nous définissons également trois composants importants : les ports cibles à sonder (services courants comme FTP, SSH, HTTP), les modèles d’attaque spécifiques à chaque service (comme les tentatives de connexion et les commandes), et les paramètres d’intensité qui contrôlent l’agressivité de notre simulation à travers les comptes de threads et les délais de timing.
La fonction simulate_connection
gère les tentatives de connexion individuelles à un port spécifique. Elle crée une connexion socket, essaie d’obtenir des bannières de service (comme les informations de version SSH), puis envoie des commandes d’attaque appropriées en fonction du type de service. Nous avons ajouté un traitement des erreurs pour les problèmes de réseau courants et également ajouté des délais réalistes entre les commandes pour imiter l’interaction humaine.
Notre fonction simulate_port_scan
agit comme un outil de reconnaissance, qui vérifiera systématiquement chaque port de notre liste cible. C’est similaire à la façon dont fonctionnent des outils comme nmap
– en parcourant les ports un par un pour voir quels services sont disponibles. Pour chaque port, elle appelle la fonction simulate_connection
et ajoute de petits délais aléatoires pour rendre le modèle de scan plus naturel.
La fonction simulate_brute_force
maintient des listes de noms d’utilisateur et de mots de passe courants, essayant différentes combinaisons contre des services comme FTP et SSH. Pour chaque tentative, elle crée une nouvelle connexion, envoie les identifiants de connexion dans le format correct pour ce service, puis ferme la connexion. Cela nous aide à tester l’efficacité du honeypot pour détecter et enregistrer les attaques de credential stuffing.
La fonction run_continuous_simulation
s’exécute pendant une durée spécifiée, choisissant aléatoirement entre différents types d’attaques comme le scan de ports, la force brute ou des attaques spécifiques à un service. Elle utilise ThreadPoolExecutor
de Python pour exécuter plusieurs attaques simultanément en fonction du niveau d’intensité spécifié.
Enfin, nous avons la fonction main
qui fournit l’interface en ligne de commande pour le simulateur. Elle utilise argparse
pour gérer les arguments de la ligne de commande, permettant aux utilisateurs de spécifier l’IP cible, le niveau d’intensité et la durée de la simulation. Elle crée une instance de la classe HoneypotSimulator
et gère l’exécution globale, y compris la gestion appropriée des interruptions et des erreurs utilisateur.
Après avoir mis le code du simulateur dans un script séparé, exécutez-le avec la commande suivante :
# Exécuter avec les paramètres par défaut (intensité moyenne, localhost, 5 minutes)
python honeypot_simulator.py
# Exécuter avec des paramètres personnalisés
python honeypot_simulator.py --target 192.168.1.100 --intensity high --duration 600
Puisque nous exécutons le honeypot ainsi que le simulateur sur la même machine localement, la cible sera localhost
. Mais cela peut être autre chose dans un scénario réel ou si vous exécutez le honeypot dans une VM ou sur une machine différente – assurez-vous donc de confirmer l’adresse IP avant d’exécuter le simulateur.
Comment Analyser les Données du Honeypot
Écrivons rapidement une fonction d’aide qui nous permettra d’analyser toutes les données collectées par le honeypot. Puisque nous avons stocké cela dans un fichier journal JSON, nous pouvons facilement le parser en utilisant le package JSON intégré.
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 = {}
# Suivre les modèles de session
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']
# Initialiser le suivi IP si nouveau
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
}
# Mettre à jour les statistiques 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())
# Suivre les modèles horaires
hour = timestamp.hour
hourly_attacks[hour] = hourly_attacks.get(hour, 0) + 1
# Analyser les modèles de ciblage des ports
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())
# Suivre les modèles de charge utile
if data.strip():
data_patterns[data.strip()] = data_patterns.get(data.strip(), 0) + 1
# Suivre la chronologie des attaques
attack_timeline.append({
'timestamp': timestamp,
'ip': ip,
'port': port
})
except (json.JSONDecodeError, KeyError) as e:
continue
# Génération de rapport d'analyse
print("\n=== Honeypot Analysis Report ===")
# 1. Analyse basée sur l'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. Analyse des ports
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. Analyse temporelle
print("\nHourly Attack Distribution:")
for hour in sorted(hourly_attacks.keys()):
print(f"Hour {hour:02d}: {hourly_attacks[hour]} attempts")
# 4. Analyse de la sophistication des attaques
print("\nAttacker Sophistication Analysis:")
for ip, stats in sorted_ips:
sophistication_score = (
len(stats['targeted_ports']) * 0.4 + # Diversité des ports
len(stats['unique_payloads']) * 0.6 # Diversité des charges utiles
)
print(f"IP {ip}: Sophistication Score {sophistication_score:.2f}")
# 5. Modèles de charge utile courants
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: # Tronquer les charges utiles longues
payload = payload[:50] + "..."
print(f"Count {count}: {payload}")
Vous pouvez placer cela dans un fichier de script séparé et appeler la fonction sur les journaux JSON. Cette fonction nous fournira des informations complètes à partir du fichier JSON basé sur les données collectées.
Notre analyse commence par le regroupement des données en plusieurs catégories telles que les statistiques basées sur l’IP, les modèles de ciblage des ports, les distributions horaires des attaques et les caractéristiques des charges utiles. Pour chaque IP, nous suivons le nombre total de tentatives, les heures de première et de dernière apparition, les ports ciblés et les charges utiles uniques. Cela nous aidera à établir des profils uniques pour les attaquants.
Nous examinons également ici les modèles d’attaques basés sur les ports qui surveillent les ports les plus souvent ciblés et le nombre d’attaquants uniques. Nous effectuons également une analyse de la sophistication des attaques qui nous aide à identifier les attaquants ciblés, en tenant compte de facteurs tels que les ports ciblés et les charges utiles uniques utilisées. Cette analyse est utilisée pour séparer les activités de balayage simples et les attaques sophistiquées.
L’analyse temporelle nous aide à identifier les modèles dans les tentatives d’attaque horaires révélant des schémas dans le timing des attaques et les campagnes de ciblage automatique potentielles. Enfin, nous publions les charges utiles couramment observées pour identifier les chaînes ou commandes d’attaque fréquemment vues.
Considérations de sécurité
Lors du déploiement de ce honeypot, assurez-vous de prendre en compte les mesures de sécurité suivantes :
-
Exécutez votre honeypot dans un environnement isolé. Typiquement à l’intérieur d’une VM, ou sur votre machine locale qui est derrière un NAT et un pare-feu.
-
Exécutez le honeypot avec des privilèges système minimaux (typiquement pas en tant que root) pour réduire le risque en cas de compromission.
-
Faites attention aux données collectées si vous prévoyez de les déployer un jour comme un honeypot de production ou de recherche, car elles peuvent contenir des logiciels malveillants ou des informations sensibles.
-
Implémentez des mécanismes de surveillance robustes pour détecter les tentatives de sortie de l’environnement honeypot.
Conclusion
Avec cela, nous avons construit notre honeypot, écrit un simulateur pour simuler des attaques sur notre honeypot et analysé les données de nos journaux de honeypot pour tirer quelques inférences simples. C’est un excellent moyen de comprendre à la fois les concepts de sécurité offensive et défensive. Vous pouvez envisager de construire sur cela pour créer des systèmes de détection plus complexes et penser à ajouter des fonctionnalités comme :
-
Émulation de service dynamique basée sur le comportement d’attaque
-
Intégration avec des systèmes de renseignement sur les menaces qui effectueront une meilleure analyse d’inférence de ces journaux de honeypot collectés
-
Rassemblez des journaux encore plus complets au-delà des données IP, port et réseau grâce à des mécanismes de journalisation avancés
-
Ajoutez des capacités d’apprentissage automatique pour détecter les schémas d’attaque
Rappelez-vous que même si les leurres sont des outils de sécurité puissants, ils doivent faire partie d’une stratégie de sécurité défensive complète, et ne pas être la seule ligne de défense.
J’espère que vous avez appris comment fonctionnent les leurres, quel est leur objectif ainsi qu’un peu de programmation Python aussi !
Source:
https://www.freecodecamp.org/news/build-a-honeypot-with-python/