Introduction
En tant qu'administrateur système ou analyste en sécurité, vous serez souvent confronté à des fichiers journaux massifs générés par des serveurs web comme Apache ou Nginx. Lire manuellement des milliers de lignes de journaux pour identifier une activité malveillante est une tâche insoutenable et sujette à l'erreur humaine.
Dans ce laboratoire, vous vous mettrez dans la peau d'un intervenant en sécurité. Vous allez écrire un script Python conçu pour ingérer les journaux d'accès d'un serveur web Apache. En utilisant la bibliothèque d'expressions régulières (re) de Python, vous extrairez automatiquement les adresses IP et détecterez les signatures d'attaques par injection SQL (SQLi) connues. Enfin, vous exporterez ces résultats dans un rapport CSV structuré pour une analyse approfondie.
Ce module marque le moment où Python devient un multiplicateur de force pour l'analyste, plutôt qu'un simple langage de programmation. Les journaux sont l'un des exemples les plus frappants de tâches trop répétitives pour une revue manuelle minutieuse, mais suffisamment structurées pour que l'automatisation apporte une aide immédiate.
Lire des fichiers journaux en Python
Dans cette étape, vous apprendrez à utiliser Python pour ouvrir et lire un fichier journal. L'environnement a déjà été préparé avec un exemple de fichier journal Apache nommé access.log dans votre répertoire de travail.
La lecture de fichiers ligne par ligne est un modèle d'automatisation fondamental. Il est plus évolutif que la copie manuelle de données et vous prépare à ajouter une logique de filtrage, d'analyse, de comptage et de rapport sans modifier l'approche d'ingestion de base.
Tout d'abord, examinons le contenu du fichier journal exemple pour comprendre sur quoi nous travaillons. Utilisez la commande cat dans votre terminal pour afficher le contenu du fichier.
cat access.log
Vous devriez voir plusieurs lignes de journaux d'accès Apache standard. Certaines de ces lignes contiennent des requêtes web normales, tandis que d'autres contiennent des tentatives suspectes d'injection SQL.
Maintenant, créons un script Python pour lire ce fichier par programmation. Nous utiliserons l'éditeur de texte nano pour créer un fichier nommé log_analyzer.py.
nano log_analyzer.py
En Python, la fonction open() est utilisée pour ouvrir un fichier, et l'instruction with garantit que le fichier est correctement fermé une fois la lecture terminée. Copiez et collez le code Python suivant dans votre éditeur nano :
def analyze_logs(file_path):
print(f"Opening log file: {file_path}")
## Open the file in read mode ('r')
with open(file_path, 'r') as file:
## Read the file line by line
for line in file:
## Print each line, stripping the extra newline character
print(line.strip())
if __name__ == "__main__":
log_file = "access.log"
analyze_logs(log_file)
Enregistrez le fichier dans nano en appuyant sur Ctrl+O, puis Enter pour confirmer le nom du fichier. Si vous souhaitez continuer à développer le script avant de le tester, vous pouvez rester dans nano et passer à l'étape suivante. Utilisez Ctrl+X uniquement lorsque vous êtes prêt à revenir au terminal.
Exécutez votre script Python nouvellement créé en utilisant la commande python3 :
python3 log_analyzer.py
Vous verrez le script afficher exactement les mêmes lignes de journal que celles vues précédemment avec la commande cat. Cela confirme que votre script Python peut ingérer avec succès les données du journal ligne par ligne.
Appliquer les Regex pour l'extraction d'IP
Dans cette étape, vous améliorerez votre script Python pour extraire automatiquement l'adresse IP de chaque ligne de journal. Pour ce faire, nous utiliserons les expressions régulières (Regex). Les Regex sont un outil puissant pour faire correspondre des modèles dans du texte.
Les expressions régulières sont utiles car les journaux sont semi-structurés : ils suivent des modèles, mais généralement pas sous la forme d'objets Python propres. Les Regex vous permettent de décrire le modèle de texte que vous recherchez et de laisser l'interpréteur effectuer le travail de correspondance répétitif.
Python fournit un module intégré appelé re pour travailler avec les expressions régulières. Nous devons importer ce module et définir un modèle qui correspond à une adresse IPv4. Une adresse IPv4 se compose de quatre nombres (allant de 0 à 255) séparés par des points.
Si log_analyzer.py est toujours ouvert dans nano, continuez à l'éditer. Sinon, rouvrez-le avec :
nano log_analyzer.py
Mettez à jour votre script pour inclure le module re et la logique de recherche des adresses IP. Remplacez tout le contenu du fichier par le code suivant :
import re
def analyze_logs(file_path):
print(f"Analyzing log file: {file_path}\n")
## Define a Regex pattern for an IPv4 address
## \b ensures word boundaries, \d{1,3} matches 1 to 3 digits, \. matches a literal dot
ip_pattern = r'\b(?:\d{1,3}\.){3}\d{1,3}\b'
with open(file_path, 'r') as file:
for line in file:
## re.findall returns a list of all matches in the string
ips_found = re.findall(ip_pattern, line)
if ips_found:
## We take the first IP found in the line
source_ip = ips_found[0]
print(f"Extracted IP: {source_ip}")
if __name__ == "__main__":
log_file = "access.log"
analyze_logs(log_file)
Enregistrez le fichier avec Ctrl+O et Enter. Si vous souhaitez tester cette version intermédiaire maintenant, quittez avec Ctrl+X et exécutez le script. Sinon, vous pouvez continuer directement à l'étape suivante.
python3 log_analyzer.py
Vous devriez voir une sortie similaire à celle-ci :
Analyzing log file: access.log
Extracted IP: 192.168.1.10
Extracted IP: 10.0.0.15
Extracted IP: 172.16.0.5
Extracted IP: 192.168.1.22
Extracted IP: 10.0.0.25
Le script ignore désormais avec succès le reste du texte du journal et isole uniquement les adresses IP sources grâce à la puissance des Regex.
Détecter les signatures SQLi
Dans cette étape, vous ajouterez une fonctionnalité de détection de sécurité à votre script. L'injection SQL (SQLi) est une attaque web courante où des instructions SQL malveillantes sont insérées dans des champs de saisie.
Cela transforme le script d'un simple analyseur en un détecteur. Au lieu de simplement extraire des champs, vous appliquez maintenant une logique de sécurité pour décider quelles lignes méritent une attention particulière. Ce passage de la collecte à l'interprétation est ce qui rend l'automatisation opérationnellement précieuse.
Les attaquants utilisent souvent des mots-clés spécifiques comme UNION SELECT pour voler des données, ou ' OR '1'='1 pour contourner l'authentification. Nous pouvons utiliser les Regex pour scanner les lignes du journal à la recherche de ces signatures d'attaques connues.
Si vous éditez toujours le même fichier dans nano, continuez à travailler dessus. Sinon, rouvrez-le :
nano log_analyzer.py
Nous allons définir un nouveau modèle Regex pour capturer les expressions SQLi courantes. Nous utiliserons (?i) pour rendre la recherche insensible à la casse, ce qui signifie qu'elle détectera UNION, union ou uNiOn. Mettez à jour votre script pour qu'il corresponde au code suivant :
import re
def analyze_logs(file_path):
print(f"Scanning log file for SQLi attacks: {file_path}\n")
ip_pattern = r'\b(?:\d{1,3}\.){3}\d{1,3}\b'
## Define a Regex pattern for SQL Injection signatures
## (?i) makes it case-insensitive
## It looks for 'union select' OR 'or 1=1' variations
sqli_pattern = r"(?i)(union.*select|or\s+1\s*=\s*1|'.*or.*')"
with open(file_path, 'r') as file:
for line in file:
ips_found = re.findall(ip_pattern, line)
source_ip = ips_found[0] if ips_found else "Unknown IP"
## re.search returns a match object if the pattern is found, otherwise None
if re.search(sqli_pattern, line):
print(f"[ALERT] SQL Injection detected from IP: {source_ip}")
print(f"Raw Log: {line.strip()}\n")
if __name__ == "__main__":
log_file = "access.log"
analyze_logs(log_file)
Enregistrez le fichier avec Ctrl+O et Enter. Quittez nano avec Ctrl+X uniquement lorsque vous êtes prêt à exécuter le script depuis le terminal.
python3 log_analyzer.py
Votre sortie devrait maintenant signaler spécifiquement les requêtes malveillantes :
Scanning log file for SQLi attacks: access.log
[ALERT] SQL Injection detected from IP: 10.0.0.15
Raw Log: 10.0.0.15 - - [10/Oct/2026:13:55:45 -0700] "GET /login.php?user=admin' OR '1'='1 HTTP/1.1" 200 5120
[ALERT] SQL Injection detected from IP: 192.168.1.22
Raw Log: 192.168.1.22 - - [10/Oct/2026:13:56:12 -0700] "GET /products.php?id=1 UNION SELECT username, password FROM users HTTP/1.1" 200 4012
Votre script agit désormais comme un système de détection d'intrusion (IDS) basique, identifiant automatiquement les requêtes suspectes dans le fichier journal.
Exporter vers un rapport CSV
Dans cette dernière étape, vous formaterez les résultats et les enregistrerez dans un fichier CSV (Comma-Separated Values). L'affichage dans le terminal est idéal pour les tests, mais les équipes de sécurité ont besoin de rapports structurés pouvant être ouverts dans un tableur ou ingérés par d'autres outils.
Python dispose d'un module csv intégré qui facilite grandement l'écriture de fichiers CSV.
Si vous avez gardé le fichier ouvert, continuez à l'éditer. Sinon, rouvrez-le :
nano log_analyzer.py
Nous allons importer le module csv, ouvrir un nouveau fichier appelé report.csv en mode écriture ('w'), et y écrire nos découvertes. Remplacez votre code par cette version finale :
import re
import csv
def analyze_logs(file_path, output_csv):
print(f"Analyzing logs and generating report: {output_csv}...")
ip_pattern = r'\b(?:\d{1,3}\.){3}\d{1,3}\b'
sqli_pattern = r"(?i)(union.*select|or\s+1\s*=\s*1|'.*or.*')"
## Open the output CSV file in write mode
with open(output_csv, 'w', newline='') as csv_file:
writer = csv.writer(csv_file)
## Write the header row
writer.writerow(['Source IP', 'SQLi Detected', 'Raw Log'])
with open(file_path, 'r') as file:
for line in file:
clean_line = line.strip()
ips_found = re.findall(ip_pattern, clean_line)
source_ip = ips_found[0] if ips_found else "Unknown IP"
## Check if SQLi is detected
sqli_detected = "Yes" if re.search(sqli_pattern, clean_line) else "No"
## Write the data row to the CSV
writer.writerow([source_ip, sqli_detected, clean_line])
print("Report generation finished.")
if __name__ == "__main__":
log_file = "access.log"
report_file = "report.csv"
analyze_logs(log_file, report_file)
Enregistrez le fichier et exécutez le script :
python3 log_analyzer.py
Vous verrez un message indiquant que la génération du rapport est terminée. Vérifions maintenant que le fichier CSV a été créé et examinons son contenu à l'aide de la commande cat :
cat report.csv
Vous devriez voir une sortie CSV parfaitement formatée :
Source IP,SQLi Detected,Raw Log
192.168.1.10,No,192.168.1.10 - - [10/Oct/2026:13:55:36 -0700] "GET /index.html HTTP/1.1" 200 2326
10.0.0.15,Yes,10.0.0.15 - - [10/Oct/2026:13:55:45 -0700] "GET /login.php?user=admin' OR '1'='1 HTTP/1.1" 200 5120
172.16.0.5,No,172.16.0.5 - - [10/Oct/2026:13:56:01 -0700] "POST /api/data HTTP/1.1" 404 134
192.168.1.22,Yes,192.168.1.22 - - [10/Oct/2026:13:56:12 -0700] "GET /products.php?id=1 UNION SELECT username, password FROM users HTTP/1.1" 200 4012
10.0.0.25,No,10.0.0.25 - - [10/Oct/2026:13:57:00 -0700] "GET /about.html HTTP/1.1" 200 1024
Résumé
Dans ce laboratoire, vous êtes passé avec succès de la lecture manuelle des journaux à une analyse automatisée à l'aide de Python. Vous avez appris à lire et à traiter des fichiers texte ligne par ligne en utilisant la gestion de fichiers intégrée de Python. Vous avez également utilisé le module re pour appliquer des expressions régulières afin d'extraire des formats de données spécifiques, tels que les adresses IP. De plus, vous avez implémenté une logique de détection de sécurité en faisant correspondre des signatures d'attaques par injection SQL connues avec les données brutes des journaux. Enfin, vous vous êtes exercé à exporter des données structurées dans un rapport CSV à l'aide du module csv, rendant les résultats faciles à partager et à analyser davantage.
Ces compétences constituent la base de l'automatisation de la sécurité et de l'analyse des données, vous permettant de traiter efficacement des ensembles de données massifs.



