PHP - Come fare un filtraggio sicuro degli input alla luce delle vulnerabilità di codifica multibyte?

8

Da giorni cerco di capire come scrivere un'applicazione web sicura in PHP, e risulta essere particolarmente difficile. Più leggo, più affondo in profonde paludi piene di vulnerabilità che non sono menzionate da persone gentili come Matt Robinson o Chris Shiflett .

Per alcuni esempi, prendi:

  • link
  • link
  • Vedi anche il consumo di personaggi come nella risposta di Rook

In breve, vedo i seguenti problemi:

  • Quando si filtra l'input, non è molto chiaro in che modo i dati verranno decodificati successivamente, e quindi i sistemi di codifica e di escape dei caratteri possono bypassare il filtraggio degli input. (come la decodifica con doppio url)
  • Durante l'escape dell'output, vengono utilizzate funzioni standard come htmlspecialchars . È bello che htmlspecialchars abbia un parametro di codifica, tuttavia ciò non impedisce di inviare input UTF-16 ad esso, e ciò potrebbe probabilmente rompere il valore di sicurezza della funzione.

Sembra che ci sia un modulo mbstring in php, ma se è vagamente sicuro quanto la documentazione è comprensibile, allora probabilmente sarà inutile anche se riuscirò a capire come usarlo. Solo un esempio dei documenti per l'illustrazione :

mbstring.strict_detection boolean

    Enables the strict encoding detection.

Ottimo, è utile.

Sfortunatamente le funzioni dipendono anche da cosa hai impostato nelle opzioni di configurazione ... Sembra esserci una funzione chiamata mb_convert_encoding , ma i documenti non dicono nulla sull'aspetto sicurezza e sembra che tu debba conoscere la codifica in ingresso (una zona di non sicurezza per la sicurezza). C'è anche mb_check_encoding . Il che sembra essere pensato per la pulizia, ma leggere i commenti degli utenti sui documenti non ispira esattamente la fiducia.

Quindi la domanda è, alla luce di tutto ciò, come fai il filtraggio sicuro degli input ? Qualcosa di simile?

  1. mb_convert_encoding a utf-8
  2. mb_check_encoding per rifiutare l'input non valido
  3. loop url_decode finché la stringa non smette di cambiare
  4. Esegui il normale filtraggio degli input con confronto e regex di testo, ecc ...

modifica: si noti che 3 è problematico perché il normale filtro di input potrebbe introdurre di nuovo entità che possono essere decodificate con URL

modifica
Ho trovato una risposta parziale qui , da Shiflett. Sembra che per htmlspecialchars che utilizza il suo parametro di codifica e assicurandosi di impostare l'intestazione di codifica dei caratteri per il browser sullo stesso, si eviti che il browser interpreti i caratteri in modo diverso rispetto a htmlspecialchars. Tutto ciò presuppone che l'input di htmlspecialchars sia valido per la codifica data o che per ogni possibile input non valido htmlspecialchars interpreti la stringa esattamente nello stesso modo di ogni browser. Sappiamo che se non troviamo alcun modo di sanificare il nostro input non possiamo garantire che l'input di htmlspecialchars sia codificato validamente, perché un utente malintenzionato potrebbe preparare una stringa con codifica non valida. Questo ci porta alla seconda possibilità, che htmlspecialchars si comporti come il browser identico per tutti i possibili input. Questo è un problema, dal momento che non possiamo usare lo stesso tokenizer per l'escape e l'utilizzo, dal momento che uno accade sul server e uno accade nel browser.

Questo è tutto simile a ciò che msql_real_escape fa per un database, anche se penso che tu possa risolvere correttamente questo problema per msql usando invece istruzioni preparate.

Un terzo output problematico è il filesystem quando si utilizza php per caricare file o altre manipolazioni del file system. A proposito di quest'ultimo sembra che ci siano pochissime informazioni disponibili. Non conosco nemmeno una funzione di escape specifica, per non parlare di una che è robusta quando riceve input distorti.

    
posta 14.05.2012 - 18:56
fonte

3 risposte

10

