Quanto è sicuro questo codice php contro l'iniezione SQL?

2

Il codice riportato di seguito è una parte di un semplice codice script di accesso ..

if (isset ($_POST['login'])) { 
                $username = $_POST['username']; 
                $password = $_POST['password'];
                $password_hash = sha1($password);

                $query = "SELECT id,username FROM users WHERE username = '".mysqli_real_escape_string($link,$username)."' AND password ='".$password_hash."'";

Ecco alcuni dei miei dubbi:

  1. Il codice precedente è vulnerabile a qualsiasi tipo di errore (cieco, unione, unione) dell'iniezione SQL?
  2. Se il codice sopra è vulnerabile agli attacchi SQL injection, come e perché l'attaccante può lanciare l'attacco?
  3. Se il codice sopra è sicuro, perché le persone scelgono ancora le istruzioni preparate ecc.?
posta ysj 26.01.2013 - 16:58
fonte

2 risposte

15

Is the above code vulnerable to any kinds (error,blind,union based) of SQL injection?

No, ma solo perché sha1() si presenta sfortunatamente per produrre un output che non contiene mai metacaratteri SQL.

Il tuo codice di creazione di query non dovrebbe essere necessario conoscere i dettagli di questa implementazione. Dovrebbe essere in grado di sfuggire anche al $password_hash , in modo che la riga di codice funzioni autonomamente e possa essere verificata come corretta e sicura senza dover esaminare il contesto più ampio. Altrimenti, quando cambi il modo in cui viene calcolato quel $password_hash (ad esempio, per memorizzare un hash salato più sicuro), potresti scoprire di aver appena creato una vulnerabilità in quel codice di query. Creare un accoppiamento non necessario tra diversi bit di codice, potenzialmente in file diversi, è in generale una cattiva idea.

If the above code is safe, why do people still go for Prepared Statements etc...?

Perché le dichiarazioni preparate sono in genere più facili da leggere, comprendere e verificare; è più difficile omettere per errore una fuga. Confronto:

$query = "SELECT id,username FROM users WHERE username = '"
         .mysqli_real_escape_string($link, $username)
         ."' AND password ='"
         .mysqli_real_escape_string($link, $password_hash)
         ."'";

con:

$query = $mysqli->prepare('SELECT id,username FROM users WHERE username=? AND password=?')
$query->bind_param('ss', $username, $password_hash);

Anche se non sono un grande fan del particolare marchio di query parametriche di mysqli (in particolare il binding alle variabili anziché ai valori), il secondo mi sembra ancora più semplice e più gestibile.

    
risposta data 28.01.2013 - 18:44
fonte
8

Stai utilizzando SHA-1 per il tuo hash della password senza sale nemmeno. Questo è male male. Vedi Come password di hash sicure? per un modo molto migliore di cancellare le tue password .

In secondo luogo, vedi Come prevenire l'SQL injection in PHP per una spiegazione di mysqli_real_escape_string rispetto alle istruzioni preparate.

Potresti dimenticare di sfuggire alle stringhe. L'utilizzo di istruzioni preparate per l'intera applicazione rende molto meno probabile la tua vulnerabilità agli attacchi di SQL injection.

Inoltre la sintassi della stringa di escape è semplicemente brutta.

In terzo luogo, perché stai utilizzando la clausola WHERE per eseguire l'autenticazione invece di recuperare sia l'hash nome utente e password dal tuo database ed eseguire un confronto?

    
risposta data 26.01.2013 - 17:00
fonte

Leggi altre domande sui tag