È sicuro reindirizzare al parametro URL senza filtrare?

7

Una pagina web reindirizza a un URL indicato nel parametro redirect senza filtrarlo, in questo modo:

$newURL=$_GET["redirect"];
header('Location: '.$newURL);

login.php?redirect=home.php

Se riecheggia l'input so che è possibile eseguire un attacco XSS, ma possiamo iniettare il codice quando è appena usato nel metodo di intestazione? È uno script sicuro?

    
posta Fast Snail 27.04.2016 - 02:54
fonte

4 risposte

9

La risposta breve

No. Questo non è sicuro e non dovrebbe essere fatto. In realtà, questo è l'ultimo di OWASP Top 10 :

A10. Unvalidated Redirects and Forwards

Web applications frequently redirect and forward users to other pages and websites, and use untrusted data to determine the destination pages. Without proper validation, attackers can redirect victims to phishing or malware sites, or use forwards to access unauthorized pages.

Phishing e diffusione di malware

Un utente malintenzionato può creare un URL per reindirizzare a qualsiasi pagina desiderata e quindi diffonderlo ovunque:

http://trusted.com/index.php?redirect=http%3A%2F%2Fmalicious.com

L'URL dannoso potrebbe essere offuscato per evitare il rilevamento da parte dell'utente tramite la codifica URL di tutti i caratteri in modo da ottenere una stringa come %68%74%74%70%3A%2F%2F%6D%61%6C%69%63%69%6F%75%73%2E%63%6F%6D .

Ora un utente che fa clic su quello che sembra un normale collegamento sicuro al tuo sito può finire ovunque:

  • Su un sito che sembra esattamente come il tuo, chiedendo nome utente e password. Boom, account rubati.
  • Un sito che diffonde malware in base al download. Potresti provare a sostenere che questo non è un tuo problema, dal momento che tecnicamente non è il tuo sito che lo diffonde. Non sono sicuro che la vittima sarebbe d'accordo.
  • Qualsiasi cosa. Vuoi che gli utenti facciano clic sui link al tuo sito e finiscano con contenuti illegali o NSFW o NSFL?

Se questo viene fatto dopo che l'utente ha effettuato l'accesso, come suggerito nella domanda, è ancora più pericoloso dal momento che in realtà nella tua pagina l'inserimento delle credenziali rafforza la convinzione degli utenti che è effettivamente sul tuo sito. Sarebbe così semplice pubblicare un tipo di pagina "password errata, riprova" dopo l'accesso.

Iniezione di intestazione

Come già affermato da Steffen Ullrich nella sua risposta a questa domanda ea me in questo risponde a un'altra domanda, su versioni di PHP precedenti alla 5.1.2 che potrebbero essere utilizzate per l'header header.

Che cosa fare invece

Whitelist o convalida

Come spesso accade, la soluzione è fare da whitelist. Ecco un esempio di PHP:

$param = $_GET["redirect"];
$allowed = array(
    "index" => "index.php",
    "blog"  => "blog/index.php",
    // ...and so on...
);
$redirect = isset($allowed[$param]) ? $allowed[$param] : "index.php";
header('Location: '.$redirect);

Questo sarà noioso se ci sono molte pagine a cui vuoi essere in grado di reindirizzare. A seconda dell'aspetto dei tuoi URL, puoi convalidare gli URL per il tuo sito. Ad esempio se sono nella forma http://trutsted.com/?pageid=1234 puoi accettare solo il paginato da reindirizzare e verificare che sia effettivamente numerico.

Controllo Referente

Se desideri che i collegamenti di reindirizzamento funzionino dal tuo sito, puoi controllare l'intestazione del referer HTTP della richiesta. Questo potrebbe incorrere in alcuni problemi se pubblichi il tuo sito su HTTP e HTTPS, poiché se si collega da una pagina HTTP a una pagina HTTPS l'intestazione del referente non verrà inviata.

Ecco alcuni esempi di codice:

$headers = apache_request_headers();
$referer = isset($headers['referer']) ? parse_url($headers['referer'], PHP_HOST) : "";
if($referer == "trusted.com") {
    //Do the redirect. If you want your code to be safe on old PHP versions,
    //you will need to filter out newlines or just URL encode the URL.
}
else {
    //Inform the user of the problem or just redirect to your index page.
}

Altre letture

  • OWASP cheat sheet su reindirizzamenti non convalidati. (Uno degli esempi su come non farlo qui è quasi identico a come l'hai fatto nella tua domanda.)
  • Troy Hunt ha un grande contributo su questo argomento.
risposta data 27.04.2016 - 10:22
fonte
5

Le versioni correnti di PHP rilevano e prevengono le iniezioni newline nella funzione di intestazione, vedi Come evitare l'intestazione HTTP Header (caratteri di nuove righe) . Nelle versioni precedenti di PHP potresti probabilmente fare qualcosa di simile a

 login.php?redirect=%0D%0A%0D%0A<script>...

Quale potrebbe uscire dall'intestazione e risultare in

 Location:

 <script>...

E il tuo script potrebbe quindi fare tutto ciò che desidera, compreso l'accesso e l'inoltro dei cookie di sessione per il dirottamento di sessione.

Questo non significa che il tuo script sia sicuro con PHP corrente. Il reindirizzamento a URL arbitrari non è mai una buona idea quindi è necessario limitare newURL agli URL previsti per il reindirizzamento.

    
risposta data 27.04.2016 - 09:03
fonte
2

Da aggiungere a ciò che altri hanno detto:

Se hai un insieme di URL noti da reindirizzare a (che potresti mappare a un identificatore), sarebbe molto meglio consentire solo gli identificatori conosciuti nel valore del parametro "reindirizzamento". Quindi puoi mappare l'identificatore al tuo URL sicuro e conosciuto.

Grazie a questa tecnica "tutti i tuoi problemi" vanno via.

Ovviamente se il valore dell'URL è arbitrario al 100% per i tuoi utenti, o se non hai l'insieme di tutti gli URL possibili, allora questo non può essere applicato. Ma se il tuo URL corrisponde a pagine conosciute su cui hai il controllo, fallo!

    
risposta data 27.04.2016 - 09:33
fonte
1

La prima vulnerabilità che riesco a pensare è passare un URL completo come argomento che reindirizzerà l'utente a una copia falsa del sito ( login.php?redirect=http://malicious.com )

A parte questo, sono sicuro che ci sono diversi modi per prevenire il reindirizzamento e visualizzare invece HTML / JavaScript malevoli.

Come regola generale, qualsiasi parametro URL dovrebbe essere disinfettato.

    
risposta data 27.04.2016 - 04:55
fonte

Leggi altre domande sui tag