LFI / RFI

LFI-haavoittuvuus PHP-sovelluksessa

Keskitaso
20 min

Tässä harjoituksessa aloitamme todentamalla haavoittuvuuden ja sitten hyödynnämme tätä suorittamalla omaa PHP-koodia sovelluksessa. Aloita käynnistämällä tehtävä ja tee vaiheet perässä. Alta löydät myös tiedoston index.php lähdekoodit, joissa kyseinen haavoittuvuus piilee.

LFI - haavoittuvuus PHP-sovelluksissa

Tässä labrassa käytämme hyväksi LFI (Local File Inclusion) haavoittuvuutta ja otamme palvelimen haltuumme.

Tavoite

Ota palvelin haltuusi ja lue lippu.

Tehtävät

Flag

Löydä lippu (flag) labraympäristöstä ja syötä se alle.

Lähdekoodi - index.php

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Mythical Encyclopedia</title>
</head>
<body>
    <?php
    if (!isset($_GET["country"])) {
      include("languages.php"); 
    }
    else {
      echo "<h1>Mythical Encyclopedia</h1>";
    }

    if (isset($_GET["country"])) {
      $country = $_GET["country"];
      if ($country == "us") {
        $file = "./us.php"; 
      }
      else if ($country == "fr") {
        $file = "./fr.php"; 
      }
      else if ($country == "fi") {
        $file = "./fi.php"; 
      }
      else {
        $file = "./" . $country; 
      }
      include($file);
    }

    ?>
</body>
</html>

Haavoittuvuuden todentaminen

PHP-koodista näemme, että index.php ensin tarkistaa, onko GET parametri country annettu (isset-funktio) ja jos tämä on annettu, niin tarkistetaan tämän parametrin sisältämä arvo if-else-if rakenteella.

Logiikka on seuraavanlainen.

  • Jos country parametri on yhtä kuin us, parametri file on ./us.php.
  • Jos country parametri on yhtä kuin fr, parametri file on ./fr.php.
  • Jos country parametri on yhtä kuin fi, parametri file on ./fi.php.
  • Muussa tapauksessa, file parametri on yhtä kuin ./ + country parametri.

Lopuksi suoritetaan include-funktio, jolle annetaan file parametri. Kyseinen funktio suorittaa ja palauttaa annetun tiedoston. Haavoittuvuus syntyy viimeisessä else-lausekkeessa, jossa file parametrille annetaan mikä vain arvo, minkä käyttäjä on antanut country parametrille, joka sitten annetaan include-funktiolle. Tästä syntyy LFI-haavoittuvuus.

Todennetaan haavoittuvuus suorittamalla seuraavanlainen HTTP-pyyntö.

GET https://www-bnmpokft3q.ha-target.com/index.php?country=../../../../../../etc/passwd HTTP/1.1

Hienoa! - Onnistuimme lukemaan järjestelmän sisäisen passwd - tiedoston. Antamamme parametri country sisälsi arvon ../../../../../../etc/passwd ja kun tämä annettiin include -funktiolle, oli tämän arvo ./../../../../../../etc/passwd, joka viittaa ensin sovelluksen juureen, jonka jälkeen etc -kansioon ja tämän sisällä olevaan passwd -tiedostoon.


Haavoittuvuuden hyödyntäminen

Katsotaan seuraavaksi, miten voimme suorittaa omaa PHP-koodia tätä hyödyntämällä. Ensinnäkin, on hyvä muistaa, että tässä tapauksessa sovellus käyttää include - funktiota, jonka dokumentaatio kertoo meille:

The include expression includes and evaluates the specified file.

Eli kyseinen funktio sisällyttää annetun tiedoston ja evaluoi (suorittaa) annetun tämän. Tämä tarkoittaa, että jos annettu tiedosto sisältää PHP-koodia, niin koodi suoritetaan. Tämä ei pidä aina paikkansa, sillä kaikki funktiot, mitä sovellus voi käyttää tiedoston sisällyttämiseksi eivät välttämättä suorita koodia vaan ainoastaan palauttavat sen raakana sivulle. Mutta include-funktion tapauksessa, PHP-koodi suoritetaan.

Tyypillisesti tämän kaltaisissa tilanteissa, hyökkääjän seuraava askel olisi yrittää tallentaa sovellukseen PHP-koodia missä muodossa tahansa, kunhan se eksyy jollekin tiedostolle, jonka hyökkääjä voi sitten sisällyttää sivulle. Tämä voi tapahtua esimerkiksi manipuloimalla HTTP-pyyntöä, siten että PHP-koodia ajautuu palvelimen loki-tiedostoon, jonka hyökkääjä voi sisällyttää sivulle. Keinoja on useita ja ovat tässä tapauksessa lähinnä riippuvaisia hyökkääjän luovuudesta.

Yritetään seuraavaksi sisällyttää apache2 -palvelun loki-tiedosto vastaavalla tavalla. /etc/passwd tilalle asetamme /var/log/apache2/access.log, joka on tyyppillinen sijainti, missä apache2 palvelin tallentaa HTTP-pyynnöt, joita palvelimelle on tullut.

Onnistuimme sisällyttämään palvelun access.log tiedoston. Datasta näkee, että palvelu tallentaa yleistä tietoa HTTP-pyynnöstä sekä User-Agent-otsakkeen, joka HTTP-pyynnössä on ollut. Palvelun lokitus on täysin konfiguroitavissa, joten lokitettu tieto ei ole aina sama. On hyvä myös muistaa, että loki-tiedostojen sijainti on yhtä lailla konfiguroitavissa, eikä niiden löytäminen ole aina näin helppoa.

Hyökkäys tapahtuu seuraavanlaisesti. Teemme HTTP-pyynnön, jossa käytämme User-Agent otsaketta, joka sisältää PHP-koodia. Sitten sisällytämme loki-tiedoston samalla tavalla kuin äsken ja include -funktion pitäisi suorittaa koodimme.

Käytämme tähän curl-komentoa, mutta saman voi tehdä millä haluaa, esimerkiksi Burpilla.

curl -H "User-Agent: <?php echo passthru('ls -al'); ?>" https://www-8ean5fizui.ha-target.com

Sitten sisällytämme saman access.log -tiedoston. (huom. kuva on otettu sivun HTML-koodista, joka näyttää komennon tulosteen hieman selvemmin. Klikkaa oikealla hiiren painikkeella sivusta ja valitse View Page Source)

Voimme nyt lukea lipun cat /flag.txt. Voit hyvänä harjoituksena itsenäisesti yrittää luoda itsellesi paremman tavan syöttää komentoja, esimerkiksi tallentamalla sovellukseen oman PHP-skriptin, joka sallii komentojen syöttämisen parametreista.

hakatemia pro

Valmis ryhtymään eettiseksi hakkeriksi?
Aloita jo tänään.

Hakatemian jäsenenä saat rajoittamattoman pääsyn Hakatemian moduuleihin, harjoituksiin ja työkaluihin, sekä pääset discord-kanavalle jossa voit pyytää apua sekä ohjaajilta että muilta Hakatemian jäseniltä.