Quelques exemples basiques d’attaque sur une application web

La plupart des failles de sécurité ont une source commune : un excès de confiance envers des données étrangères. Ces données peuvent être envoyées par un visiteur, récupérées d’une régie publicitaire, d’un prestataire qui lui-même peut être victime d’une faille de sécurité, …

Il est primordial de toujours s’assurer que les données reçues soient valides avant tout affichage ou stockage (bdd, fichier, …) sans quoi l’application devient potentiellement vulnérable.

Je décris dans la suite du post les failles de sécurité les plus courantes mais la liste est loin d’être exhaustive, on pourrait effectivement y ajouter :

  • Le spam
  • Cache Poisonning
  • Cross-User Defacement
  • Attaque de type DOS (denis de service)
  • CRLF injection

En cas de doute sur une application, des logiciels existent pour aider le développeur à débusquer certaines failles qu’il aurait pu laisser par inadvertance. On peut citer par exemple le logiciel gratuit d’audit Wapiti (ici) ou l’application d’IBM Rational Appscan (ici).

Injection SQL

Définition

Une injection SQL est une faille de sécurité permettant à un utilisateur mal intentionné d’exécuter n’importe quelle requête SQL sur votre base de données.

La faille est rendue possible lorsque des données envoyées par un utilisateur sont utilisées sans traitement pour construire des requêtes SQL. On peut alors jouer avec les caractères spéciaux (caractères de commentaire en particulier) pour modifier ou ajouter des requêtes.

Les risques d’une injection SQL

  • Rendre inopérante l’application web
  • Voler les informations stockées en base de données
  • Usurpation d’identité
  • Altération des informations stockées dans la base de données

Exemple

Imaginons un formulaire d’identification codé par un stagiaire débutant en informatique :

<form action="doLogin.php" method="post">
 
  <label for="login"> Votre identifiant </label>
<input id="login" name="login" type="text" />
 
  <label for="password">Mot de passe </label>
<input id="password" name="password" type="password" />
<input type="submit" value="Se connecter" />
</form>

Le script doLogin.php récupère les données et exécute la requête suivante :

$existUser = mysql_query("SELECT * FROM users WHERE login =‘". $_POST["LOGIN"] . "’ AND password =‘" . $_POST["PASSWORD"] . "‘ LIMIT 1", $myRessourceSQL);
 
if(mysql_num_rows($existUser)) {
  connectUser();
}

Il est alors très facile pour un pirate de se connecter au site sans avoir de compte en passant comme identifiant : 1′ or 1=1 – . La requête exécutée devient alors :

SELECT * FROM users WHERE login =1OR 1=1 -- AND password = ‘password’ LIMIT 1;

Cet exemple est évidemment basique mais explique bien le principe des injections SQL.

Comment s’en protéger

Vérifier et filtrer toutes les données étrangères avant de les utiliser. De nombreuses méthodes PHP telles que addslashes ou mysql_real_escape_string permettent d’échapper les caractères spéciaux. Il ne faut pas s’en priver. Il est également efficace de transtyper les données numériques.

Ne pas afficher de messages d’erreurs donnant des informations précieuses à un éventuel pirate (type et version de la base de données utilisée, noms des tables ou des champs, …)

Se connecter aux bases de données avec un compte possédant les droits minima nécessaires pour l’application web : inutile de se connecter avec un compte root pour un blog !

Attaque XSS (Cross-Site Scripting)

Définition

En utilisant une vulnérabilité XSS, contrairement à une injection SQL, le pirate s’attaque à l’utilisateur plutôt qu’à l’application web.

Les attaques de type XSS consistent en l’insertion de bouts de code non prévu au sein d’une page web qui sera exécuté côté client par les navigateurs. La faille existe dès que l’application web affiche sur une page des données étrangères sans filtrer les balises html et en particulier la balise <script>.

