Alternativa a mysql_real_escape_string senza connessione al DB


91

Mi piacerebbe avere una funzione che si comporti come mysql_real_escape_string senza connettersi al database poiché a volte ho bisogno di eseguire test a secco senza connessione DB. mysql_escape_string è deprecato e quindi non è desiderabile. Alcuni dei miei risultati:

http://www.gamedev.net/community/forums/topic.asp?topic_id=448909

http://w3schools.invisionzone.com/index.php?showtopic=20064



1
+1 Sto scrivendo la classe MySQL da solo e uso mysql_real_escape_string () per scopi di associazione dei parametri. Evito di usare mysqli poiché non tutti gli hosting lo supportano. Evito anche la libreria multi-file e multi-classe. Quello di cui ho bisogno è solo una singola classe ordinata e pulita. Grazie!
Viet

+1 anche per me. Il mio caso d'uso è un'APi SugarCRM in cui devo inviare frammenti di SQL all'istanza SugarCRM remota tramite l'API. Per quanto sia brutto, è quello con cui devo lavorare (vai a mettere insieme alcune teste di sviluppatori di SugarCRM). Ho bisogno di eseguire l'escape delle stringhe in SQL nell'applicazione che utilizza l'API e che è totalmente separata dal database dietro l'istanza di SugarCRM.
Jason

Risposte:


75

È impossibile sfuggire in modo sicuro a una stringa senza una connessione DB. mysql_real_escape_string()e le istruzioni preparate richiedono una connessione al database in modo che possano eseguire l'escape della stringa utilizzando il set di caratteri appropriato, altrimenti gli attacchi SQL injection sono ancora possibili utilizzando caratteri multibyte.

Se stai solo testando , puoi anche usare mysql_escape_string(), non è garantito al 100% contro gli attacchi di SQL injection, ma è impossibile creare qualcosa di più sicuro senza una connessione DB.


1
+1 Grazie per la nota. Non sono molto sicuro di come testare contro gli attacchi di SQL injection utilizzando caratteri multibyte.
Viet

2
Mi è stato dato del vecchio codice da aggiornare. Utilizza mysql_escape_stringsenza una connessione (ancora cercando di capire perché). Dato che quella funzione è deprecata, mi chiedo solo come posso sostituirla. Certamente sembra ragionevole che si possa specificare il "set di caratteri appropriato" in qualunque funzione lo sostituisca senza aprire una connessione.
JohnK

3
Impossibile? Cosa ottiene mysql_real_escape_string dalla connessione al database che non sono dati di configurazione che potrebbero essere passati manualmente a una funzione equivalente? Modifica: basta leggere sotto, richiama una funzione di libreria all'interno di MySQL, quindi c'è qualche elaborazione che avviene al di fuori di PHP. Potrebbe ancora essere portatile, ma mantenerlo aggiornato sarebbe un progetto in sé.
Jason

2
Cosa succede se il set di caratteri DB è noto in anticipo?
jchook

7
Sì, se conosci il set di caratteri, cosa impedisce di eseguire la fuga senza una connessione?
Johan

66

Bene, secondo la pagina di riferimento della funzione mysql_real_escape_string : "mysql_real_escape_string () chiama la funzione di libreria di MySQL mysql_real_escape_string, che sfugge ai seguenti caratteri: \ x00, \ n, \ r, \, '," e \ x1a. "

Con questo in mente, la funzione fornita nel secondo link che hai pubblicato dovrebbe fare esattamente ciò di cui hai bisogno:

function mres($value)
{
    $search = array("\\",  "\x00", "\n",  "\r",  "'",  '"', "\x1a");
    $replace = array("\\\\","\\0","\\n", "\\r", "\'", '\"', "\\Z");

    return str_replace($search, $replace, $value);
}

6
Grazie. Suggerirei qualcos'altro: function escape ($ aQuery) {return strtr ($ aQuery, array ("\ x00" => '\ x00', "\ n" => '\ n', "\ r" => '\ r', '\\' => '\\\\', "'" => "\'", '"' => '\"', "\ x1a" => '\ x1a')) ; }
Viet

1
perché \ x1a viene sostituito con \\\ x1a anziché \\ x1a? È un errore di battitura?
Michael Z

16
-1 Questo è estremamente pericoloso. Se la connessione al database utilizza un set di caratteri multibyte, semplici sostituzioni byte per byte come questa potrebbero portare alla corruzione dei dati (inclusi caratteri di escape / virgolette) - questo può essere deliberatamente sfruttato da un malintenzionato per iniettare SQL arbitrario.
Eggyal

Se sbagli i set di caratteri su questo, può essere pericoloso. Per i set di caratteri multibyte, se mysql lo usa, qualcuno può semplicemente inserire un byte per cancellare il \\. I set di caratteri multibyte possono spesso prendere qualsiasi cosa come secondo byte, incluso \\ per mysql, non lo vedrà come un carattere autonomo \\ ma parte del carattere multibyte. Non ho idea di cosa succede con UTF8. Spero che con [0xB0, '\\'] che colpendo un byte non valido \\ si fermi e ricominci con quel byte invece di ingerirlo.
jgmjgm

1
Se so che il set di caratteri è utf8, è sicuro usare mb_strpos()(e mb_substr()creare un comportamento simile a substr_replace()) per farlo?
SOFe

28

