Un forum affiche le pseudonyme des auteurs tel qu'il a été saisi
Exercice supplémentaire · niveau 3 (difficile) · NSI (première), chapitre 10 — Interagir sur le Web · Ce que la page fait toute seule
Énoncé
Un forum affiche le pseudonyme des auteurs tel qu'il a été saisi. Un utilisateur s'inscrit sous le pseudonyme suivant :
<script>envoyer(document.cookie)</script>
- Que se passe-t-il dans le navigateur des autres visiteurs ?
- Écrire en Python une fonction
echapper(texte)qui rend un texte inoffensif avant insertion dans du HTML. - L'ordre des remplacements a une importance. Montrer qu'un ordre mal choisi produit un résultat faux, sur l'exemple du texte
a < b & c.
Corrigé
1. Le serveur recopie le pseudonyme dans la page. Le navigateur des autres visiteurs reçoit donc une balise <script> authentique, qu'il exécute — il n'a aucun moyen de distinguer ce script de ceux du site. Le code s'exécute avec tous les droits de la page, et peut lire les cookies, donc voler la session. C'est une injection de code, et la faute est du côté du site : il a laissé une donnée devenir du programme.
2.
def echapper(texte):
"""Rend un texte inoffensif avant insertion dans du HTML."""
remplacements = [("&", "&"), ("<", "<"),
(">", ">"), ('"', """)]
for ancien, nouveau in remplacements:
texte = texte.replace(ancien, nouveau)
return texte
print(echapper("<script>envoyer(document.cookie)</script>"))
# <script>envoyer(document.cookie)</script>
Le navigateur affiche alors le texte <script>... au lieu de l'exécuter : les entités &lt; et &gt; représentent les chevrons sans les être.
3. L'esperluette doit être traitée en premier, parce que tous les autres remplacements en produisent. Sur le texte a < b & c :
| Ordre | Résultat |
|---|---|
| `&` d'abord, puis `<` | `a < b & c` (correct) |
| `<` d'abord, puis `&` | `a < b & c` (faux) |
Dans le second cas, le & de &lt; — produit par le remplacement précédent — a été échappé à son tour : le navigateur affichera littéralement &lt; au lieu de <. On peut le vérifier en une ligne :
print("a < b & c".replace("<", "<").replace("&", "&"))
# a &lt; b & c
La leçon dépasse le Web : chaque fois qu'on insère une donnée dans un texte qui sera ensuite interprété — HTML, requête de base de données, ligne de commande — il faut l'échapper selon les règles de ce texte-là. Et il faut le faire avec l'outil prévu, jamais avec quatre replace écrits à la main : la question 3 montre à quel point l'ordre compte.
Les autres exercices de ce chapitre Le cours du chapitre
Un blocage sur cet exercice ? Le tuteur d'Adloun guide par questions, sans donner la réponse.