Page 1 sur 1

Plantage volontaire d'apache

Posté : 06 juil. 2009, 15:21
par sebcap26
Bonjour,

Voila mon problème. Un utilisateur de mon site à trouvé une faille, d'un type que je n'avais jamais vu. Il réussit à faire planter apache en injectant du texte dans l'url. Après installation d'un système me permettant de savoir la page qu'il utilise, j'ai fini par trouver (les logs d'apache faisaient plus de 1 Go, donc inouvrables et inexploitables :shock: ).

Il utilise cette technique un peu partout, et ca fonctionne sur l'immense majorité des pages du site. Il injecte de cette facon :

/sujet.php?id=http://217.218.225.2:2082/index.html?

La variable info est sensée être un nombre. La variable est bien traitée pour éviter les injections SQL, et ne pose aucun problème au serveur SQL, à part un message d'erreur car ce n'est pas le bon type de données. Après vérification de mon code, je pense que ca vient de cette ligne :
header('Location: repondre.php?id='.$_GET['id']);
Alors ma première question : Comment une telle ligne peut-elle faire planter apache ?
Malgré les risques, je suis allé voir l'url qu'il injecte depuis mon navigateur, et il s'agit simplement d'une page de login d'un cpanel, donc rien de méchant.

Deuxième question : Mon site comporte un trop grand nombre de pages pour que je les modifie toutes à la main. Donc mon idée, même si c'est un peu bourrin, serait de, dans une des pages qui est utilisée partout (header.php), filtrer les variables GET, et supprimer celles contenant une url (car je pense que sa méthode fonctionne avec d'autres urls). Donc comment identifier une chaine comme url ?

Merci.

Posté : 06 juil. 2009, 16:31
par enneite
bah pour savoir si une chaine est une url:
function test_si_url($chaine)
{
if(strpos($chaine,"http://")!=false) $res=true;
else $res=false;

return $res;

}
ça commence comme ça, on peut meme faire evoluer et ameliorer cette fonction.

Posté : 06 juil. 2009, 16:38
par enneite
reflexion faite, je me dis que tu devrais plutôt tester si ton ID est un nombre avant de rediriger...
Par contre, je ne vois pas comment cela fait planter ton apache;

Pour tes logs : utilise une rotation des logs

http://httpd.apache.org/docs/1.3/progra ... elogs.html

Posté : 06 juil. 2009, 16:49
par agité
ben déjà tu fais intval() sur ton ($_GET['id']) comme ça plus de redirection qui foirent.

Posté : 06 juil. 2009, 22:46
par Sékiltoyai
Je vais répondre à la question : Pourquoi ça fait planter apache ?
Tu obtiens une url de redirection de ce type : "repondre.php?id=http://217.218.225.2:2082/index.html"
Url qui est invalide. Il est normal que cela puisse faire planter apache, puisqu'il peut être amené à parser les headers avant de les envoyer au navigateur.

Posté : 06 juil. 2009, 23:31
par savageman
Url qui est invalide. Il est normal que cela puisse faire planter apache, puisqu'il peut être amené à parser les headers avant de les envoyer au navigateur.
J'suis pas sûr d'avoir tout compris, mais une URL invalide ne devrait pas faire planter Apache.
(Par contre, il est très facile de saturer les connexions d'apache sans saturer le réseau. C'est un gros problème inhérent à Apache, mais c'est un autre problème.)

Posté : 07 juil. 2009, 00:46
par Sékiltoyai
Url qui est invalide. Il est normal que cela puisse faire planter apache, puisqu'il peut être amené à parser les headers avant de les envoyer au navigateur.
J'suis pas sûr d'avoir tout compris, mais une URL invalide ne devrait pas faire planter Apache.
(Par contre, il est très facile de saturer les connexions d'apache sans saturer le réseau. C'est un gros problème inhérent à Apache, mais c'est un autre problème.)
Bah suffit que la connexion PHP-Apache soit foireuse…
En plus, quand on utilise la fonction header(), il y a de fortes chances que le résultat soit interprété comme tel…

Mais sinon peut être que le code de la page vers laquelle on redirige pourrait nous en dire plus (des redirections récursives ?).

Re: Plantage volontaire d'apache

Posté : 07 juil. 2009, 09:42
par FuZZyLine
Salut,
Bonjour,
Voila mon problème. Un utilisateur de mon site à trouvé une faille, d'un type que je n'avais jamais vu. Il réussit à faire planter apache en injectant du texte dans l'url.
J'ai déja entendu parlé de ca bien que ca fasse un bail. Bref, peu importe ;)
Après installation d'un système me permettant de savoir la page qu'il utilise, j'ai fini par trouver (les logs d'apache faisaient plus de 1 Go, donc inouvrables et inexploitables :shock: ).
Il utilise cette technique un peu partout, et ca fonctionne sur l'immense majorité des pages du site. Il injecte de cette facon :
/sujet.php?id=http://217.218.225.2:2082/index.html?
La variable info est sensée être un nombre. La variable est bien traitée pour éviter les injections SQL, et ne pose aucun problème au serveur SQL, à part un message d'erreur car ce n'est pas le bon type de données. Après vérification de mon code, je pense que ca vient de cette ligne :
header('Location: repondre.php?id='.$_GET['id']);
Alors ma première question : Comment une telle ligne peut-elle faire planter apache ?
A vu de nez je dirais qu'il boucle ;)
Malgré les risques, je suis allé voir l'url qu'il injecte depuis mon navigateur, et il s'agit simplement d'une page de login d'un cpanel, donc rien de méchant.
Deuxième question : Mon site comporte un trop grand nombre de pages pour que je les modifie toutes à la main. Donc mon idée, même si c'est un peu bourrin, serait de, dans une des pages qui est utilisée partout (header.php), filtrer les variables GET, et supprimer celles contenant une url (car je pense que sa méthode fonctionne avec d'autres urls). Donc comment identifier une chaine comme url ?
Merci.
Déja, si, l'ID est numérique:
if (!is_numeric($_GET[id])) die("Tu peux traiter ici... En remplacant die par ce que tu veux.");
...
// suite du process
...
De mon côté, je vérifie l'autorisation de telle ou telle URL et pareil avec les fragments.
define ("authorized", 1);
define ("unauthorized", 2);
define ("restricted", 4);

