Usamos cookies para medir audiência e melhorar sua experiência. Você pode aceitar ou recusar a qualquer momento. Veja sobre o iMasters.
Revisando alguns códigos sobre segurança e prepared statements, percebi algumas diferenças e fiquei em dúvida sobre o SELECT.
O código abaixo do jeito que está, com $mysqli->query($sql); torna seguro o SELECT ou é necessário fazer todo o processo de prepare, bind_param, execute, bind_result?
O query() por si só já representa um prepared statement?
$sql = "SELECT id FROM membros WHERE email='$e' AND password='$pass' LIMIT 1";
$numrows = $mysqli->query($sql);
if($numrows->num_rows == 0){
...
}
else {
if($numrows->num_rows > 0){
while($result_row = $numrows->fetch_assoc()){
$id = $result_row['id'];
echo $id;
}
}O query() por si só já representa um prepared statement?
Não.
Um Prepared Statement consistem em enviar ao SGBD a query sem os parâmetros. Na verdade, a query com os placeholders que representam os parâmetros.
Os parâmetros propriamente ditos são enviados em pacotes diferentes. Assim o próprio SGBD faz a filtragem deles e os vincula à query
O método query() só será seguro se não possuir parâmetros do usuário. Por exemplo na query "SELECT campos FROM tabela WHERE data_hora = NOW()".
Veja este meu artigo sobre prevenção de SQL Injection:
http://rberaldo.com.br/seguranca-em-sistemas-de-login-protecao-contra-sql-injection/
Ok, vou ler as duas sugestões. E por exemplo num script de recuperação de senha onde o usuário vai inserir seu e-mail, os filter_input, filter_var com FILTER_SANITIZE_EMAIL e FILTER_VALIDATE_EMAIL já são suficientes pra tornar seguro o script:
Exemplo:
<?php
if (isset($_POST['email'])) {
$email = mysqli_real_escape_string($mysqli, $_POST['email']);
$email = filter_input(INPUT_POST, 'email', FILTER_SANITIZE_EMAIL);
$email = filter_var($email, FILTER_VALIDATE_EMAIL);
if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
// Email inválido
echo "<script>
alert('O endereço de email digitado não é válido');
window.location.href='../lostpwd.php';
</script>";
}else{
$sql = "SELECT email FROM membros WHERE email = '$email'";
$result_mail = mysqli_query($mysqli, $sql);
$e_mail = "";
if($result_mail->num_rows > 0){
while($row = $result_mail->fetch_assoc()){
$e_mail = $row['email'];
}
}
if ($email == $e_mail) {
....
?>
processa o envio da mensagem com link de recuperação de senha
<?php
....
// Link clicado no email executa este codigo
if(isset($_GET['u']) && isset($_GET['p'])){
$u = $_GET['u'];
$temppasshash = $_GET['p'];
if(strlen($temppasshash) < 16){
exit();
}
$sql = "SELECT id FROM membros WHERE email='$u' AND password='$temppasshash' LIMIT 1";
$numrows = $mysqli->query($sql);
if($numrows->num_rows == 0){
echo "Não foi encontrado nenhum usuário com esta senha temporária. ";
echo "<a href='../login.php'>Home</a>";
exit();
}
else {
...
}
?>
O SELECT que fiz do email no banco pra comparar com o email digitado pelo usuario é o caso onde não há parametros do usuario e posso fazer um query() mais simples, certo?!
Já as variáveis $u e $temppasshash podem apresentar algum risco, ja que elas vem do link da mensagem do email? Por exemplo se o link de recuperação de senha for copiado da mensagem do email e colado no navegador e inserido alguma tentativa injection neste link?!
A menos que você tenha tratado as suas variáveis $e e $pass, o código acima não está veraneável a sql injection.
Da uma olhada aqui tem bons exemplos tanto com mysqli quanto com pdo.
How to prevent SQL injection in PHP
http://indieteq.com/index/readmore/how-to-prevent-sql-injection-in-php