it-swarm-eu.dev

Iniezione SQL: perché le quotazioni di escape non sono più sicure?

SQL non elaborato

Quando stai scrivendo SQL - per tutto ciò che prende davvero l'input umano, sono state fatte molte cose per evitare l'iniezione.

Tutti quelli che hanno sentito parlare di SQL injection sanno che (userò PHP come esempio) fare qualcosa del genere non è sicuro:

$sql = "SELECT * FROM `users` 
.  WHERE `userName` = "{$_POST["username"]}" 
.  AND `pass` = "{$_POST["pass"]}";";

Magia

Quindi, naturalmente, qualcuno è venuto fuori con l'idea di usare "citazioni di evasione magica" per gestire l'input del programma che non è stato disinfettato correttamente e messo direttamente in sql a causa di cattive pratiche. Questo non risolveva davvero il problema con SQL injection, ma significava che tutti gli input dell'utente erano stati alterati.

Aggiunta di barre

Quindi, alcune persone hanno disattivato le citazioni magiche. Quindi, hanno analizzato l'input dell'utente prima del punto di SQL attraverso addslashes() che in teoria sfugge a tutte le virgolette e il tuo hacker non può fare ' OR 1=1, Ma anche la documentazione per addlash è di per sé che non dovresti usare gli addlash, dice che usa la funzione specifica del database come mysql_real_escape_string(), ma questo è ancora detto che non è abbastanza per alcuni.

Aggiunta di barre specifiche per il database

Quindi, non possiamo usare *_real_escape_string Specifico per DBMS, non possiamo usare add slashes, La cosa "citazioni magiche" ha causato molti problemi e il web è pieno di citazioni brevi come :

"Un hacker dedicato troverà un modo per saltare attraverso i tuoi loop che evitano le virgolette, basta usare le istruzioni preparate da DBAL" - John Q qualsiasi programmatore

Ok, questo mi ha spaventato abbastanza da usare le istruzioni di preparazione e un DBAL. Non ha davvero spiegato nulla, ma suona bene perché l'ho sentito molto.

Dichiarazioni preparate

Quindi ora stiamo usando PDO, o un DBAL da un framework, o qualcos'altro che avvolge tutto il nostro sql e si assicura che qualcuno non possa eseguire un'iniezione di sql.

La mia domanda è fondamentalmente un "perché no?", Non un "cosa dovrei usare?". Il Web è pieno di persone che ti dicono di usarlo o di usarlo o qualunque , ma nessuna spiegazione del perché queste cose debbano accadere.

Domande dirette

Domande mirate (promemoria, sto chiedendo di SQL, PHP era un linguaggio di esempio a causa della sua cattiva reputazione su SQL, i concetti sono universali):

  1. Perché non possiamo sfuggire a tutti gli input dell'utente usando "magic"?
  2. Perché gli addlash non sono stati "abbastanza buoni"?
  3. Cosa c'è di sbagliato nell'utilizzo delle funzioni di escape specifiche per DB, e perché era meglio delle addlash?
  4. Perché le dichiarazioni preparate con framework e DOP vengono accolte come il gold standard di SQL? Perché stanno meglio? Perché non posso fare un'iniezione SQL con questi, dove potrei avere con i mezzi precedentemente menzionati? Un programmatore non può in qualche modo riuscire a rovinarlo ancora? Cosa dovrebbero cercare?
  5. Altre preoccupazioni che non ho sollevato?
78
Incognito

Perché non possiamo sfuggire a tutti gli input dell'utente usando "magic"?

Al momento dell'applicazione della magia, non è noto dove finiranno i dati. Quindi le citazioni magiche stanno distruggendo i dati che, a meno che non siano scritti senza caratteri di escape in un database.

Può essere utilizzato solo nella risposta HTML inviata al client. Pensa a un modulo che non è stato compilato completamente e che viene quindi mostrato di nuovo all'utente. Con le virgolette magiche, i dati immessi al primo tentativo saranno ora sottoposti a escape SQL, il che non ha senso su una pagina HTML. Ancora peggio: al secondo invio i dati vengono nuovamente sottoposti a escape in SQL.

Perché gli addlash non sono stati "abbastanza buoni"?

Ha problemi con i caratteri multibyte:

' 27
\ 5c
뼧 bf 5c

Sono due byte, ma solo un carattere Unicode.

Poiché addslashes non sa nulla di Unicode, converte l'input bf 27 per bf 5c 27. Se viene letto da un programma compatibile con Unicode, viene visualizzato come 뼧 '. Boom.

C'è una buona spiegazione di questo problema su http://shiflett.org/blog/2006/jan/addslashes-versus-mysql-real-escape-string

Cosa c'è di sbagliato nell'utilizzo delle funzioni di escape specifiche per DB, e perché era meglio delle addlash?

Sono migliori perché assicurano che l'escaping interpreti i dati nello stesso modo del database (vedi l'ultima domanda).

