¿El código anterior es vulnerable a cualquier tipo (error, ciego, unión basada) de inyección SQL?
No, pero solo porque sha1()
sucede por suerte para producir resultados que nunca contienen metacaracteres SQL.
Su código de creación de consultas no debería tener que conocer los detalles de la implementación. También debería estar escapando de $password_hash
, para que la línea de código funcione por sí sola y se pueda verificar como correcta y segura sin tener que mirar el contexto más amplio. De lo contrario, cuando cambie la forma en que se calcula ese $password_hash
(por ejemplo, para almacenar un hash salado más seguro), es posible que haya creado una vulnerabilidad en ese código de consulta. Crear un acoplamiento innecesario entre bits de código dispares, potencialmente en diferentes archivos, es en general una mala idea.
Si el código anterior es seguro, ¿por qué la gente sigue buscando declaraciones preparadas, etc.?
Porque las declaraciones preparadas suelen ser más fáciles de leer, comprender y verificar; es más difícil omitir accidentalmente un escape. Comparar:
$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);
Aunque no soy un gran fanático de la marca particular de mysqli de consultas parametrizadas (especialmente vinculadas a variables en lugar de valores), esta última todavía me parece más simple y más mantenible.