Iniezione SQL usando lettere e numeri?

8

Mi chiedevo se è possibile che un hacker esegua un attacco di SQL injection usando solo lettere e numeri. Ad esempio, diamo un'occhiata a questo codice PHP che usa espressioni regolari invece delle funzioni PHP incorporate:

<?php
$id = preg_replace('/[^a-zA-Z0-9]/', '', $_GET['id']);
$result = $mysqli->query("SELECT * users WHERE id = '".$id."'");

Nel caso in cui ti chiedi cosa fa il codice, rimuove tutti i caratteri che non sono lettere o numeri ed esegue quella query in MySQL. Mi chiedevo se un hacker potesse essere in grado di sfruttare quel codice in qualche modo e in caso contrario, quale potrebbe essere la differenza tra questo e mysqli::prepare o mysqli::escape_string ?

    
posta ub3rst4r 04.07.2013 - 05:48
fonte

4 risposte

8

Ci sarebbe solo un difetto di sicurezza se fosse possibile lasciare la stringa MySQL letterale contesto il valore $id viene inserito in e per fornire frammenti SQL arbitrari. E questo è possibile solo se $id contiene il ' normale che denoterebbe il delimitatore finale della stringa letterale MySQL:

// resulting SQL statement with $id = "' OR '1'='1"
SELECT * users WHERE id = '' OR '1'='1'

Da quando rimuovi qualsiasi carattere ' da $id , non è possibile lasciare il contesto letterale della stringa e quindi non è possibile fornire frammenti SQL arbitrari.

Tuttavia, questa conclusione si applica solo per il caso in cui il valore è utilizzato in una stringa letterale MySQL. Se stai utilizzando lo stesso filtro di input sui valori in una query diversa, potresti comunque essere vulnerabile alle iniezioni SQL.

Detto questo, metodi come mysqli::prepare e mysqli::escape_string sono tecniche di mitigazione appropriate. mysqli::prepare implementa la cosiddetta istruzione / query parametrizzata tramite istruzioni preparate dove il comando (istruzione SQL) ei dati forniti dall'utente sono separati l'uno dall'altro in modo che i dati forniti dall'utente non possano essere interpretati erroneamente come comando. mysqli::escape_string sarebbe simile alla tua tecnica attuale in quanto sfugge solo certi caratteri dei dati a non essere confuso come controllo caratteri come il delimitatore di fine letterale stringa.

    
risposta data 04.07.2013 - 07:34
fonte
3

(Vorrei postare questo come un commento, ma i commenti non fanno collegamenti ordinatamente).

Questo è abbastanza simile a molti < a href="https://stackoverflow.com/questions/8506574/sql-injection-isnt-replace-good-enough"> domande su Stack Overflow.

L'Open Web Application Security Project (OWASP) fa notare che escaping caratteri speciali è una difesa contro l'iniezione SQL:

  1. Use Prepared Statements (Parameterized Queries) and Stored Procedures
  2. If a parameterized API is not available...Escape Special Characters
  3. Perform White List Input Validation

Per quanto riguarda la prova del codice concettuale che raggiunge SQLi senza caratteri speciali - non ne ho visto nessuno, ma l'assenza di prove non è prova di assenza. Se è possibile implementare query parametrizzate, perché non farlo?

    
risposta data 04.07.2013 - 06:46
fonte
3

Una regola empirica generale: non reinventare la ruota!

Sebbene il codice che hai fornito non sia probabilmente sfruttabile ci sono alcuni buoni motivi per usare le dichiarazioni preparate (un buon quadro di persistenza è ancora meglio) quando possibile:

  • Le dichiarazioni preparate sono efficienti
  • Non vuoi occuparti di tutti i possibili esiti di alimentazione di caratteri esotici al tuo motore di espressioni regolari (vedi mysql_escape_string () fiasco)
  • In relazione al punto precedente: se i dati dell'utente sono memorizzati / codificati / formattati in modo non banale SQL contrabbando potrebbe essere possibile
  • Nel tuo esempio, la difesa viene implementata in due fasi: sia l'espressione RE che l'espressione SQL devono essere ottimizzate tenendo presente l'altro componente. Man mano che il tuo codice base inizia a crescere (e forse gli altri sviluppatori si uniscono) sarà difficile prendersi cura di entrambi i passaggi e prima o poi farai un errore sfruttabile
risposta data 04.07.2013 - 15:04
fonte
0

Il lavoro di iniezione SQL è il supporto di MySQL per i letterali esadecimali e il fatto che la colonna id della tabella dei voti è di tipo stringa, in quanto in quel caso vale quanto segue:

In contesti di stringhe, si comportano come stringhe binarie, in cui ogni coppia di cifre esadecimali viene convertita in un carattere:

mysql> SELECT 0x0f+0;
    -> 15

Per PHP 0x ... è numerico (cioè, is_numeric) e per MySQL 0x ... viene interpretato e memorizzato come stringa, che successivamente viene inserito nell'istruzione SELECT sopra menzionata.

Questo non sarebbe possibile se

id sarebbe stato un tipo di dati numerici, o la SELECT sarebbe stata una dichiarazione preparata.

Quindi i payload esencodificati potrebbero passare mentre stai permettendo 0-9 e a-z che possono essere utilizzati per iniettare payload codificati esadecimali a partire da 0x [0-9a-f] .....

    
risposta data 18.09.2018 - 17:17
fonte

Leggi altre domande sui tag