2011-12-19 14 views
8

Ho sentito dire (in relazione a C#/SQL Server, ma anche in relazione a PHP/MySql): Non sfuggire le stringhe manualmente: utilizzare le stored procedure invece.Perché mysql_real_escape_string() non dovrebbe evitare SQL Injection?

Ok, posso accettare questo suggerimento, ma perché? Molti dicono (anche su SO) mysql_real_escape_string() è abbastanza, mysql_real_escape_string() è buono, mysql_real_escape_string() è il primo modo di protezione.

Perché? C'è un caso in cui mysql_real_escape_string() può fallire? Almeno uno ... non ho bisogno di molti :)

+8

La più grande debolezza è che si può dimenticare di usarlo! –

+0

Troverete meno l'utilizzo delle stored procedure in MySQL che in SQL Server, ma l'uso di istruzioni preparate è solitamente quello che viene incoraggiato con le API PHP/MySQL. –

+1

Non ho mai avuto problemi con mysql_real_escape_string(). Penso che la gente dice di usare le procedure di archiviazione, invece, è perché c'è una possibilità di dimenticare di usare mysql_real_escape_String(). – Khronos

risposta

1

Solo per informazioni: mysql_real_escape_string() non sfugge % e _. Questi sono caratteri jolly in MySQL se combinati con LIKE, GRANT, or REVOKE.

3

ci sono due cose che possono andare male con mysql_real_escape_string:

  • Si può dimenticare di utilizzarlo
  • Se si sta utilizzando alcune codifiche di connessione multibyte specifici, ed è stato impostato queste codifiche con SET NAMES invece di mysql_set_charset come si conviene, si può ancora lasciare vulnerabili

Aggiornamento:

  • Sei al sicuro con UTF-8 (anche se questo non significa che si dovrebbe continuare a utilizzare SET NAMES!)
  • Per una spiegazione, vedere here
+0

Puoi darmi un esempio del secondo punto?Io uso SET NAMES con UTF8, e dovrebbe essere sicuro giusto? – markzzz

+0

@markzzz: vedere la risposta aggiornata – Jon

+0

Terza cosa: è possibile ricordarsi di usarlo, farlo quando non si trova tra virgolette. – Cheekysoft

0

mysql_real_escape_string()può non da pulire l'input. Poiché mysql_real_esacpe_string() tiene conto del set di caratteri durante la pulizia delle stringhe. C'è il problema. È possibile modificare il carattere tramite la funzione mysql_query inviando la query per modificare il set di caratteri della connessione. Tuttavia, mysql_real_escape_string() è ignaro del set che stai utilizzando e sfuggirebbe alcuni caratteri in modo improprio.

L'altra cosa la sta invocando costantemente manualmente. Anche avvolgendolo in una funzione è un P.I.T.A. poiché implica la necessità di creare una sorta di wrapper del database/livello di astrazione del database per poter automatizzare le chiamate a mysql_real_escape_string().

Ecco perché abbiamo PDO in PHP che ci aiuta ad alleviare tutto quanto sopra e si arriva a utilizzare istruzioni preparate parametrizzate che sono modo preferibile di occuparsi di query ripetute che alterano i dati.

Preparare la dichiarazione, associare le variabili di input e pulirà l'input in base al driver del database utilizzato e al set di caratteri della connessione. È meno codice e completamente sicuro.

+0

Niente è completamente sicuro, anche DOP. Cioè non ha alcun meccanismo per l'uso di nomi di tabelle e colonne come parametri, in modo tale che, in entrambi i casi, si utilizzi l'igienizzazione manuale per evitare iniezioni, anche con PDO. – brezanac

+0

@holodoc - se ci si trova nella necessità di associare i nomi di colonne e tabelle tramite PDO che implica che si ricevono nomi di colonne/tabelle dall'input degli utenti, il che implica inoltre che il modo in cui si sta facendo è semplicemente sbagliato. Altrimenti, se hai codificato i tuoi col./tables in una matrice del tuo DBAL, qual è la necessità di controllare ulteriormente se causano o meno un errore sql? DOP è perfettamente sicuro per il salvataggio degli input degli utenti. mysql_real_escape ha alcuni difetti e sono stati segnalati. –

+0

Perché utilizzare nomi dinamici di colonne e tabelle implica che questi vengano recuperati dall'input dell'utente? Ci sono molti casi in cui nominare i nomi di tabelle/colonne determinati dal semplice controllo del flusso. – brezanac

9

Quando mysql_real_escape_string FAIL:

$sql = "SELECT * FROM users WHERE id=" + mysql_real_escape_string($_GET['id']); 

Se $_GET['user_id'] è impostato su 1 OR 1 = 1, non ci sono caratteri speciali e non è filtrato.

Il risultato: Tutte le righe vengono restituite.

Si va peggio. Che ne dici di questo ... cosa succede se $_GET['user_id'] è impostato su 1 O is_admin = 1?

La funzione è progettata esclusivamente per essere utilizzata all'interno di apici singoli.

+0

Lo vedo così spesso in natura – Cheekysoft

+0

Sì! Di solito se aspetto un int, controllo prima se $ _GET ['user_id'] è int! Sì, certo che dovrei usare PDO per evitare questi controlli ... – markzzz

+0

ok, anche questo non funzionerà con PDO, comunque ......: O – markzzz

0

C'è solo una cosa su mysql_real_escape_string() e SQL Injection -

Il primo non hanno un minimo rispetto a quest'ultimo.

Anche se sembra paradossale, nulla può essere più vero.

Qui ci sono 2 dichiarazioni attestanti che

  1. Dovete fuggire solo stringhe tra virgolette, in quanto questa funzione aiuta a nient'altro.
  2. In effetti, è necessario sfuggire alla stringa ogni che si aggiunge alla query, anche quella più sicura. solo perché potrebbe contenere un carattere speciale e quindi interrompere la query (proprio come un incidente, non una trama malevola).

Pertanto, se applicabile, questa funzione deve essere comunque utilizzata, nonostante qualsiasi pericolo o paura. E in ogni altro caso non aiuterà nulla.

L'unica cosa che devo aggiungere è che le istruzioni preparate non offrono neanche protezione completa. Ecco la spiegazione e i consigli: https://stackoverflow.com/a/8255054/285587

Problemi correlati