Al fine di montare una difesa adeguata contro una minaccia è necessario capirlo. Schemi di codifica con strati chiari è molto pericoloso in quanto ciò può introdurre un problema quando, di default, questo di solito non è un problema. In generale, i problemi di sicurezza legati alla codifica derivano dal fatto che le funzioni di escape possono agire su dati in modo diverso da come sono interpretati. Ma non è l'unica preoccupazione, può anche confondere il programmatore nel fatto che pensano che una stringa sia sfuggita, quando non lo è.

La prima preoccupazione è che le funzioni di escape possono creare stringhe pericolose per l'utente malintenzionato .

mysql_real_escape_string () è una funzione speciale che sa quale tipo di codifica sta usando il database e ne regola l'escaping per seguirne l'esempio. Lì non può esserci mai una disconnessione tra il metodo di codifica, la funzione di fuga e l'interprete. Semplicemente usando addslashes() può essere molto pericoloso per questo motivo.

Come esempio si usa 0xbf27 , che è un singolo carattere GBK. addslashes() non capisce GBK, capisce solo ASCII. Se questa stringa interpretata come ASCII, il primo carattere sarebbe 0xbf, che è un carattere ASCII non stampabile, consente di chiamare ¿ . Il secondo carattere ASCII è 0x27 che è una virgoletta singola ' . Dopo addslashes () 0xbf27 diventa 0xbf5c27 o se è stampato in ASCII sarebbe ¿\' . Il problema è che 0xbf5c è un carattere GBK valido, quindi addslashes () ha trasformato un carattere multi-byte in 2 caratteri, uno dei quali è una citazione singola. Un altro modo di pensare a questo è che la barra retroversa è consumata dalla codifica GBK.

Il consumo di caratteri può essere un problema senza funzioni di escape . Consente di utilizzare SHIFT-JS e HTML come esempio. Questo esempio è stato preso da The Tangled Web :

<img src="http://fuzzybunnies.com/0xEO">...thisisstillapartofthemarkup..." onerror="alret('this will execute!')"
<div>
...the page continues...

In questo caso il "> alla fine del tag img è un carattere di controllo molto importante che sta consumando . Il " viene utilizzato dallo schema di codifica e quindi > e qualche altro testo sembrano appartenere all'attributo src HTML, non finché non raggiunge il " onerror che l'attributo è terminato.

... Ma non è tutto. Consente di cambiare marcia un po '. Che dire di urldecode() ?

<?php
$id=mysql_real_escape_string($_GET['id']);
$id=urldecode($id);
mysql_query("select * from user where id='".$id."'");

Vedi la vulnerabilità? Dalla mia esperienza la maggior parte dei programmatori PHP non la vede. Il problema è che urldecode() può essere usato per costruire una stringa vulnerabile, diciamo che l'autore dell'attacco ha fornito una stringa come http://localhost/vuln.php?id=%2527 or sleep(30)-- . Beh, quasi ogni piattaforma di applicazioni Web eseguirà automaticamente un urldecode su tutti gli input HTTP. Quindi il contenuto di $ _GET ['id'] è in realtà %27 or sleep(30)-- Questo perché% 25 è stato decodificato in % (% è esadecimale 25). Dopo mysql_real_escape_string() o anche addslashes() il valore è ancora solo %27 or sleep(30)-- Dopo aver eseguito nuovamente urldecode (), il contenuto di $id è ora ' or sleep(30)-- , che è pericoloso.

Quindi, come suggerimento di un hacker, quando sto verificando un codice base che utilizza magic_quotes_gpc o qualcosa di simile, grep però il codice cercando decode funzioni , come urldcode() , htmlspecialchars_decode() , base64_decode() e funzioni simili. Anche se l'applicazione esegue addslashes () ciecamente su tutti gli input, una funzione di decodifica consentirà all'utente malintenzionato di costruire la sua stringa di attacco.

Quindi come difendi te stesso? Bene prova il tuo codice. Alcuni scanner di applicazioni Web testeranno per errori di codifica esattamente come questo. In effetti, ho ricercato questo argomento mentre lo sviluppo di uno scanner vulnerabile . Un altro punto, l'input sempre igienizzato al momento dell'utilizzo, evita il problema della decodifica dell'elusione dopo . Non puoi sapere come verrà utilizzato, quindi codificare / decodificare / sfuggire tutto sarà sempre imperfetto. Query parametrizzate utilizzate per la creazione di istruzioni SQL. UTF-8 è un ottimo default nella maggior parte dei casi (ma non sempre), e * la maggior parte * di questi problemi non si presentano con questo schema di codifica muli-byte. / p>     

