File Inclusion â High
Om van het knippen-en-plakken-probleem af te zijn, stapt de ontwikkelaar over op een strengere aanpak.
1. Predict (Voorspel)â
De server controleert nu of de bestandsnaam aan strenge voorwaarden voldoet, anders gooit hij direct een foutmelding:
$file = $_GET['page'];
if( !fnmatch( "file*", $file ) && $file != "include.php" ) {
echo "ERROR: File not found!";
exit;
}
include($file);
Vraag: De bestandsnaam moet exact include.php heten, of beginnen met het woord file. Hoe kan dit ene woord file een onbedoelde achterdeur openzetten?
Antwoord
Op Linux en macOS bestaat het file://-protocol (net als http:// en ftp://). Dit protocol wordt gebruikt om in een browser naar lokale bestanden op de harde schijf te verwijzen. Omdat de ontwikkelaar eist dat de invoer begint met file, staat hij onbewust het gebruik van dit protocol toe â waarmee de volledige harde schijf uitgelezen kan worden.
2. Run (Uitvoeren)â
Start het lab en bevestig dat de normale pagina's werken.
Probeer ?page=file1.php en ?page=file2.php. Observeer dat dit werkt. Probeer daarna ?page=../../etc/passwd.
3. Investigate (Onderzoeken)â
Probeer verschillende payloads en kijk welke de "ERROR: File not found."-melding geven en welke door het filter komen.
Vraag: Welk patroon moet jouw payload hebben om door de fnmatch("file*", ...) check te komen? Welk protocol begint toevallig ook met het woord file?
Antwoord
De fnmatch("file*", $file)-check laat alles door dat begint met de vier letters f, i, l, e. Het file://-protocol begint precies met die letters en wordt dus door de check heen gelaten. Omdat include() ook het file://-protocol begrijpt, kun je het absolute pad van elk bestand op de server opgeven zonder ../ te hoeven gebruiken.
4. Modify & Make (Aanpassen & Maken)â
Bouw een payload die begint met het woord file en navigeer direct naar /etc/passwd.
Tip
Gebruik het file://-protocol en geef het absolute pad op vanuit de root van de harde schijf â je hoeft niet met ../ te werken.
Antwoord
Vul in de URL:
?page=file:///etc/passwd
Omdat de string netjes begint met "file", gooit het beveiligingsfilter het niet weg. De include()-functie leest vervolgens letterlijk het file-protocol uit en toont het wachtwoordenbestand.
5. â Wat moest je zien?â
- De pagina toont de inhoud van
/etc/passwdvia hetfile://-protocol. - De aanval met
../../etc/passwdgeeft nog steeds "ERROR: File not found." â de whitelist werkt voor dat patroon. - Het
file://-protocol is een blinde vlek in de whitelist-check.
Werkt het niet? Controleer of je drie slashes gebruikt: file:///etc/passwd (twee na file: en ÊÊn voor het absolute pad).