Maison >développement back-end >Tutoriel Python >Comment effectuer et détecter des attaques par injection de chemin
Tout d'abord, je ne suis pas un spécialiste du sujet, j'apprends et m'amuse en utilisant les outils d'IA.
Cela dit... Je faisais un développement pour un ami, il a un PDF de 100 feuilles, avec les relevés des transactions bancaires. Vous devez avoir ces enregistrements dans un Excel pour pouvoir les traiter plus tard.
Avec l'utilisation du copilote Github, j'ai créé un script d'extraction de données en utilisant python et quelques bibliothèques... Trois doritos plus tard... Et comme systèmes de petit-déjeuner, de déjeuner et de dîner, j'ai construit un serveur flask, pour servir le script via un point final dans un front avec html, css et js pur et simple.
Lors du processus d'interaction avec Copilot, une alerte a été déclenchée indiquant qu'une partie du code présentait une vulnérabilité de type "path injection". Cette alerte est assez intéressante :D
Et comme je cherche à en savoir plus sur la sécurité informatique, je blogue ici pour laisser une trace de ce voyage...
Ici l'IA commence à parler.
Un attaquant pourrait exploiter une vulnérabilité d'injection de chemin en manipulant les entrées de l'utilisateur pour accéder à des fichiers ou des répertoires non autorisés sur le système de fichiers du serveur. Voici un exemple de la façon dont vous pourriez procéder :
Supposons que vous disposiez d'un itinéraire dans votre application Flask qui permet aux utilisateurs de télécharger des fichiers et de les enregistrer sur le serveur. Si vous ne validez pas ou ne nettoyez pas le nom du fichier, un attaquant pourrait envoyer un nom de fichier malveillant pour tenter d'accéder aux fichiers sensibles du système.
Code vulnérable
@app.route('/upload', methods=['POST']) def upload(): file = request.files['file'] filename = file.filename # Nombre del archivo proporcionado por el usuario save_path = os.path.join('uploads', filename) # Guardar el archivo sin validar el nombre del archivo with open(save_path, 'wb') as f: f.write(file.read()) return 'File uploaded successfully'
Attaque par injection de chemin
Un attaquant pourrait envoyer une requête avec un nom de fichier malveillant tel que ../../etc/passwd. Cela pourrait donner lieu à l'itinéraire suivant :
uploads/../../etc/passwd
Si le serveur ne valide pas ou assainit le nom du fichier, le fichier pourrait être enregistré dans un emplacement indésirable, permettant à l'attaquant d'écraser les fichiers sensibles sur le système.
Solution : Valider et désinfecter l'entrée
Pour éviter ce type d'attaques, vous devez valider et nettoyer le nom du fichier avant de l'enregistrer. Voici une version sécurisée du code :
Code sécurisé
import os import re from flask import Flask, render_template, request, send_file import requests from datetime import datetime app = Flask(__name__) def sanitize_filename(filename): # Eliminar caracteres no permitidos del nombre del archivo return re.sub(r'[^a-zA-Z0-9_\-\.]', '', filename) @app.route('/') def index(): return render_template('index.html') @app.route('/upload', methods=['POST']) def upload(): file = request.files['file'] response = requests.post('http://127.0.0.1:5001/pdf-to-excel', files={'file': file}) # Obtener la fecha actual current_date = datetime.now().strftime("%Y%m%d") # Obtener el nombre original del archivo sin la extensión original_filename = os.path.splitext(file.filename)[0] # Sanitizar el nombre del archivo sanitized_filename = sanitize_filename(original_filename) # Crear el nuevo nombre del archivo con la fecha al final output_filename = f'{sanitized_filename}_{current_date}.xlsx' # Crear la ruta completa del archivo save_path = os.path.join('uploads', output_filename) # Asegurarse de que la ruta sea absoluta save_path = os.path.abspath(save_path) # Guardar el archivo Excel resultante localmente con el nuevo nombre with open(save_path, 'wb') as f: f.write(response.content) # Enviar el archivo Excel de vuelta al usuario con el nuevo nombre return send_file(save_path, as_attachment=True, download_name=output_filename) if __name__ == '__main__': app.run(port=5000, debug=True)
Explication du code sécurisé
Sanitize File Name : La fonction sanitize_filename supprime les caractères illégaux du nom de fichier à l'aide d'une expression régulière.
Créer le chemin complet du fichier : la fonction os.path.join est utilisée pour créer le chemin complet du fichier, en combinant le répertoire de destination (téléchargements) avec le nom du fichier nettoyé (output_filename).
Assurez-vous que le chemin est absolu : la fonction os.path.abspath convertit le chemin en chemin absolu pour éviter les manipulations avec des chemins relatifs.
Enregistrer le fichier : Enfin, le fichier est enregistré dans le chemin spécifié.
Résumé
Injection de chemin : un attaquant peut manipuler les entrées de l'utilisateur pour accéder à des fichiers ou des répertoires non autorisés.
Validation et nettoyage : validez et nettoyez toujours les entrées de l'utilisateur pour éviter les attaques par injection de chemin.
Routes absolues : utilisez des routes absolues pour éviter les manipulations avec des routes relatives.
En suivant ces pratiques, vous pouvez protéger votre application contre les attaques par injection de chemin et améliorer la sécurité globale de votre système.
Ici, je lui ai demandé comment mener l'attaque. De plus, j'ai laissé des logs enregistrés pour pouvoir déboguer ces cas.
Pour sécuriser votre application contre les attaques par injection de chemin, il est utile de comprendre comment ces attaques peuvent être effectuées. Ici, je vous montre comment un attaquant pourrait tenter d'exploiter votre application et comment vous pouvez détecter ces activités dans les journaux.
Manipulation des formulaires HTML
Un attaquant peut manipuler un formulaire HTML pour soumettre un nom de fichier malveillant.
Étape par étape :
@app.route('/upload', methods=['POST']) def upload(): file = request.files['file'] filename = file.filename # Nombre del archivo proporcionado por el usuario save_path = os.path.join('uploads', filename) # Guardar el archivo sin validar el nombre del archivo with open(save_path, 'wb') as f: f.write(file.read()) return 'File uploaded successfully'
Envoi de requêtes HTTP manipulées
Un attaquant peut utiliser Postman pour envoyer des requêtes HTTP contrefaites directement au serveur.
Étape par étape :
Utilisation de scripts Python
Un attaquant peut utiliser des scripts Python pour envoyer des requêtes HTTP malveillantes.
Exemple de script Python :
import os import re from flask import Flask, render_template, request, send_file import requests from datetime import datetime app = Flask(__name__) def sanitize_filename(filename): # Eliminar caracteres no permitidos del nombre del archivo return re.sub(r'[^a-zA-Z0-9_\-\.]', '', filename) @app.route('/') def index(): return render_template('index.html') @app.route('/upload', methods=['POST']) def upload(): file = request.files['file'] response = requests.post('http://127.0.0.1:5001/pdf-to-excel', files={'file': file}) # Obtener la fecha actual current_date = datetime.now().strftime("%Y%m%d") # Obtener el nombre original del archivo sin la extensión original_filename = os.path.splitext(file.filename)[0] # Sanitizar el nombre del archivo sanitized_filename = sanitize_filename(original_filename) # Crear el nuevo nombre del archivo con la fecha al final output_filename = f'{sanitized_filename}_{current_date}.xlsx' # Crear la ruta completa del archivo save_path = os.path.join('uploads', output_filename) # Asegurarse de que la ruta sea absoluta save_path = os.path.abspath(save_path) # Guardar el archivo Excel resultante localmente con el nuevo nombre with open(save_path, 'wb') as f: f.write(response.content) # Enviar el archivo Excel de vuelta al usuario con el nuevo nombre return send_file(save_path, as_attachment=True, download_name=output_filename) if __name__ == '__main__': app.run(port=5000, debug=True)
Détection dans les journaux : enregistre le nom du fichier reçu dans les journaux.
Mise en place de logs pour la détection
Voici une implémentation complète qui inclut la journalisation pour détecter les noms de fichiers suspects :
@app.route('/upload', methods=['POST']) def upload(): file = request.files['file'] filename = file.filename # Nombre del archivo proporcionado por el usuario save_path = os.path.join('uploads', filename) # Guardar el archivo sin validar el nombre del archivo with open(save_path, 'wb') as f: f.write(file.read()) return 'File uploaded successfully'
Résumé
Depuis le navigateur : manipulation de formulaires HTML ou utilisation d'outils de développement de navigateur.
Utilisation d'outils comme Postman : envoi de requêtes HTTP spécialement conçues directement au serveur.
Utilisation de scripts automatisés : utilisation de scripts en Python, Bash ou tout autre langage pour envoyer des requêtes HTTP malveillantes.
Détection des journaux : enregistre le nom du fichier reçu et d'autres activités suspectes dans les journaux pour détecter d'éventuelles attaques.
En mettant en œuvre ces mesures, vous pouvez améliorer la sécurité de votre application et détecter les activités suspectes pouvant indiquer une tentative d'attaque.
Conclusion : Dans ce contexte d'apprentissage et de développement en programmation en binôme avec l'IA, je trouve ce type d'alertes sur la plateforme extrêmement utile pour détecter les vulnérabilités. Aujourd'hui, je me suis réveillé en pensant que j'allais déployer Heroku et là je me retrouve à découvrir différentes vulnérabilités :D
bon codage !
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!