sql injection, exec e preg_replace filter

2

Sono stato informato che questo non è sicuro da usare per quanto riguarda l'iniezione sql:

preg_replace("/[\"'%()@$.!&?_: #\/-]/","", mysql_real_escape_string($_GET['var']));

quale sarebbe la differenza nel seguente cambiamento?

mysql_real_escape_string(preg_replace("/[\"'%()@$.!&?_: #\/-]/","", $_GET['var']));

Che ne dici se non è stata effettuata alcuna connessione al database, ad esempio è stato chiamato exec, come è stato possibile scavalcarlo? esempio di lavoro? un modo migliore per evitare l'iniezione?

$theVar = preg_replace("/[\"'%()@$.!&?_: #\/-]/","", mysql_real_escape_string($_GET['var']));
exec("zip -r archived.zip ./".$theVar."/");
    
posta quick_learner42 13.05.2013 - 04:57
fonte

3 risposte

1

Tutto dipende dal contesto in cui sono inseriti i dati forniti dall'utente.

Nel caso in cui non sia una stringa letterale SQL, mysql_real_escape_string sarebbe inutile in quanto non vi è alcuna stringa che l'utente malintenzionato deve interrompere fuori da e qualcosa di simile a UNION SELECT … con alcuni caratteri di spazi bianchi anziché lo spazio filtrato sarebbe ancora possibile.

Sfruttare l'esempio di exec è ancora più semplice:

var=;+evil+command;+cd+

Ciò comporterebbe:

zip -r archived.zip ./; evil command; cd /

Qui escapeshellarg potrebbe essere la corretta funzione di escape:

exec("zip -r archived.zip ".escapeshellarg("./".$theVar."/"));

Tuttavia, dovresti comunque convalidare $_GET['var'] anche se stai utilizzando escapeshellarg per assicurarti che il valore inserito sia quello che ti aspetti, ad esempio un percorso valido per il file system.

Spero che tu veda che non esiste alcuna funzione di escape o filtraggio universale. È sempre necessario tenere conto del contesto in cui verranno inseriti i dati forniti dall'utente. Ogni contesto può avere le proprie regole, caratteri speciali e sequenze di escape che devono essere gestite separatamente. Potrai persino incontrare più livelli di contesti che devono essere gestiti separatamente e nell'ordine corretto.

    
risposta data 13.05.2013 - 07:18
fonte
1

L'unico modo sicuro per proteggersi dall'iniezione SQL è l'utilizzo di query parametrizzate. Vedi: foglio Cheat di SQL Injection Prevention di OWASP .

    
risposta data 13.05.2013 - 05:41
fonte
1

Questa non è affatto l'iniezione SQL; non stai passando $theVar a un server SQL, ma a un comando shell. Pertanto, mysql_real_escape_string è inutile.

Devi utilizzare escapeshellarg , che applica lo stesso concetto a una stringa di shell.

In questo esempio,

$theVar = preg_replace("/[\"'%()@$.!&?_: #\/-]/","",  mysql_real_escape_string($_GET['var']));
exec("zip -r archived.zip ./".$theVar."/");

non stai sfuggendo ai caratteri di reindirizzamento < e & gt ;. Quindi (per esempio) è possibile sovrascrivere qualsiasi file a cui il processo che esegue zip ha accesso.

Peggio ancora, non stai sfuggendo al carattere del separatore del comando; . Quindi è possibile aggiungere comandi aggiuntivi (a patto che non utilizzino nessuno dei caratteri vietati) che verrà eseguito anche.

Un approccio migliore sarebbe vedere quali caratteri sono permessi in un nome file e accettare solo quelli, rifiutando qualsiasi stringa contenente caratteri proibiti. Se autorizzi i caratteri jolly (come te), espandi quelli stessi con glob() per ottenere un elenco di file e controlla quei file per le autorizzazioni e la posizione traducendo ciascun percorso in un percorso univoco canonico utilizzando realpath() .

Meglio ancora, non permettere i caratteri jolly. A quel punto sarebbe anche facile verificare se il file richiesto esiste effettivamente. I comandi della shell risulterebbero per lo più invalidi o inesistenti come nomi di file e saranno automaticamente rifiutati senza costi aggiuntivi.

    
risposta data 13.05.2013 - 08:50
fonte

Leggi altre domande sui tag