juin
2008
Taint est un fork de PHP initialement proposé par Wietse Venema.
Le principe est de marquer chaque variable par un masque de bits afin de savoir si elles sont correctement préparées avant d’être envoyées vers une sortie comme un document HTML, une requête SQL, une expression rationnelle, une commande système… Vous n’êtes pas sans savoir que chaque type de sortie a son propre mécanisme de préparation des variables (échappement) :
http://php.developpez.com/faq/index.php?page=securite#securite-injection
La problématique de Taint est de déterminer quelles variables sont envoyées vers une sortie avant d’avoir été correctement préparées.
Si j’utilise echo ou print sur une variable qui n’est pas passée par htmlentities() ou htmlspecialchars(), Taint s’en rend compte et m’affiche un message :
<?php
ini_set("taint_error_level", E_WARNING);
$input = $_GET['input'];
echo "You entered: $input\n";
Warning: echo() [function.echo]: Argument contains data that is not converted with htmlspecialchars() or htmlentities() in C:\Web\online\http\tests\taint\basic.php on line 4
You entered: bouh
Ainsi, Taint permet de marquer les variables qui ont été préparées pour un affichage particulier. Par exemple, si j’utilise htmlentities() sur une variable, Taint marque cette variable avec un masque de bits lui permettant de savoir qu’elle est prête à être affichée dans une page Web. Si j’utilise echo ou print sur cette variable, tout se passe bien :
<?php
ini_set("taint_error_level", E_WARNING);
$input = htmlspecialchars($_GET['input'], ENT_QUOTES);
echo "You entered: $input\n";
You entered: bouh
De même, Taint m’avertit si j’utilise une fonction inappropriée pour préparer mes données :
<?php
ini_set("taint_error_level", E_WARNING);
$input = isset($_GET['input']) ? htmlspecialchars($_GET['input'], ENT_QUOTES) : '';
mysql_connect('localhost', 'root', '');
mysql_select_db('developpez');
mysql_query("SELECT * FROM rubrique WHERE nom LIKE '%$input%'");
Warning: mysql_query() [function.mysql-query]: Query contains data that is not converted with mysql_real_escape_string() in C:\Web\online\http\tests\taint\basic.php on line 6
Taint n’est pas une déclinaison de PHP prévue pour les serveurs en production. Elle est résolument orientée vers les développeurs sur leur machine de développment. N’oubliez pas d’activer le niveau d’erreurs Taint dans php.ini ainsi que l’affichage des erreurs PHP :
error_reporting = E_ALL | E_STRICT
display_errors = On
taint_error_level = E_WARNING
Une dernière chose : Taint est un fork de PHP car il faut apporter de légères modifications à son code source. Ainsi, toutes les fonctions n’ont pas encore été réécrites par Mr Venema. Je suis sûr qu’il accepterait volontiers de l’aide si certains d’entre vous ont confiance en leurs compétences en langage C. Je me ferai un plaisir de vous mette en contact
Voici la RFC de Taint contenant la liste à jour des fonctions réécrites : http://wiki.php.net/rfc/taint
NB1 : Certaines extensions ne suivant pas les recommandatsions du PHP Group pour l’écriture de leurs fonctions, elles risquent d’être plus complexes à « teinter ». Ne vous découragez pas pour autant, car je suis sûr que les mainteneurs de ces extensions accepteraient volontiers un patch résolvant ces problèmes…
NB2 : Les exemples présentés ici activent display_errors, mais le plus pratique est parfois de cacher les erreurs en ayant une console avec tail -f error.log : à vous de voir