On distingue deux types d’attaques XSS : le XSS permanent et le XSS transitoire.
Le XSS transitoire profite en général de failles sur les paramètres d’url afin d’y injecter du code fallacieux ; l’url sera alors envoyée à la victime par mail, site malveillant, MSN,… Ce type d’attaque fait souvent pair avec l’ingénierie sociale.

Le XSS permanent apparait lorsque l’application web enregistre dans une base de données ou un fichier le code fallacieux pour ensuite l’afficher sur une page publique (forum, blog, …). Ainsi chaque client qui affiche la page vérolée devient une victime.

Les risques d’une attaque XSS

  • Affichage de contenu subversif pouvant nuire à l’image de marque de l’entreprise propriétaire du site.
  • Redirection vers un autre site pour tromper l’utilisateur, récupérer des informations personnelles, …
  • Vol de session ou de cookies pouvant mener à l’usurpation d’identité.

Exemple

Imaginons un site e-commerce d’une entreprise prestigieuse.

Sur ce site a été mise en place une page 404 personnalisée. Cette page prend dans son corps de page l’url erronée directement sans validation préalable par exemple : « La page «/pagequinexistepas» n’existe pas. Vous allez être redirigé vers la page d’accueil d’ici 5 secondes. »

Imaginons maintenant un pirate qui découvre cette faille. Il prépare un mail pour sa victime reprenant la charte de l’entreprise et lui vantant les mérites d’une nouvelle fonctionnalité mise en place. Bien entendu un lien est présent dans ce mail pointant vers une page erronée. Les paramètres de ce lien sont camouflés et contiennent un script qui récupère les cookies de session et les envoie au pirate.

Le pirate envoie alors ce mail à un ensemble de victimes. Si l’une d’entre elles clique sur le lien en étant connectée sur le site, le pirate sera alors capable d’usurper son identité.

Le pirate aurait également pu développer un site reprenant le skin du site e-commerce et rediriger les victimes sur ce site piégé et ainsi récupérer leurs identifiants.

Autres exemples célèbres :

  • Samy le premier ver XSS pour MySpace
  • Yamanner le premier ver XSS sur la plateforme web-mail Yahoo !

Comment s’en protéger

Filtrer toutes les données étrangères. Ici encore, PHP fournit en standard de nombreuses méthodes : htmlentities, addslashes, strip_tags, etc.

Utiliser des filtres restrictifs en ayant la philosophie suivante : autoriser ce qu’on l’on sait sûr plutôt que de chercher à exclure ce que l’on juge incorrect. Il n’est pas possible d’être absolument exhaustif ; Les hackers savent faire preuve d’imagination !

Il faut vérifier toutes les données ! Même celles qu’on juge à priori sûres, comme les informations provenant d’un select ou d’une checkbox : il est très facile de coder un script qui envoie une valeur quelconque à ces champs.

Attaque CSRF (Cross-Site Request Forgeries)

Définition

Là encore, le pirate s’attaque à l’utilisateur plutôt qu’à l’applicatif web. En effet, les attaques CSRF consistent à faire exécuter des requêtes (GET, POST ou PUT sur un serveur IIS) involontairement aux utilisateurs accrédités d’un site vulnérable. L’envoi des requêtes se fait lorsque la victime visite un site malveillant, un site victime d’une attaque XSS ou en cliquant sur un lien corrompu.

Le vecteur le plus souvent utilisé pour ce type d’attaque est la balise html <img/>.

Les risques d’une attaque CSRF (Cross Site Request Forge)

Usurpation d’identité et exécution d’action malveillantes (dépendant du site victime de la faille de sécurité).

Exemple

Imaginons que l’entreprise du site d’e-commerce présentée pour illustrer les attaques XSS développe une fonction d’achat en un clic.

Cette fonctionnalité se traduit par un formulaire grâce auquel l’utilisateur connecté choisit un produit et sa quantité. Il ne lui reste qu’à valider ce formulaire pour terminer sa commande.

<form action="doAchat.php" method="get">
 
  <label for="produit">Référence du produit</label>
