Le couche contrôleur, dans une architecture MVC comprend le systèle de routage et les différents contrôleurs associés aux actions / cas d’utilisations / routes de l’application.
Les contrôleurs sont chargés d’effectuer les vérifications nécessaires concernant
les requêtes HTTP et les
données transmises par le client, et le cas échéant de renvoyer un code de
statut d’erreur avec la fonction http_status_code(40x), notamment :
400—Bad Request: lorsque les données reçues sont invalides ;400—Not Found: lorsque la requête porte sur un objet qui n’existe pas ou en cas de non respect de l’intégrité référentielle.
Le contrôleur interragit :
- avec le modèle et la couche de persistance des données — souvent assurée par un SGBD, (en utilisant éventuellement un ORM ;
- avec la vue, responsable du rendu HTML (en utilisant éventuellement un moteur de gabarits).
Après une opération qui modifie l’état du système (création, mise-à-jour ou
suppression), le contrôleur fait généralement une redirection : header('Location: /uri').
Ne jamais faire confiances aux données en provenance du client.
Tous les contrôles effectués côté client, que ce soit en HTML ou en Javascript servent uniquement à l’ergonomie, mais en aucun cas à la sécurité : il est (très) facile de les contourner.
Toujours considérer une utilisation malveillante par des moyens détournés :
- javascript désactivé ;
- édition dynamique du contenu du document ou utilisation d’un navigateur qui ignore les contraintes de saisie au niveau des formulaires ;
- saisie manuelle d’URL (contournement des liens de l’application) ;
- recours à des forgeurs de requêtes HTTP.
C’est le rôle du contrôleur, côté serveur, d’effectuer les vérifications nécessaires.
En HTML, seules les méthodes GET et POST sont utilisables pour les formulaires.
Selon le style d’architecture ReST,
la méthode POST sert à créer, PUT à mettre à jour et DELETE à supprimer.
Le Javascript permet d’utiliser ces méthodes, mais en attendant, le POST
doit servir à toutes les opérations de changement d’état. Une solution est
d’utiliser une seule route, avec un algorithme capable de déterminer l’opération
à effectuer ; exemple :
- si l’identifiant est égal à 0 et qu’il y a des données en entrée (de la requête), c’est une création ;
- si l’identifiant est différent de 0 et qu’il y a des données en entrée, c’est une mise à jour ;
- si l’identifiant est différent de 0 et qu’il n’y a pas des données en entrée, c’est une suppression.
Sécurité
La méthode GET ne doit jamais être utilisée pour une action qui modifie
l’état du système. En effet, c’est elle qui est utilisée lors du clic sur
un lien hypertexte, la saisie d’une adresse web ou le chargement de ressources
externes à la page (images, CSS, javascript…). Il est facile pour un attaquant
d’inciter des utilisateurs :
- à scanner et suivre le lien contenu dans un QR-Code ;
- d’envoyer un courriel contenant un lien hypertexte, ou une balise
imgqui dont la source ne pointe pas sur une image mais vers une URL d’action…
Le “referer” est un en-tête HTTP qui indique l’URL de la page web d’où provient une requête. Lorsqu’un utilisateur clique sur un lien pour accéder à une nouvelle page, le navigateur envoie l’URL de la page d’origine via cet en-tête. Le referer est couramment utilisé pour :
- l’analyse de trafic : il permet aux webmestres de comprendre l’origine des visites et le cheminement dans le site ;
- la personnalisation en fonction de l’origine, ou la redirection vers la page d’origine après authentification.
Exemple en PHP :
<?php
if (isset($_SERVER['HTTP_REFERER'])) { //si le referer est défini
$referer = $_SERVER['HTTP_REFERER'];
echo 'Origine : ' . htmlspecialchars($referer) . '<br/>';
} else {
echo "Aucun referer trouvé.";
}
?>
Comme tout ce qui provient du client, le referer est un vecteur d’attaque.
La validation consiste à vérifier qu’un chaîne de caractères respecte
un certain motif (cf fonction filter_var qui utilise des expressions rationnelles).
Le filtrage consiste à désactiver (échapper — cd \) ou remplacer certains
caractères spéciaux / de contrôle : côte simple ou double, < (remplacé par <)…
Les caractères à filtrer dépendent du contexte ; exemples :
- la fonction
PDO::quoteet les requêtes préparées servent à échapper les caractères spéciaux du SQL pour prévenir les injections ; - la fonction
htmlspecialcharssert à encoder les caractères spéciaux du HTML (&→&,"→",'→',<→<et>→>) pour prévenir le XSS.
Rappel : attention à éviter le double encodage ; par exemple (en HTML) :
< est encodé < (“lower than”) puis &lt; en cas de double encodage.