// Récupération de l'url
$strUrl = ...

// Récupération d'un des fragment du get (sous while ou for)
$strFrag = ...

$arrayAuthorizedUrl = Array("accueil" => 1, "admin" => 4, "member" => 4, "send" => 1);
$arrayAuthorizedFrag = Array("id", "log", ...);

if (!isset($arrayAuthorizedUrl[$url] | (!$arrayAuthorized[$url]  & authorized) ) die("...ou traitement");

if (!!isset($arrayAuthorizedFrag[$strFrag]) ) die("...ou traitement");
...
// Suite du process
...
C'est vraiment pas très clair mais ca représente la structure telle qu'est la mienne pour la gestion des entrées. Ce n'est pas la "spuper-extra" protection mais bon, c'est déja un début. J'espere avoir saisi ton problème et t'avoir mis sur la piste d'une solution.

@+ ;)

Posté : 07 juil. 2009, 13:50
par sebcap26
Merci à tous pour vos réponses.

Le problème c'est que je ne souhaitait pas modifier les pages une par une, vu que y'en a beaucoup trop. J'ai donc fait un filtrage sur les éléments du tableau $_GET dans la page qui est commune à toutes les autres. Comme ces variables sont parfois du texte, le problème est surtout de savoir si une chaine est une url. Pour le moment, j'ai identifié une chaine comme url si elle contient "http://", je pense que ca devrait éviter les bugs.

Posté : 07 juil. 2009, 14:02
par Sékiltoyai
Non, mais t'as pas besoin.
Tu te contentes d'interdire les caractères improbables dans un id. Voire, comme ça a été dit, si l'id est forcément numérique, d'interdire les id non numériques…

Posté : 07 juil. 2009, 14:24
par FuZZyLine
Merci à tous pour vos réponses.
Le problème c'est que je ne souhaitait pas modifier les pages une par une, vu que y'en a beaucoup trop. J'ai donc fait un filtrage sur les éléments du tableau $_GET dans la page qui est commune à toutes les autres. Comme ces variables sont parfois du texte, le problème est surtout de savoir si une chaine est une url. Pour le moment, j'ai identifié une chaine comme url si elle contient "http://", je pense que ca devrait éviter les bugs.
Allez, puisque tu veux absolument tester s'il s'agit d'une url voici une preg que j'ai conçu y a pas bien longtemps. Elle suffit allègrement à mes besoins... Modifie la si tu le souhaites ;)
Je doute être le seul à y avoir pensé, peut-être, même, y en t'il de mieux... 'fin à toi de voir ;)
$value = "Ta chaine à tester";
$pattern = "#^(((http|https)(:\/\/))[\w+]|([w]{3})[\.])(.*)#Um";
$match();
if (preg_match($pattern, $value, $match) =! 0) /* alors c'est bien une URL */ exit(-1);
Ce quelle reconnait: (Maj/Min)

http://www.
https://www.
www.suite...

Ce quelle ignore:

Beaucoup de choses dont les url mal formées.

M'en sert pour parser une url via formulaire. Elle me donne toute satisfaction même si
je ne peux, biensur, vérifier son existance sur la toile. En même temps ca tombe bien c'est
pas son utilisation de base ;)

Sinon, tu as aussi:

la fonction filter_var qui, liée à une liste d'options et de flags, n'est pas désagréables.

@+ bon code ;)

Posté : 09 juil. 2009, 13:38
par sebcap26
Merci à tous pour vos réponses et à Fuzzy pour son code. Mon problème est réglé.

Posté : 10 juil. 2009, 13:12
par Hywan
Hey :),

Moi j'avais une question : est-ce tu as une réécriture d'URL quelque part, juste pour la curiosité ?

Posté : 10 juil. 2009, 13:31
par Invité
Euh, non aucune d'installée, pourquoi ?

Posté : 10 juil. 2009, 14:00
par Hywan
Non parce que c'est un cas typique. Tu as une réécriture qui lance une réécriture, donc tu boucles et Apache crash.