Faille dans Apache : Contourner les .htaccess avec « Limit GET POST »

26 février 2008 – 15:10

Le week-end dernier, j’ai reçu un coup de fil d’un ami (Geo). Il m’annonçait qu’il avait réussi à contourner le .htaccess que j’avais placé pour sécuriser la zone admin de Ghosts In The Stack. Perplexe, je lui ai demandé comment il avait fait… et il s’avère que cela serait du à Apache, qui a tendance à exécuter les requêtes qu’il ne comprend pas comme étant des requêtes GET. Concernant les autres serveurs Web, je n’ai pas pu tester car je n’en ai pas d’autres sous la main. Voici quelques éléments pour comprendre comment tirer profit de la faille, et comment éviter de se faire avoir.

Mise en évidence de la faille

Supposons que nous disposons d’un serveur Apache local et que nous avons une page index.php très simple comme ceci :

<h1>Bonjour !</h1>

Pour accéder à la page, nous accédons à l’URL http://127.0.0.1/~trance/vuln/ avec un navigateur Web. La requête envoyée est grossièrement la suivante :

GET http://127.0.0.1/~trance/vuln/ HTTP/1.1
Host: 127.0.0.1

La réponse reçue comporte alors le code HTML de la page Web. Jusqu’ici, tout est normal : Apache n’a fait qu’interpréter la requête GET qu’on lui a envoyé. Maintenant, imaginez que nous envoyons une requête mal formée qui n’est pas de type GET, comme :

n1Mp0rTeKwa http://127.0.0.1/~trance/vuln/ HTTP/1.1
Host: 127.0.0.1

Et là, nous constatons qu’Apache ne fait absolument aucune différence entre cette et la requête précédente ! Il n’y a aucune erreur ; il renvoie la même chose. A première vue, cela ne choque pas forcément, mais on s’aperçoit assez vite que l’on peut tirer profit de cette faille pour contourner certaines protections .htaccess.

Contourner le « Limit GET POST »

Dans de nombreux cas, un webmaster peut souhaiter restreindre l’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’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’illustrent. Certains proposent une solution simple pour protéger l’accès à un fichier par un mot de passe. Il suffit, selon eux, de créer un .htaccess selon ce modèle :

<Files fichierAProteger.php>

AuthUserFile /chemin/vers/.htpasswd
AuthName "Zone à accès restreint"
AuthType Basic
    <Limit GET POST>
    require valid-user
    </Limit>
</Files>

Ce fichier permet d’indiquer à Apache de refuser toute requête POST ou GET si l’utilisateur n’est pas identifié avec un login et un mot de passe apparaissant dans le fichier .htpasswd correspondant. En fait, peu importe qu’il y ait de .htpasswd ; la faille ne se situe pas à ce niveau.

Souvenez-vous de ce que nous avons vu plus haut. Nous avons vu qu’Apache interprétait toutes les requêtes qu’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’authentifier !

Exemple : imaginons que nous avons un .htaccess rudimentaire de ce type dans le même dossier :

<Limit GET POST>
Deny from all
</Limit>

Logiquement, ce fichier est censé interdire tout accès aux pages du dossier. Le hic, c’est que seules les requêtes GET ou POST sont concernées… Tentez d’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 :

n1Mp0rTeKwa  http://127.0.0.1/~trance/vuln/ HTTP/1.1
Host: 127.0.0.1

Et vous obtiendrez la réponse suivante :

<h1>Bonjour !</h1>

Voila donc comment contourner la protection… Simple, n’est-ce pas ? Le pire, dans tout cela, c’est que la majorité des webmasters protègent leurs sites de cette façon. Et j’en faisais partie, jusqu’à ce qu’on me le signale ;)

Correction

La correction est ultra-simple : n’utilisez pas l’instruction « limit » quand vous voulez restreindre l’accès à un fichier ou dossier ! Bannissez les lignes « <Limit GET POST> » et « </Limit> » de vos fichiers .htaccess et vous éviterez ce genre de problèmes.