risposta data 15.05.2012 - 04:45
fonte
2

No, non consiglio l'approccio che hai citato.

Prima di tutto, lasciami fare il backup. Concettualmente, forse l'approccio più sicuro consiste nell'applicare una combinazione di convalida dell'input ed escaping dell'output. Convalida dell'input significa che definisci quale sia la forma degli input attesi / buoni e controlla che gli input abbiano quella forma. L'escaping dell'output significa che si escono le uscite, in base al contesto in cui verranno consumate. La convalida degli input viene generalmente eseguita per gli input non appena li ricevi; L'escaping dell'output avviene generalmente alla fine, prima di inserire un valore in un documento HTML o altro output.

Per informazioni generali sui concetti di convalida dell'input e dell'output dell'output, oltre a suggerimenti sull'implementazione, OWASP ha alcune risorse eccellenti. Vedi anche questa domanda: Filtra l'input dell'utente prima del database o sul display? , per ulteriori informazioni sui concetti.

Per eseguire la convalida dell'input, penso che definirei una whitelist di caratteri consentiti o un'espressione regolare che caratterizzi l'input previsto e che l'input corrisponda a questa espressione regolare / lista bianca. (Una lista bianca appropriata dovrebbe occuparsi di problemi relativi a codifiche di input divertenti.) In alcuni casi un altro modo per eseguire la convalida dell'input consiste nel trasmettere l'input a un tipo specifico, ad esempio (int) . La funzione di convalida specifica dipenderà dal tipo e dal formato dell'input; non è possibile utilizzare un validatore valido per tutte le dimensioni.

Per eseguire l'escapizzazione dell'output, ti consiglio di utilizzare una libreria di escape, come OWASP ESAPI. È necessario comprendere i diversi contesti di analisi in cui possono essere visualizzati i valori e quindi utilizzare la funzione di escape corretta per il contesto di analisi. Ad esempio, htmlspecialchars() è una funzione di escape appropriata per i valori dinamici che verranno inseriti in un documento HTML tra tag, ma non è appropriato per un URL (per gli URL, devi anche controllare che il protocollo sia valido). OWASP ESAPI offre una suite di funzioni di escape per i contesti più comuni in cui potresti inserire dati in output.

Assicurati di usare dichiarazioni preparate. Non creare query SQL tramite concatenazione di stringhe.

Detto questo, il supporto di PHP per la sicurezza è debole. Molti altri moderni framework di programmazione web offrono un maggiore supporto per la sicurezza, ad esempio fornendo un sistema di template con auto-escape sensibile al contesto , fornendo supporto automatico per i token CSRF, gestione sicura delle sessioni, accessi utente, un ORM del database e così via.

Vedi anche Attacchi di sicurezza su applicazioni Web PHP , Quali caratteristiche di sicurezza dovrebbe avere un framework PHP? , È strip_tags () orribilmente pericoloso? , Quali sono alcuni buoni strumenti gratuiti per eseguire controlli di sicurezza automatizzati per il codice PHP? , Come eseguire un controllo di sicurezza per un'applicazione PHP? , Perché la gente dice che PHP è intrinsecamente insicuro? .

    
risposta data 16.05.2012 - 03:02
fonte
0

Sono giunto alla conclusione di usare:

$input = mb_convert_encoding( $input, 'UTF-8' );

Per disinfettare la codifica dei caratteri prima di eseguire qualsiasi altra operazione, come la convalida dell'input e l'escaping dell'output. Probabilmente dovrò esaminare il codice sorgente per mb_convert_encoding e i test delle unità per assicurarmi che sia sicuro, ma ho l'impressione che restituisca sempre una stringa UTF-8 valida.

Il resto della mia applicazione userà utf-8 durante il quale eviterà che qualsiasi cosa venga interpretata in modo diverso, fino al browser.

    
risposta data 29.09.2015 - 11:59
fonte

Leggi altre domande sui tag