Comment éviter les attaques de $_SERVER["PHP_SELF"] en PHP ?

La variable $_SERVER["PHP_SELF"] peut être utilisée par des pirates pour injecter du code JavaScript dans la page web côté client.

<h1>Formulaire</h1>
<form method="post" action="<?php echo $_SERVER["PHP_SELF"]; ?>">
    <label>Nom d'utilisateur : </label>
    <input type="text" name="username" id="username" />
    <label>Password : </label>
    <input type="password" name="password" id="password" />
    <input type="submit" value="Se connecter" id="connect-btn" />
</form>

Par exemple, ici nous avons un formulaire avec un nom d'utilisateur et un mot de passe.

Le pirate pourrait injecter le code suivant dans l'URL :

<script>
//Attend que la page se charge
window.addEventListener('load', function () {

    //Récupérer les champs du formulaire dans des variables
    var username = document.getElementById('username');
    var password = document.getElementById('password');
    var btn = document.getElementById('connect-btn');

    // Lors de l'envoi du formulaire
    btn.onclick = function(event) {
        //Empêche l'envoi du formulaire
        event.preventDefault();

        //Ajax vers serveur du pirate
        console.log(username.value);
	console.log(password.value);
    };

});
</script>

Les console.log pourraient être remplacés par des fonction Ajax pour envoyer les données du formulaire vers le serveur du pirate.

Le lien suivant peut être envoyé par mail par exemple :

http://127.0.0.1/form.php/%22%3E%3Cscript%3E%20window.addEventListener('load',%20function%20()%20%7B%20var%20username%20=%20document.getElementById('username');%20var%20password%20=%20document.getElementById('password');%20var%20btn%20=%20document.getElementById('connect-btn');%20btn.onclick%20=%20function(event)%20%7B%20event.preventDefault();%20console.log(username.value);%20console.log(password.value);%20%7D;%20%7D);%20%3C/script%3E

Lors de l'ouverture du lien, le script sera injecté dans la page.

Pour éviter cette attaque vous devez utiliser la fonction htmlspecialchars() de PHP. Elle permet d'échapper les caractères HTML.

<h1>Formulaire</h1>
<form method="post" action="<?php echo htmlspecialchars($_SERVER["PHP_SELF"]); ?>">
    <label>Nom d'utilisateur : </label>
    <input type="text" name="username" id="username" />
    <label>Password : </label>
    <input type="password" name="password" id="password" />
    <input type="submit" value="Se connecter" id="connect-btn" />
</form>

Le script ne sera alors pas interprété.

Commentaires