kutombawewe.net

SQL injection che aggira mysql_real_escape_string ()

Esiste una possibilità di iniezione SQL anche quando si utilizza la funzione mysql_real_escape_string()?

Considera questa situazione di esempio. SQL è costruito in PHP come questo:

$login = mysql_real_escape_string(GetFromPost('login'));
$password = mysql_real_escape_string(GetFromPost('password'));

$sql = "SELECT * FROM table WHERE login='$login' AND password='$password'";

Ho sentito numerose persone dirmi che un codice del genere è ancora pericoloso e può essere modificato anche con la funzione mysql_real_escape_string() utilizzata. Ma non riesco a pensare a qualche possibile exploit?

Iniezioni classiche come questa:

aaa' OR 1=1 --

non lavorare.

Sei a conoscenza di una possibile iniezione che avrebbe superato il codice PHP sopra?

539
Richard Knop

Considera la seguente domanda:

$iId = mysql_real_escape_string("1 OR 1=1");    
$sSql = "SELECT * FROM table WHERE id = $iId";

mysql_real_escape_string() non ti proteggerà da questo . Il fatto che tu usi le virgolette singole (' ') attorno alle tue variabili all'interno della tua query è ciò che ti protegge da questo. Il seguente è anche un'opzione:

$iId = (int)"1 OR 1=1";
$sSql = "SELECT * FROM table WHERE id = $iId";
328

Beh, non c'è nulla che possa attraversarlo, oltre al jolly %. Potrebbe essere pericoloso se tu stessi usando la dichiarazione LIKE dato che l'autore dell'attacco potrebbe inserire solo % come login se non lo si filtra, e dovrebbe semplicemente applicare una password a bruteforce a qualcuno dei tuoi utenti . Le persone spesso suggeriscono di usare istruzioni preparate per renderlo sicuro al 100%, dato che i dati non possono interferire con la query stessa in questo modo . Ma per query così semplici probabilmente sarebbe più efficiente fare qualcosa come $login = preg_replace('/[^a-zA-Z0-9_]/', '', $login);

19
Slava

sono stato di fronte a questo e ti suggerisco di lavorare con PDO, ma in alcuni casi potresti voler provare questo metodo. Funziona e molto semplice. Mi chiedo perché la gente l'abbia trascurato.

Esempio di codice // Uso del mio framework Moorexa

supporta un ORM ricco e molto di più . Ma ho dovuto eseguire questo test case per essere sicuro di un'alternativa alle persone che scrivono le istruzioni raw sql.

esempio. 

// checking from a user table
$check = DB::table('api_users')->get(['username' => "admin' or password='1'"])->run();

// expected output
SELECT * FROM api_users  WHERE username='admin' or password='1'

//sql generated output
SELECT * FROM api_users  WHERE username='admin\' or password=\'1\''

// lets try something heavy
$check = DB::table($table)->get(['username' => "admin' or 1=1 UNION SELECT password FROM api_users where id=1"])->run();

// expected output
SELECT * FROM api_users  WHERE username='admin' or 1=1 UNION SELECT password FROM api_users where id=1

// this would pass and fail
SELECT * FROM api_users  WHERE username='admin\' or 1=1 UNION SELECT password FROM api_users where id=1'

quindi qual è il Gist.

  1. Controlla il tipo.
  2. convalidare l'input dell'utente. <TRUST NO ONE>
  3. frasi di fuga per stringhe

ti mostrerò un esempio di codice che esegue una query di selezione.

// let's assume. would all work
$input = ['username' => "moorexa"]; //or $_POST or $_GET

$sql = 'SELECT * FROM '.$table.' ';

$safe = "";

// let's grab the user input from the array
foreach ($input as $key => $val)
{
    switch($val)
    {
        case is_string($val):
            $safe .= $key .'=\''.addslashes($val).'\' AND ';
        break;

        case is_int($val):
            $safe .= $key .'='.((int) $val).' AND ';
        break;

        case is_float($val):
        case is_double($val):
            $safe .= $key .'='.(double) $val.' AND ';
        break;

        default:
            // this failed
    }
}

$safe = rtrim($safe, "AND ");
$sql .= ' WHERE '. $safe .' ';  

// now sql contains a valid statement. and would only fail when terms are not met.
// Hope you can apply this and also use more test cases.
0
Ifeanyi Amadi