In diretta opposizione alla mia altra risposta, questa seguente funzione è probabilmente sicura, anche con caratteri multibyte.

// replace any non-ascii character with its hex code.
function escape($value) {
    $return = '';
    for($i = 0; $i < strlen($value); ++$i) {
        $char = $value[$i];
        $ord = ord($char);
        if($char !== "'" && $char !== "\"" && $char !== '\\' && $ord >= 32 && $ord <= 126)
            $return .= $char;
        else
            $return .= '\\x' . dechex($ord);
    }
    return $return;
}

Spero che qualcuno più esperto di me possa dirmi perché il codice sopra non funziona ...


+1 Grazie per lo sforzo extra. Vado in giro per saperne di più sulle iniezioni SQL relative a multibyte.
Viet

Immagino che dovrebbe essere $ return. = '\ X'. dechex ($ ord); invece
Viet

1
Come regola generale, preferisco usare "\\" anche nelle stringhe tra virgolette, solo perché un singolo "\" può influenzare il carattere successivo se non stai attento. Probabilmente sono solo di nuovo OCD.
troppo php

1
Questa funzione non segue le regole di escape di mysql e provocherà la perdita dell'integrità dei dati. "MySQL riconosce le sequenze di escape mostrate nella Tabella 9.1," Sequenze di escape di caratteri speciali ". Per tutte le altre sequenze di escape, la barra rovesciata viene ignorata. Cioè, il carattere di escape viene interpretato come se non fosse stato sottoposto a escape. Ad esempio," \ x " è solo "x". " - dev.mysql.com/doc/refman/5.6/en/…
velcrow

2
\ XAA significa effettivamente qualcosa di più del testo "xAA" in una stringa letterale MySQL? La documentazione sembra dire che \ x non ha alcun significato speciale, quindi \ verrà ignorato. dev.mysql.com/doc/refman/5.0/en/string-literals.html
Jason

6

Da ulteriori ricerche, ho trovato:

http://dev.mysql.com/doc/refman/5.1/en/news-5-1-11.html

Correzione di sicurezza:

È stata rilevata una falla nella sicurezza di SQL injection nell'elaborazione della codifica multibyte. Il bug era nel server, analizzando in modo errato la stringa di cui è stato eseguito l'escape con la funzione API C mysql_real_escape_string ().

Questa vulnerabilità è stata scoperta e segnalata da Josh Berkus e Tom Lane come parte della collaborazione per la sicurezza tra i progetti del consorzio OSDB. Per ulteriori informazioni sull'iniezione SQL, vedere il testo seguente.

Discussione. È stata rilevata una falla nella sicurezza di SQL injection nell'elaborazione della codifica multibyte. Un buco di sicurezza di SQL injection può includere una situazione in cui quando un utente ha fornito dati da inserire in un database, l'utente potrebbe iniettare istruzioni SQL nei dati che il server eseguirà. Per quanto riguarda questa vulnerabilità, quando viene utilizzato l'escape inconsapevole del set di caratteri (ad esempio, addlashes () in PHP), è possibile aggirare l'escape in alcuni set di caratteri multibyte (ad esempio, SJIS, BIG5 e GBK). Di conseguenza, una funzione come addlashes () non è in grado di prevenire attacchi di SQL injection. È impossibile risolvere questo problema sul lato server. La soluzione migliore è che le applicazioni utilizzino l'escape in base al set di caratteri offerto da una funzione come mysql_real_escape_string ().

Tuttavia, è stato rilevato un bug nel modo in cui il server MySQL analizza l'output di mysql_real_escape_string (). Di conseguenza, anche quando veniva utilizzata la funzione di riconoscimento del set di caratteri mysql_real_escape_string (), era possibile l'iniezione SQL. Questo errore è stato corretto.

Soluzioni alternative. Se non sei in grado di aggiornare MySQL a una versione che include la correzione del bug nell'analisi di mysql_real_escape_string (), ma esegui MySQL 5.0.1 o versioni successive, puoi utilizzare la modalità SQL NO_BACKSLASH_ESCAPES come soluzione alternativa. (Questa modalità è stata introdotta in MySQL 5.0.1.) NO_BACKSLASH_ESCAPES abilita una modalità di compatibilità standard SQL, dove la barra rovesciata non è considerata un carattere speciale. Il risultato sarà che le query falliranno.

Per impostare questa modalità per la connessione corrente, immettere la seguente istruzione SQL:

SET sql_mode='NO_BACKSLASH_ESCAPES';

Puoi anche impostare la modalità a livello globale per tutti i client:

SET GLOBAL sql_mode='NO_BACKSLASH_ESCAPES';

Questa modalità SQL può anche essere abilitata automaticamente all'avvio del server utilizzando l'opzione della riga di comando --sql-mode = NO_BACKSLASH_ESCAPES o impostando sql-mode = NO_BACKSLASH_ESCAPES nel file delle opzioni del server (ad esempio, my.cnf o my.ini , a seconda del sistema). (Bug # 8378, CVE-2006-2753)

Vedi anche Bug # 8303.


1
Questo problema è stato risolto molto tempo fa.
Il tuo buon senso

2
Attenzione anche che NO_BACKSLASH_ESCAPES introduce altre vulnerabilità .
Eggyal

2
Risolto in 5.1.11 - Il collegamento era interrotto, ecco l'archivio: web.archive.org/web/20120501203047/http://dev.mysql.com:80/doc/…
Bastion
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.