<input id="produit" name="produit" type="text" />
 
  <label for="qte">Quantité</label>
<input id="qte" name="qte" type="text" />
<input type="submit" value="J’achète!" />
</form>

Le pirate reprend son mail et passe en paramètres camouflés le code suivant :

<script type="text/javascript"><!--mce:0--></script>

Ainsi toute victime connectée qui cliquera sur le lien commandera 1000 produits REF0192.

Comment s’en protéger

Envoyez vos données en POST plutôt qu’en GET : ça permet au moins à la victime de se rendre compte a posteriori qu’elle a été victime d’une attaque CSRF lorsque la page de confirmation du formulaire s’affichera.

Ne simplifiez pas les actions importantes : acheter en un clic, supprimer un produit en un clic, etc… Il est très difficile de contrefaire plusieurs requêtes POST consécutives. Par contre, attention, pour des requêtes GET, il suffira d’utiliser plusieurs images au lieu d’une.

Obligez l’utilisateur à utiliser vos formulaires HTML par un système de tokens à durée de vie limitée dans le temps par exemple.

Upload de fichier

L’upload de fichier n’est évidement pas un type d’attaque mais elle peut en être la victime. Il faut être très prudent lorsque l’on permet à un utilisateur d’uploader un fichier sur son site comme un CV au format word ou pdf, une image, etc.

Si l’on n’y prend pas garde, il sera très facile pour un pirate d’installer sur le serveur hébergeant le site un des scripts voire un root kit.

Exemple

Un site propose l’upload d’image en particulier d’image gif.

Le dossier d’upload se trouve dans le document root du site.

Le script d’upload a la forme suivante :

$imageInfo = getimagesize($_FILES["image"]["tmp_name"]);
if($imageInfo["mime"] == "image/gif" || $imageInfo["mime"]== "image/jpeg") {
	$uploadDir = $_SERVER["DOCUMENT_ROOT"] . DIRECTORY_SEPARATOR "uploads";
	$uploadFile = $uploadDir . DIRECTORY_SEPARATOR . basename($_FILES["image"]["name"]);
	if (move_uploaded_file($_FILES["image"]["tmp_name"], $uploadFile) {
		echo "L'upload a réussi";
	}
}
echo "L'upload a échoué";

Le format d’image GIF a ceci de particulier qu’il est possible d’y inclure des commentaires.

Par exemple, je prends une image GIF quelconque, j’ajoute dans le binaire de cette image le commentaire suivant : <?php phpinfo() ; ?> et je la renomme monImage.php

Je vais pouvoir l’uploader sans souci car il s’agit bien d’une image avec comme type mime ‘image/gif’, l’image s’affichera normalement au sein d’une balise <img/> par contre, si je l’affiche directement dans un navigateur, le commentaire sera exécuté comme du PHP classique !

A noter qu’il n’est pas obligé de renommer le fichier en .php si un script intermédiaire utilisant la méthode readfile est appelé pour afficher les images.

Comment s’en protéger

Sortir le dossier d’upload du document root et créer par exemple un sous domaine pointant vers le dossier.

Toujours limiter la taille et le nombre d’uploads que peut exécuter un utilisateur sur une durée donnée.

Renommer les fichiers uploadés et tester les extensions valides en rejetant toutes les autres.

Ressources

Articles relatifs

3 Responses to “Quelques exemples basiques d’attaque sur une application web”

  1. Cool !

    Un petit lien complémentaire :

    http://cwe.mitre.org/

    Répondre

  2. Article très intéressant, toutefois je tiens à préciser que readfile() n’exécute pas le code php éventuellement contenu dans le fichier “à lire”.

    Le problème pourrait par contre se poser si on utilise include ou require pour afficher l’image (mais qui ferai ça).

    Complément : http://fr.php.net/manual/fr/function.readfile.php#48560

    Répondre

  3. Bonjour

    très bonne article, cela m’ a permi de sécurier mon site

    merci

    Répondre

Leave a Reply