2010-11-17 5 views

risposta

0

Suppongo che intendi senza consentire agli utenti di di attraversare la directory sì?

Se si sta tentando di impedire al proprio PHP di attraversare la directory, è sufficiente attivare correttamente il php.

Quello che vi serve per impedire agli utenti è un file .htaccess modificato ...

Options -Indexes 

(Tutto questo presuppone che si sta parlando di utenti)

+0

MainMa ha capito cosa sto cercando di ottenere. – Johnny

+0

Fa comparire '$ _GET', è chiaro che sta cercando di impedire un attacco di directory trasversale da parte di hacker, quindi per favore non dire" dovresti semplicemente far funzionare correttamente il php in primo luogo ". – FluorescentGreen5

93

Bene, una possibilità sarebbe quella di confrontare il vero percorsi:

$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 effettivo disco fisico (risolvere simbolici, .., ., /, //, ecc.). Quindi se il percorso dell'utente reale non inizia con il percorso di base reale, sta tentando di eseguire un attraversamento. Si noti che l'uscita del realpath sarà non avere alcun "directory virtuali" come . o .. ...

+2

L'unico modo corretto di farlo .. –

+0

Editor: strpos è già sicuro multi-byte. Introdurre l'alternativa mb potrebbe introdurre altre vulnerabilità ... – ircmaxell

+1

E i collegamenti simbolici? O se il file che vogliamo controllare non esiste ancora? (cioè creando un nuovo file in un percorso futuro). – Petah

4

non è sufficiente per verificare la presenza di 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.

12

La risposta di ircmaxell non era completamente corretta. Ho visto questa soluzione in diversi frammenti ma ha un bug relativo all'output di realpath(). La funzione realpath() rimuove il separatore di directory finale, quindi immaginate due directory contigue quali:

/foo/bar/baz/ 

/foo/bar/baz_baz/ 

Come realpath() sarebbe rimuovere l'ultimo separatore di directory, il metodo sarebbe tornato "buona strada", se $_GET['path'] è stato pari a" ../ Baz_baz", come sarebbe qualcosa di simile

strpos("/foo/bar/baz_baz", "/foo/bar/baz") 

Forse:

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

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

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

Che cosa fa "strcmp" nel codice? – Andrew

1

Si può essere tentati di provare ed usare espressioni regolari per rimuovere tutte le ../s ma ci sono alcune funzioni belle integrate in PHP che farà un lavoro molto migliore:

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

basename - strisce tutte le informazioni di directory dal percorso ad es ../pages/about.php sarebbe diventato circa .ph p

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

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

+0

Non penso che questo impedisca di attraversare! – Gerfried