template - w3school php exercises




Prevenire l'attraversamento di directory in PHP, ma permettendo percorsi (4)

Ho un percorso di base / qualunque / foo /

e $_GET['path'] dovrebbe essere relativo ad esso.

Tuttavia, come posso ottenere questo risultato (leggendo la directory), senza consentire l'attraversamento della directory?

per esempio.

/\.\.|\.\./

Non filtrerà correttamente.


Bene, un'opzione potrebbe essere quella di confrontare i percorsi reali:

$basepath = '/foo/bar/baz/';
$realBase = realpath($basepath);

$userpath = $basepath . $_GET['path'];
$realUserPath = realpath($userpath);

if ($realUserPath === false || strpos($realUserPath, $realBase) !== 0) {
    //Directory Traversal!
} else {
    //Good path!
}

Fondamentalmente, realpath() risolverà il percorso fornito a un percorso fisico fisico effettivo (risolvendo i collegamenti simbolici, .. , . , / , // , ecc.). Quindi, se il percorso dell'utente reale non inizia con il percorso di base reale, sta cercando di fare un attraversamento. Si noti che l'output di realpath non avrà alcuna "directory virtuale" come . o .. ...


Immagino tu voglia dire senza permettere agli utenti di attraversare la directory sì?

Se stai cercando di impedire al tuo PHP di attraversare la directory, dovresti semplicemente far funzionare correttamente il php.

Quello che ti serve per fermare gli utenti è un file .htaccess modificato ...

Options -Indexes

(Tutto questo presuppone che tu stia parlando di utenti)


Non è sufficiente controllare modelli come ../ o simili. Prendi "../" per esempio quale URI codifica su "% 2e% 2e% 2f". Se il tuo pattern check viene eseguito prima di una decodifica, ti mancherà questo tentativo di attraversamento. Ci sono altri trucchi che gli hacker possono fare per aggirare un controllore di pattern, specialmente quando si utilizzano stringhe codificate.

Ho avuto il maggior successo fermandoli canonicalizzando qualsiasi stringa di percorso sul suo percorso assoluto usando qualcosa come realpath () come suggerisce ircmaxwell. Solo allora comincio a verificare gli attacchi traversali confrontandoli con un percorso di base che ho predefinito.


Potresti essere tentato di provare a usare regex per rimuovere tutti ../s ma ci sono alcune funzioni piacevoli integrate in PHP che faranno un lavoro molto migliore:

$ page = basename (realpath ($ _ GET));

basename - rimuove tutte le informazioni di directory dal percorso, ad esempio ../pages/about.php diventerebbe about.php

realpath - restituisce un percorso completo al file, ad esempio about.php diventerebbe /home/www/pages/about.php, ma solo se il file esiste.

Combinati restituiscono solo il nome del file ma solo se il file esiste.





directory-traversal