Dal punto di vista della sicurezza, vanno bene se li usi per ogni singolo input del database. Ma hanno il rischio che tu possa dimenticare uno dei due da qualche parte.

Modifica : Come aggiunto getahobby: O che usi xxx_escape_strings per i numeri senza aggiungere virgolette attorno a loro nell'istruzione SQL e senza assicurarti che siano numeri reali trasmissione o conversione dell'input nel tipo di dati appropriato /Modifica

Dal punto di vista dello sviluppo software sono dannosi perché rendono molto più difficile aggiungere il supporto per altri software del server di database SQL.

Perché le dichiarazioni preparate con framework e DOP vengono accolte come il gold standard di SQL? Perché stanno meglio?

DOP è principalmente una buona cosa per motivi di progettazione del software. Rende molto più semplice supportare altri software per server database. Ha un'interfaccia orientata agli oggetti che risolve molte piccole incompatibilità specifiche del database.

Perché non posso fare un'iniezione SQL con queste [istruzioni preparate], dove potrei avere con i mezzi precedentemente menzionati?

La parte " query costante con parametri variabili " delle istruzioni preparate è ciò che è importante qui. Il driver del database sfuggirà automaticamente a tutti i parametri senza che lo sviluppatore debba pensarci.

Le query con parametri sono spesso più facili da leggere delle query normali con parametri di escape per motivi sintattici. A seconda dell'ambiente, potrebbero essere un po 'più veloci.

Usare sempre istruzioni preparate con parametri è qualcosa che può essere validato da strumenti di analisi del codice statico . Una chiamata mancante a xxx_escape_string non viene individuata in modo facile e affidabile.

Un programmatore non può in qualche modo riuscire a rovinare tutto? Cosa dovrebbero cercare?

Le "dichiarazioni preparate" implicano che sono costante . La generazione dinamica di istruzioni preparate, in particolare con l'input dell'utente, presenta ancora tutti i problemi di iniezione.

52

[1.] Perché non possiamo sfuggire a tutti gli input dell'utente usando "magic"?

Perché le virgolette magiche sono spezzate per due motivi:

  1. Non tutti i dati $ _ (REQUEST/GET/POST) vanno nel DB. E per avere un senso, devi sfuggire all'input.
  2. Sono l'equivalente addslashes (vedi la mia nota su [2.]), quindi non sono effettivamente sicuri.

[2.] Perché gli addlash non sono stati "abbastanza buoni"?

Esistono molti modi per uscire dalla restrizione addslashes, pertanto è fondamentalmente imperfetto, tuttavia si tenta di utilizzarlo.

[3.] Cosa c'è che non va nell'uso delle funzioni di escape specifiche per DB, e perché è stato meglio delle aggiunte?

Niente. Questo è semplicemente il mantra sul perché DOP/preparati sono "migliori". Sono way meglio di addslashes poiché si prendono cura di molti fattori, inclusa la codifica. Ecco un piccolo segreto; PDO li usa internamente, ma non addslashes...

[4.] Perché le dichiarazioni preparate con framework e DOP vengono accolte come il gold standard di SQL? Perché stanno meglio? Perché non posso fare un'iniezione SQL con questi, dove potrei avere con i mezzi precedentemente menzionati?

Sono non il gold standard, sono non "più" sicuri delle funzioni specifiche del DB e tu puoi fare SQL injection con questi anche. E no, non è possibile eseguire l'iniezione SQL con input adeguatamente disinfettati.

Come per tutte le tecnologie là fuori, gli sviluppatori tendono a sviluppare tendenze religiose (fanatiche?) Per qualcosa di "nuovo". Questo è il motivo per cui vieni avvisato degli ingegneri certificati Zend (TM) esperti, non obbligandoti a passare a dichiarazioni preparate.

La realtà, tuttavia, è che tutto dipende dal sapere cosa stai facendo. Se stai caricando un articolo con il suo ID numerico, non hai bisogno di alcun tipo di escape, anche meno DOP. Devi semplicemente assicurarti che l'ID sia effettivamente un numero intero.

Da una prospettiva più realistica, la regola generale non è di usare le istruzioni DOP/preparate, ma di usare le giuste funzioni, vale a dire devi usa mysql_real_escape_string() invece di addslashes() o mysql_escape_string().

[5.] Un programmatore non può in qualche modo riuscire a rovinare tutto? Cosa dovrebbero cercare?

Ovviamente! Ma non è "cosa cercare" ma piuttosto "sapere cosa stai facendo".

Vedete, eval($_GET['code']) * è del tutto legittimo se usato nel posto giusto (come un local PHP Test Runner).

Se si utilizza un ORM per eseguire una query condizionale, si immette il codice direttamente, quindi potrebbe esserci la possibilità di ottenere l'iniezione SQL se non lo si esegue correttamente (dipende dall'ORM in questione). Esempio (ipotetico):

// update() sets the value of a column given a condition
//
//                         .--escaping is automatic here
//                         |                           .--hypothetical SQL injection
//                         v                           v
Db()->update('name',$_GET['newname'])->where(' id = '.$_GET['id']);

