<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>The Tech Guy FR &#187; sécurité</title>
	<atom:link href="http://blog.juliencrouzet.fr/tag/securite/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.juliencrouzet.fr</link>
	<description>Le blog de Julien CROUZET</description>
	<lastBuildDate>Thu, 01 Jul 2010 19:38:12 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0</generator>
		<item>
		<title>[PHP] Les requêtes préparées</title>
		<link>http://blog.juliencrouzet.fr/343/php-les-requetes-preparees/</link>
		<comments>http://blog.juliencrouzet.fr/343/php-les-requetes-preparees/#comments</comments>
		<pubDate>Tue, 17 Mar 2009 07:00:49 +0000</pubDate>
		<dc:creator>c2c</dc:creator>
				<category><![CDATA[pdo]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[piratage]]></category>
		<category><![CDATA[sécurité]]></category>
		<category><![CDATA[Tech]]></category>

		<guid isPermaLink="false">http://blog.juliencrouzet.fr/?p=343</guid>
		<description><![CDATA[
Warning: call_user_func_array() expects parameter 1 to be a valid callback, first array member is not a valid class name or object in /home/www/blog.juliencrouzet.fr/wp-includes/plugin.php on line 166

Call Stack:
    0.0001     623456   1. {main}() /home/www/blog.juliencrouzet.fr/index.php:0
    0.0002     628984   2. require('/home/www/blog.juliencrouzet.fr/wp-blog-header.php') /home/www/blog.juliencrouzet.fr/index.php:17
    0.2072   37734576   3. require_once('/home/www/blog.juliencrouzet.fr/wp-includes/template-loader.php') /home/www/blog.juliencrouzet.fr/wp-blog-header.php:16
    0.2081   37737496   4. do_feed() /home/www/blog.juliencrouzet.fr/wp-includes/template-loader.php:14
    0.2081   37737776   5. do_action() /home/www/blog.juliencrouzet.fr/wp-includes/functions.php:1721
    0.2081   37739800   6. call_user_func_array() /home/www/blog.juliencrouzet.fr/wp-includes/plugin.php:395
    0.2081   37739856   7. do_feed_rss2() /home/www/blog.juliencrouzet.fr/wp-includes/plugin.php:0
    0.2081   37740048   8. load_template() /home/www/blog.juliencrouzet.fr/wp-includes/functions.php:1753
    0.2083   37802208   9. require_once('/home/www/blog.juliencrouzet.fr/wp-includes/feed-rss2.php') /home/www/blog.juliencrouzet.fr/wp-includes/theme.php:1087
    0.2133   37884328  10. the_excerpt_rss() /home/www/blog.juliencrouzet.fr/wp-includes/feed-rss2.php:46
    0.2247   37887832  11. apply_filters() /home/www/blog.juliencrouzet.fr/wp-includes/feed.php:177
    0.2249   37890424  12. call_user_func_array() /home/www/blog.juliencrouzet.fr/wp-includes/plugin.php:166

]]></description>
			<content:encoded><![CDATA[<div id="attachment_344" class="wp-caption aligncenter" style="width: 152px"><a href="http://blog.juliencrouzet.fr/wp-content/uploads/2009/03/pr_cadenas_anse_surex_de_40mm.jpg" rel="lightbox[343]"><img class="size-thumbnail wp-image-344" title="pr_cadenas_anse_surex_de_40mm" src="http://blog.juliencrouzet.fr/wp-content/uploads/2009/03/pr_cadenas_anse_surex_de_40mm-150x150.jpg" alt="pr_cadenas_anse_surex_de_40mm" width="142" height="160" /></a><p class="wp-caption-text">Protégez votre code !</p></div>
<p style="text-align: left;">Une des failles les plus connues, les plus utilisées et les plus simples à utiliser quand on parle de sites Web, c&#8217;est évidemment les injections SQL. Même Kaskpersky, le grand nom de la sécurité informatique <a href="/2009/02/10/le-site-de-kaspersky-hacke/">y passe</a>.</p>
<p style="text-align: left;">Les requêtes préparées sont, de loin, la méthode la plus fiable et la plus performante pour se protéger.</p>
<p style="text-align: left;">Je vais essayer dans cet article de vous expliquer pourquoi et surtout comment les utiliser avec PDO (qui rappelons le va devenir le <a href="http://r.wikipedia.org/wiki/Système_de_gestion_de_base_de_données">SGBD </a>par défaut de PHP6, les fonctions mysql_*, désuettes,  seront recalées au fin fond d&#8217;une extension <a href="http://pecl.php.net">PECL</a>).</p>
<p style="text-align: left;"><span id="more-343"></span></p>
<h2 style="text-align: left;">Une injection SQL, comment ça marche ?</h2>
<p>Le fonctionnement des applications PHP / MySQL (ou autres) depuis des lustres est basé sur un principe simple : L&#8217;utilisateur envoi une requête, cette requête est interprétée, une requête SQL en découle et le résultat est mis en forme ou enregistré en base de données.</p>
<p>Pour ce faire, le développeur génère des requêtes SQL en utilisant les données envoyées par l&#8217;internaute comme paramètres, par exemple :</p>
<pre lang="php">mysql_query('UPDATE `users` SET `name`="' . $_POST['name'] . '" WHERE `id_user`=' . $user_id);</pre>
<p>Problème : L&#8217;internaute envoie ce qu&#8217;il veut, et la requête effectuée sur la base de donnée peut être dangereuse. Par exemple, dans l&#8217;exemple précédent, si l&#8217;internaute envoie</p>
<blockquote><p>&laquo;&nbsp;; DELETE from users; &#8211;</p></blockquote>
<p>vous allez envoyer comme requête à votre serveur SQL :</p>
<pre lang="sql">UPDATE `users` SET `name`=""; DELETE from users; --" WHERE `id_user`= 5</pre>
<p>Soit : Efface tous les noms de ma table puis vide là. Problématique &#8230;</p>
<h2 style="text-align: left;">L&#8217;échappement comme solution miracle &#8230;</h2>
<p>Face à ce problème évident de sécurité, les développeurs ont souvent le reflexe d&#8217;utiliser <a href="http://fr.php.net/mysql-escape-string">mysql_escape_string()</a>, ou mieux, <a href="http://fr.php.net/manual/fr/function.mysql-real-escape-string.php">mysql_real_escape_string()</a>. Ces deux fonctions de PHP ont pour but de protéger les champs envoyés par les internautes contre ces injections SQL en échappant (en ajoutant un backslash ou <strong></strong>) devant les caractères    <em>NULL</em>, <em>x00 </em>(null), <em>n </em>(saut de ligne),    <em>r</em> (retour chariot), <em></em>, <em>&#8216;</em>,    <em>&laquo;&nbsp;</em> et <em>x1a </em>(control).</p>
<p>Pour l&#8217;exemple précédent, cela donnera :</p>
<pre lang="php">mysql_query('UPDATE `users` SET `name`="' . mysql_real_escape_string($_POST['name']) . '" WHERE `id_user`=' . mysql_real_escape_string($user_id));</pre>
<p>soit la requête :</p>
<pre lang="sql">UPDATE `users` SET `name`=""; DELETE from users; --" WHERE `id_user`= 5</pre>
<p>Youpi nous voila protégé ! L&#8217;article est fini ? Non.</p>
<h2 style="text-align: left;">&#8230; ou pas !</h2>
<h3>mysql_real_escape_string() n&#8217;est pas totalement sécurisé</h3>
<p>Et oui, on nous ment, on nous spolie ! Bon, la on passe au niveau barbu du hacking (les enfants, passez au point suivant, ne refaites pas cela chez vous).</p>
<p>mysql_real_escape_string() se base sur le jeu de caractère de la connexion active (<em>SET NAMES</em>) et si celui-ci n&#8217;est pas actif, elle utilise le jeu de caractère par défaut. Il est alors facile d&#8217;utiliser la magie de &laquo;&nbsp;<em><code>chr(0xbf) . chr(0x27)</code></em><code>" pour insérer l'injection fatale.</code>Cependant, cela ne marche que pour des jeu de caractères comme GBK ou Big5, donc il est probable qu&#8217;un <em>SET NAMES</em> soit présent.</p>
<p>Vous n&#8217;avez pas compris ? Pas grave, retenez juste que malgré ce que dit le complot universel, mysql_real_escape_string() n&#8217;est pas infaillible !</p>
<h3>Alors pourquoi ne pas encoder la chaîne ?</h3>
<p>Effectivement, si l&#8217;on utilise <a href="http://fr.php.net/manual/fr/function.htmlentities.php">htmlentities()</a> qui convertit chaque caractère qui peut l&#8217;être en entité HTML (&amp;quelquechose), ou <a href="http://fr.php.net/base64-encode">base64_encode()</a>, etc. il semble que l&#8217;on sera protégés ?</p>
<p>Oui et non, déjà non, on ne sera pas <span style="text-decoration: underline;">COMPLÈTEMENT </span>protégé, pour les même raisons que le point précédent. Et puis vous allez vous compliquer la vie lorsque vous souhaiterez rechercher du texte (oui, rechercher des entités HTML c&#8217;ets pas sexy).</p>
<h3>Et puis surtout, ce n&#8217;est pas optimisé !</h3>
<p>Un des goulot d&#8217;étranglement d&#8217;une application web ou d&#8217;un site, c&#8217;est souvent la base de donnée ; alors en plus y rajouter des traitement, recherche et modifications permanents de chaîne, c&#8217;est du suicide et du massacre de cycle de processeur !</p>
<h2 style="text-align: left;">Puis vinrent les requêtes préparées !</h2>
<p>Les requêtes préparées, ou prepared queries, c&#8217;est la bonne réponse, pour la simple et bonne raison : Ce n&#8217;est pas un patch mais une refonte de la reflexion !</p>
<p>Posons nous une seconde sur le problème, la source de la faille repose sur le fait qu&#8217;un serveur SQL quel qu&#8217;il soit se base sur un concept : PHP se connecte, lui donne une requête (un ordre) qu&#8217;il execute sans broncher.Le script lui prend une donnée qui n&#8217;est pas contrôlée par le développeur et la place au milieu de l&#8217;ordre donnée.</p>
<p>Il n&#8217;y a donc qu&#8217;une solution : Séparer ce que l&#8217;on contrôle, l&#8217;ordre, de ce que l&#8217;on ne controle pas, les arguments.</p>
<p>Le principe de la requête préparée, c&#8217;est ça. On dit au serveur SQL :</p>
<blockquote><p>Tu vas modifier le champs name par une certaine valeur la table users quand le champs id sera d&#8217;un autre certaine valeur</p></blockquote>
<p>Puis, on lui précise</p>
<blockquote><p>La première valeur c&#8217;est $_POST['name'], et la seconde c&#8217;est 5</p></blockquote>
<p>La première partie fera l&#8217;objet d&#8217;un analyse du serveur SQL, la seconde ne le sera pas. Voila, on est protégé, on est optmisé la messe est dite <img src='http://blog.juliencrouzet.fr/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<h2 style="text-align: left;">Donc, comment ça marche ?</h2>
<p>Qui dit requête préparée en PHP, dit <a href="http://fr.php.net/pdo">PDO</a> (ou <a href="http://framework.zend.com/manual/fr/zend.db.html">Zend Framework</a> qui vous simplifie la vie, voila il est placé).</p>
<p>Plutôt qu&#8217;un long discours, voici un exemple qui insere et lit des données, pour aller plus loin, je vous laisse lire la doc.</p>
<pre lang="php">/**
 * Création d'un objet PDO
 */
$object = new PDO('mysql:host=localhost;dbname=myDatabase', 'user', 'pass');
/**
 * On énonce une requête préparée
 */
$statement = $object->prepare("SELECT * FROM `user` WHERE `name`=? OR `firstname`=?");
/**
 * On éxécute l'énoncé avec une paire d'argument
 */
$statement->execute(array($_POST['name'], $_POST['firstname']));
/**
 * On récupère le résultat
 */
$result = $statement->fetchRow();
/**
 * On énonce une requête préparée d'insertion
 */
$statement = $object->prepare("INSERT INTO `users` (`name`, `firstname`, `email`) VALUES (?, ?, ?)");
/**
 * On éxécute l'énoncé pour 4 valeurs différentes
 */
$statement->execute(array('doe', 'john', 'john.doe@gmail.com'));
$statement->execute(array('gates', 'bill', 'bill@microsoft.com'));
$statement->execute(array('jobs', 'steve', 'sjobs@apple.com'));
$statement->execute(array('"; DELETE from users; --', 'blah', 'bleh'));</pre>
<h2 style="text-align: left;">D&#8217;autres intérêts ?</h2>
<p style="text-align: left;">Utiliser des requêtes préparées en PDO ne vous apportera pas que la sécurisation de vos requêtes.</p>
<p style="text-align: left;">Déjà, utiliser PDO vous apportera une vraie conception objet de la gestion de la base de données (mais encore plus avec Zend Framework <img src='http://blog.juliencrouzet.fr/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> ) mais j&#8217;y reviendrais avec un billet sur <a href="http://fr.wikipedia.org/wiki/Mod%C3%A8le-Vue-Contr%C3%B4leur">MVC</a>.</p>
<p>Mais en plus, si vous regardez bien l&#8217;exemple, j&#8217;ai fait 4 requêtes avec une énoncé, donc concretement, votre serveur SQL n&#8217;a analysé qu&#8217;une fois votre requête et vous n&#8217;avez fait aucune analyse des paramètres.</p>
<p>Je vous laisse méditer sur l&#8217;optimisation obtenue <img src='http://blog.juliencrouzet.fr/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://blog.juliencrouzet.fr/343/php-les-requetes-preparees/feed/</wfw:commentRss>
		<slash:comments>14</slash:comments>
		</item>
		<item>
		<title>J&#039;ai pas gagné au loto &#8230;</title>
		<link>http://blog.juliencrouzet.fr/175/jai-pas-gagne-au-loto/</link>
		<comments>http://blog.juliencrouzet.fr/175/jai-pas-gagne-au-loto/#comments</comments>
		<pubDate>Sat, 14 Feb 2009 00:17:55 +0000</pubDate>
		<dc:creator>c2c</dc:creator>
				<category><![CDATA[Web]]></category>
		<category><![CDATA[fun]]></category>
		<category><![CDATA[sécurité]]></category>

		<guid isPermaLink="false">http://blog.juliencrouzet.fr/?p=175</guid>
		<description><![CDATA[
Warning: call_user_func_array() expects parameter 1 to be a valid callback, first array member is not a valid class name or object in /home/www/blog.juliencrouzet.fr/wp-includes/plugin.php on line 166

Call Stack:
    0.0001     623456   1. {main}() /home/www/blog.juliencrouzet.fr/index.php:0
    0.0002     628984   2. require('/home/www/blog.juliencrouzet.fr/wp-blog-header.php') /home/www/blog.juliencrouzet.fr/index.php:17
    0.2072   37734576   3. require_once('/home/www/blog.juliencrouzet.fr/wp-includes/template-loader.php') /home/www/blog.juliencrouzet.fr/wp-blog-header.php:16
    0.2081   37737496   4. do_feed() /home/www/blog.juliencrouzet.fr/wp-includes/template-loader.php:14
    0.2081   37737776   5. do_action() /home/www/blog.juliencrouzet.fr/wp-includes/functions.php:1721
    0.2081   37739800   6. call_user_func_array() /home/www/blog.juliencrouzet.fr/wp-includes/plugin.php:395
    0.2081   37739856   7. do_feed_rss2() /home/www/blog.juliencrouzet.fr/wp-includes/plugin.php:0
    0.2081   37740048   8. load_template() /home/www/blog.juliencrouzet.fr/wp-includes/functions.php:1753
    0.2083   37802208   9. require_once('/home/www/blog.juliencrouzet.fr/wp-includes/feed-rss2.php') /home/www/blog.juliencrouzet.fr/wp-includes/theme.php:1087
    0.2385   37899360  10. the_excerpt_rss() /home/www/blog.juliencrouzet.fr/wp-includes/feed-rss2.php:46
    0.2392   37901792  11. apply_filters() /home/www/blog.juliencrouzet.fr/wp-includes/feed.php:177
    0.2394   37903928  12. call_user_func_array() /home/www/blog.juliencrouzet.fr/wp-includes/plugin.php:166

]]></description>
			<content:encoded><![CDATA[<div id="attachment_178" class="wp-caption aligncenter" style="width: 264px"><a href="http://blog.juliencrouzet.fr/wp-content/uploads/2009/02/pr_cadenas_anse_surex_de_40mm.jpg" rel="lightbox[175]"><img class="size-medium wp-image-178" title="pr_cadenas_anse_surex_de_40mm" src="http://blog.juliencrouzet.fr/wp-content/uploads/2009/02/pr_cadenas_anse_surex_de_40mm-300x211.jpg" alt="La Française des Jeux n'est pas au top" width="254" height="178" /></a><p class="wp-caption-text">La Française des Jeux n&#39;est pas au top</p></div>
<p>&#8230; mais quelque part, tant mieux, parce que la Française des Jeux, ils ne me rassurent pas question Web !</p>
<p><a href="http://blog.juliencrouzet.fr/wp-content/uploads/2009/02/fdjeux.png" rel="lightbox[175]"><img class="alignnone size-medium wp-image-174" title="fdjeux" src="http://blog.juliencrouzet.fr/wp-content/uploads/2009/02/fdjeux-188x300.png" alt="fdjeux" width="188" height="300" /></a></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.juliencrouzet.fr/175/jai-pas-gagne-au-loto/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