D’ailleurs, la documentation d’Apache précise bien qu’en général, il ne faut pas utiliser <Limit> lorsque l’on cherche à restreindre l’accès. Je cite : « In the general case, access control directives should not be placed within a <Limit> section. »

Limites

Un petit bémol cependant : pour le moment, nous n’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 à priori sûrs. Mais je vous conseille quand même de patcher vos .htaccess en retirant les lignes « <Limit> » un peu trop dangereuses…

D’autre part, je suis loin d’être un expert en configuration Apache. Il est possible qu’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’intéresse…

Merci encore à Geo pour m’avoir averti de la présence de la faille sur GITS !

  1. 32 réponses à “Faille dans Apache : Contourner les .htaccess avec « Limit GET POST »”

  2. Génial ton article. Au moins, tout à le mérite d’être clair.

    Allez, publie-nous encore des trucs sympa.
    (Et dans 3 ans, tu t’enregistres sur le « Je suis ingénieur informaticieeeeennn ! »)

    Par Geo le 27 février 2008

  3. Merci !
    Au fait, est-ce que tu sais si ça marche aussi avec le serveur IIS ?

    Par Emilien Girault le 27 février 2008

  4. Bien vu ! J’étais quasiment sûr que si la requête était invalide, Apache renvoyait une erreur…

    Perso, pour limiter les requêtes à GET/POST/HEAD, je le fais en général avec mod_security.

    Par Biglo le 3 mars 2008

  5. Salut Emilien pour répondre à ta question par rapport au fonctionnement de la technique sur un serveur ISS, et bien non ! Tout simplement car un serveur ISS ne supporte pas les htaccess, c’est propre à Apache.

    Cependant il existe un équivalent qui permet une authentification http : http://www.iistools.com/en/iispassword.html

    Bonne continuation,

    a+

    Par skorbuth le 4 mars 2008

  6. Salut skorbuth,

    Oui en effet, mais ce que je voulais dire, c’est est-ce qu’ISS aussi interprète les requêtes erronées comme des GET ?

    Par Emilien Girault le 4 mars 2008

  7. L’erreur est humaine et permet au moins de ne pas se tromper par la suite.
    merci :)

    Par tryks le 12 mars 2008

  8. Il faut préciser aussi que Apache ET php se partagent la faute, ce bypass ne fonctionne en effet que sur une page PHP (.php/.php3), c’est la désagréable conclusion que j’ai eu en voulant récupérer par exemple un script .py qui par défaut n’est pas handled par le moteur php…

    Par j0rn le 29 mars 2008

  9. Une vulnérabilité identique quin’est plus valable :
    http://www.verisign.com/security-intelligence-service/current-intelligence/vulnerability-advisories/2003/97.html

    @jorn : Tu dis n’importe quoi, en quoi ca serait la faute de php ? Si tu n’as pas pu récupérer ton fichier script.py, c’est parceque python n’est pas configuré en tant que module d’interprétation.
    La variable AddType est également conséquence de ce défaut.

    Par epitech le 18 avril 2008

  10. Salut, je me demandais, sur quel version d’apache a tu exploité cette « faille » ?
    chez moi :
    [root@Omega]>./apache2 -v (08-05-20)
    Server version: Apache/2.2.8 (Unix)

    avec un fichier .htaccess qui ressemble a ca :
    AuthName « Accès protégé »
    AuthType Basic
    AuthUserFile « /rep/.htpasswd »
    Require valid-user

    je n’ai pas reussi…

    Par Nicolas le 20 mai 2008

  11. J’ai la même version que toi, mais ce n’est pas étonnant que ça n’est pas marché : le .htaccess que tu as mis n’est pas vulnérable. Comme je le dis dans l’article, seuls ceux qui ont la balise « Limit GET POST » le sont… Réessaye en encadrant « Require valid-user » avec cette balise (regarde le 1er exemple de .htaccess que je donne).

    Par Emilien Girault le 20 mai 2008

  12. désolé je me suis raté dans mon c/c , tard tout ca :)
    Le fichier .htacess en question fini bien par :

    j’ai bien vérifié que mon mod_security etait désactivé
    il doit y avoir autre chose, un autre mod ou une spécificité de ma conf peut être..

    Par Nicolas le 20 mai 2008

  13. ah ah,Correction, je me suis pas raté dans mon c/c c’est ton blog qui a strippé mes balises pour éviter une faille xss :)

    Par Nicolas le 20 mai 2008

  14. Le stripping anti-XSS en effet c’est probable :)
    Sinon je suis bientôt en vacances, je vais pouvoir re-tester pour voir ça… car en effet c’est curieux.

    Par Emilien Girault le 20 mai 2008

  15. Génial ton article MDR

    Surtout qu’il n’est pas de toi !!!!!!!!!

    Je connai le site qu’il l’a publié et tu as vraiment fait un copier coller !!!!

    « Futur ingénieur en informatique » Laisse moi rire

    Par Deli le 29 juin 2009

  16. Alors selon toi, j’ai pompé sur un site ? Je serai curieux de savoir lequel… :) Car je peux t’assurer que ce que je dis dedans est totalement vrai : c’est suite à la réaction de Geo que j’ai pris conscience de la faille et rédigé cet article.

    Bien entendu, ça ne m’étonnerait pas qu’une telle faille ait fait l’objet de pas mal d’articles sur le Web, mais je peux te garantir que je n’ai pas du tout copié collé. Ça se voit que tu ne me connais pas… D’ailleurs, j’ai même plutôt l’habitude de voir mes articles pompés sur d’autres sites. Alors si j’étais toi :
    1) Je vérifierai mes sources avant d’accuser quelqu’un de plagiat (sur un site que tu n’as même pas cité).
    2) J’éviterai de critiquer les compétences d’une personne que je ne connais absolument pas en se basant uniquement sur un tel fait.

    En tout cas, j’attends l’adresse de ton soi-disant site plagié, je serai ravi d’aller y faire un tour…

    Par Emilien Girault le 29 juin 2009

  17. Effectivement, pour penser que tu as pu plagier un autre site, ce type ne te connais vraiment pas… :)

    Le bon coté des choses, c’est que tes articles sont suffisament bon pour être eux-même plagiés, ce qui est plutôt flateur finalement. :)

    @++

    Par Léo le 30 juin 2009

  18. Oui ou alors il a vu l’article sur Ghost in the stack … il a pas fait le rapprochement avec ton pseudo ^^

    Rahh ces jeunes … belle article en tout cas !

    Par Thibow le 8 juillet 2009

  19. Salut,

    Voici une page dont le contenu est rigoureusement identique à la tienne. Je ne connais pas ton blog et ne peux pas dire qui pompe sur qui. J’avoue faire moins confiance à un type dont le site veut absolument faire croire que c’est un crack en info (je parle du sien ;) )

    http://www.ghostsinthestack.org/article-26-bypasser-les-htaccess-avec-limit.html

    J’ai une question. J’ai tenté de « cracker » mon propre serveur avec la faille que tu décris. Mais je ne sais pas comment envoyer une requête mal formée comme tu en proposes une.

    Pourrais-tu t’expliquer ?
    (« GET http://127.0.0.1/~trance/vuln/ HTTP/1.1″ ok mais comment tu fais pour envoyer « n1Mp0rTeKwa http://127.0.0.1/~trance/vuln/ HTTP/1.1″ au serveur ?)

    Bref, j’attends avant de corriger :D

    Par Réveillé le 21 juillet 2009

  20. Mort de rire. Il se trouve que deuxieme site est egalement a moi. Je poste assez souvent mes articles sur les deux. Donc aucun n’a pompé sur l’autre…
    Sinon, je ne vois pas ce qui te permet de dire que j’essaye de passer pour un crack. Si c’est le fait d’écrire des articles et publier des projets dans le but d’en faire profiter des gens, je crois qu’on ne partage pas la meme definition du crack en info.
    Sinon pour forger des requetes, tu peux utiliser netcat ou des extensions firefox comme livehttpheaders.
    Comme je l’ai deja dit, cette faille est vieille et sans doute patchée.

    Par Emilien Girault le 21 juillet 2009

  21. J’avoue, je m’en suis rendu compte tout seul comme un grand que j’allais pas tarder à passer pour un débile quand je me suis un peu balladé sur ton autre site. Disons que ça partait d’une bonne intention.

    Pour le fait que je trouve que l’autre site a un design qui me fait penser à quelqu’un qui veut se faire passer pour un crack je dirais que l’ambiance « underground » qui y règne y est pour beaucoup. Je te parle de l’ambiance pas du contenu. Désolé si je me suis mal exprimé. Bref, ça ne me donne pas envie (et qui s’en soucis soyons clair !), c’était une opinion tout ce qu’il y a de plus superficielle ;)

    Bonne continuation.

    Par Réveillé le 23 juillet 2009

  22. Oui il faut avouer que le design de GITS en rebute plus d’un, et commence à dater :p. Mais je t’assure qu’il y a plein d’autres sites dans le même genre, voire « pires » (dans le sens de la lisibilité). Et pourtant, ils sont super riches en contenus. Comme quoi il ne faut pas se fier aux apparences ;)

    Par Emilien Girault le 24 juillet 2009

  23. Salut,
    J’ai comme l’impression que cette faille est encore vraiment d’actualité.
    Aujourd’hui, je l’ai rencontrée trois fois en cherchant !
    Ceci dit, excellent article.
    Bonne continuation !

    Par SWH le 28 juillet 2009

  24. Il y a ça pour régler le problème:
    http://httpd.apache.org/docs/2.2/mod/core.html#limitexcept

    Require valid-user

    Par Sirius le 10 août 2009

  25. Salut,
    Comment faire pour envoyer une requête http mal formée !!!

    Par Amira le 14 septembre 2009

  26. Soit à la main avec des outils comme Netcat (qui nécessite de connaître un minimum le protocole HTTP), soit avec des extensions Firefox comme Live HTTP Headers qui permettent de rejouer une requête en la modifiant.

    Par Emilien Girault le 14 septembre 2009

  27. Merci pour cet article il est super bien détaillé. Cependant, j’ai appliquer ta méthode mais maintenant que je récupère le code source le la page en mode console, comment dois-je faire pour pouvoir l’utiliser avec mon navigateur et réellement accéder a la page souhaitée?

    Par Joe la carotte le 6 juillet 2010

  28. Tu peux utiliser l’extension Firefox citée ci-dessus : Live HTTP Headers. En gros, tu sniffes la requête, et tu la rejoues en modifiant la méthode GET par autre chose.

    Par Emilien Girault le 6 juillet 2010

  29. Testé avec Live HTTP Headers : j’ai changé le méthode get par un truc au hasard et ça me sort à chaque fois « requête invalide ».

    Quelque chose est invalide dans la requéte HTTP. Problèmes envisageables :
    * Méthode de requête absente ou inconnue (GET, POST)
    * Absence d’URL
    * Absence d’identifiant HTTP (HTTP/1.0)
    * La requête est peut-être trop volumineuse
    * Champ Content-Length absent pour les requêtes POST ou PUT
    * Caractère illégal dans le nom de la machine, les soulignés (underscores) ne sont pas autorisés.

    On dirait donc que Firefox empêche systématiquement l’emploi de méthodes autres que GET ou POSt, donc la faille n’est pas exploitable avec ce module.

    Par Eric le 23 août 2010

  30. L’erreur obtenue provient bien du serveur et non de Firefox. Essayez sur Google (avec Live HTTP Headers) et vous verrez ;) .
    Le comportement peut différer sensiblement selon l’éditeur, la version et la configuration du serveur.

    Par Emilien Girault le 23 août 2010

  31. Trés intéréssant émilien :)
    Bravo pour ton explication claire et concise

    Par Eric Seguinard le 1 juin 2011

  32. J’arrive un peu tard, mais pourquoi ne pas utiliser pour interdire tout ce qu’on ne veut pas autoriser ?

    Par Amandilh le 11 juillet 2013

  1. 1 Trackback(s)

  2. 26 avril 2011: faille [Wiki Echosystem]

Désolé, les commentaires sont fermés pour le moment.