(* Posso solo immaginare gli innumerevoli professionisti sbattere la testa su questo)

13
Christian

Alla fine della giornata, è necessario evitare l'eventuale input per proteggere le query da SQL Injection. Le librerie di query parametrizzate come PDO e ADODB usano l'escaping , tutto ciò che fanno è applicare questa pratica in modo implicitamente sicuro. Secondo constrast magic_quotes_gpc [~ # ~] non [~ # ~] , questo è un approccio fondamentalmente errato al problema.

1) L'evasione può essere problematica se non capisci cosa stai facendo. Questo tipo di problema è ancora sfruttabile se magic_quotes_gpc è abilitato.

mysql_query("select * from users where id=".addslashes($_GET[id]));

Exploit PoC: http: //localhost/vuln.php? Id = sleep ( )

patch:

mysql_query("select * from users where id='".addslashes($_GET[id])."'");

Lezione: Non hai bisogno di virgolette per sfruttare l'iniezione sql.

2) Diciamo che eviti solo le virgolette:

mysql_query("select * from users where name='".htmlspecialchars($_GET[name],ENT_QUOTES)."' and id='".htmlspecialchars($_GET[id],ENT_QUOTES)."'");

Sfruttamento PoC: http: //localhost/vuln.php? Name = \& id = + o + sleep (30)/*

Patch:

mysql_query("select * from users where name='".addslashes($_GET[name])."' and id='".addslashes($_GET[id])."'");

Lezione : Le barre rovesciate sono ugualmente pericolose come virgolette.

3) Che dire della codifica del linguaggio?

mysql_query("SET CHARACTER SET 'gbk'");
mysql_query("select * from user where name='".addslashes($_GET[name])."'");

Exploit PoC: http: //localhost/vuln.php? Name =% bf% 27 = sleep (30)/*

Patch:

mysql_query("SET CHARACTER SET 'gbk'");
mysql_query("select * from user where name='".mysql_real_escape_string($_GET[name])."'");

Conclusione:

L'escaping è assolutamente necessario per prevenire l'iniezione sql in un'applicazione. In PHP PDO e ADOB sono ottime librerie di query parametrizzate che impongono la fuga dell'input dell'utente. Il problema è che molti programmatori non capiscono cosa sia la fuga. Avere una libreria per applicare questa politica di sicurezza è il miglior metodo di difesa, perché non è necessario comprendere le regole di fuga.

9
rook

Informazioni sulle funzioni di escape specifiche del DB. Esistono molti scenari in cui può verificarsi l'iniezione SQL, anche se è stato utilizzato mysql_real_escape_string (). LIMIT e ORDER BY sono davvero complicati!

Questi esempi sono vulnerabili all'iniezione SQL:

$offset = isset($_GET['o']) ? $_GET['o'] : 0;
$offset = mysql_real_escape_string($offset);
$sql = "SELECT userid, username FROM sql_injection_test LIMIT $offset, 10";

o

$order = isset($_GET['o']) ? $_GET['o'] : 'userid';
$order = mysql_real_escape_string($order);
$sql = "SELECT userid, username FROM sql_injection_test ORDER BY `$order`";

In entrambi i casi non puoi usare 'per proteggere l'incapsulamento.

fonte : l'inaspettata SQL Injection (quando l'escaping non è abbastanza) <- Leggi questo

5
Cut Copy

I filtri possono essere bypassati e i dati che vanno nelle istruzioni SQL possono provenire da più posizioni rispetto all'input dell'utente. I punti di ingresso in un source/sink influenzato da SQL possono essere memorizzati (ordine superiore), ad esempio, ma chiaramente i parametri HTTP GET e POST dai moduli HTML non sono le uniche modalità di utilizzo ingresso.

Le query con parametri non rendono necessariamente le tue istruzioni SQL libere da iniezioni. Richiedono inoltre l'associazione variabile, la rimozione di operazioni/concatenazione di stringhe e l'eliminazione di alcuni problemi di sicurezza con un'ampia gamma di clausole SQL.

La maggior parte degli sviluppatori dimentica anche di controllare i propri componenti di terze parti e altre dipendenze per problemi di iniezione di SQL, e talvolta non si rende conto che queste inclusioni potrebbero rendere vulnerabile il proprio codice.

La cosa migliore da fare è assumere una società di consulenza sulla sicurezza delle applicazioni per preparare le applicazioni per la prontezza di produzione e formare i propri team di appdev sulla creazione di controlli di sicurezza delle applicazioni nel loro processo e tecnologia di sviluppo.

4
atdre

Per espandere la risposta di Hendrick. È facile pensare a real_escape_string come un proiettile magico quando in realtà non lo è. Ho visto persone usare quella funzione quando invece vogliono usare intval o lanciare l'input su un numero intero. Puoi comunque essere iniettato se usi la stringa di escape nel contesto sbagliato.

3
getahobby