Impedir injeção de SQL em PHP
- Use as instruções preparadas e o PDO para evitar injeção de SQL em PHP
-
Use as instruções
Prepared
com a consulta parametrizada para evitar injeção de SQL em PHP -
Defina o atributo
PDO::ATTR_EMULATE_PREPARES
comofalse
para evitar a injeção de SQL
Apresentaremos um método para prevenir a injeção de SQL em PHP usando as instruções preparadas e o PHP Data Objects (PDO). Usamos PDO para estabelecer a comunicação do banco de dados neste método. Este método envia os dados e a consulta separadamente para o servidor de banco de dados, o que evita a mistura dos dados e do servidor.
Apresentaremos um método para prevenir a injeção de SQL em PHP usando as instruções preparadas e a consulta parametrizada. Usamos mysqli
para estabelecer a comunicação do banco de dados neste método. Este método possui um mecanismo de funcionamento semelhante ao primeiro método. O ponto de contraste são apenas as funções mysqli
que usamos para prevenir a injeção de SQL.
Mostraremos um exemplo de como se proteger da injeção de SQL ao usar o PDO no PHP, definindo a emulação de instruções preparadas como false
.
Use as instruções preparadas e o PDO para evitar injeção de SQL em PHP
Podemos usar a instrução preparada junto com o PDO para evitar injeção de SQL no PHP. A injeção de SQL ocorre quando há a mistura da consulta e dos dados durante o envio ao banco de dados. Neste método, não especificamos o valor exato dos dados na instrução SQL. Em vez disso, usamos os marcadores de posição. Devido a isso, as instruções SQL parametrizadas são enviadas ao servidor como a primeira solicitação. Usamos a função prepare()
para fazer isso. Vinculamos o valor exato do parâmetro na segunda solicitação ao servidor de banco de dados. Usamos a função bindValue()
para este propósito. Assim, enviamos o programa na primeira solicitação e os dados na segunda solicitação. Se solicitarmos os dados junto com os códigos SQL, o usuário pode alterar o programa e escrever códigos maliciosos. Assim, evita que códigos SQL maliciosos sejam injetados no servidor.
Por exemplo, uma tabela usuários
contém os seguintes campos e dados.
+----+-----------+----------+------------+
| id | firstname | lastname | dob |
+----+-----------+----------+------------+
| 1 | bruce | rose | 1998-02-13 |
| 2 | jeff | james | 2000-03-30 |
+----+-----------+----------+------------+
Ele cria uma variável $firstname
e atribui a ela o nome bruce
. Ele cria uma variável $sql
e escreve uma consulta SELECT * FROM users WHERE firstname =:fname;
nele.
Não escreva o valor exato dos dados para firstname
. Em vez disso, use o parâmetro :fname
. Use a variável $pdo
para chamar a função prepare()
na variável de consulta. Substitua o valor de :fname
pela variável $firstname
. Execute a instrução com a função execute()
. Verifique o resultado com a função fetch()
se as credenciais correspondem ao banco de dados. Em caso afirmativo, exiba o id
, firstname
e o lastname
da linha selecionada.
O exemplo abaixo demonstra o uso de uma declaração preparada. Ele armazena o valor do campo firstname
em uma variável para verificar se a credencial corresponde. Se a variável contiver algum código malicioso, ela exibirá a mensagem Credentials do no match
. Isso ocorre porque a função prepared()
leva apenas a consulta parametrizada e não permite os dados exatos. A variável $pdo
contém o objeto da conexão do banco de dados.
Código de exemplo:
# php 7.*
<?php
$firstname = "bruce";
$sql = "SELECT * FROM users WHERE firstname =:fname ;";
$stmt = $pdo->prepare($sql);
$stmt->bindValue(":fname", $firstname);
$stmt->execute();
if(!$result = $stmt->fetch(PDO::FETCH_OBJ)){
echo "Credentials do no match";
} else {
echo"Id: ".$result->id. " Name: ".$result->firstname." ".$result->lastname;
}
?>
Resultado:
Id: 1 Name: bruce rose
Use as instruções Prepared
com a consulta parametrizada para evitar injeção de SQL em PHP
Podemos usar a instrução preparada junto com a consulta parametrizada para evitar injeção de SQL no PHP. Usamos o objeto da função mysqli()
para criar uma conexão de banco de dados. Neste método, usamos um símbolo de ponto de interrogação ?
como marcadores de posição dos dados. Usamos a função prepare()
como o método acima. Usamos a função bind_param()
para vincular os dados reais no placeholder. Este método segue um mecanismo de trabalho semelhante ao método acima.
Por exemplo, estabeleça uma conexão de banco de dados criando um objeto da função mysqli()
e atribua-o a uma variável $conn
. Atribua com o nome jeff
a uma variável $firstname
. Crie uma variável $sql
e escreva uma consulta SELECT * FROM users WHERE first name =?;
. Use a variável $conn
para chamar a função prepare()
na variável de consulta. Substitua o marcador ?
com a variável $firstname
. Execute a instrução com a função execute()
. Chame a função get_result()
para armazenar o resultado na variável $result
. Verifique se a linha existe com a propriedade num_rows
e retorne a mensagem No Rows
com a função exit()
se a condição falhar. Chame o método fetch_assoc()
e armazene-o na variável $row
em um loop while. Exibe o id
, firstname
e o lastname
da linha selecionada.
Código de exemplo:
#php 7.x
<?php
$conn = new mysqli($host, $user, $pwd, $dbName);
$firstname = "jeff";
$sql = "SELECT * FROM users WHERE firstname = ?";
$stmt = $conn->prepare($sql);
$stmt->bind_param("s", $firstname);
$stmt->execute();
$result = $stmt->get_result();
if($result->num_rows === 0) exit('No rows');
while($row = $result->fetch_assoc()) {
echo"Id: ".$row['id']. " Name: ".$row['firstname']." ".$row['lastname'];
}
Resultado:
Id: 2 Name: jeff james
Defina o atributo PDO::ATTR_EMULATE_PREPARES
como false
para evitar a injeção de SQL
Usar instruções preparadas no PDO pode não ser suficiente para evitar a injeção de SQL se não definirmos os atributos do PDO corretamente. Devemos definir o atributo PDO::ATTR_EMULATE_PREPARES
para false
para evitar a injeção. Se definirmos o atributo como true
, o PDO apenas emulará as instruções preparadas em vez de usá-las. Assim, o sistema ficará vulnerável à injeção de SQL.
Por exemplo, crie uma conexão PDO com o banco de dados em uma variável $pdo
. Use a variável para chamar a função setAttribute()
. Defina o atributo PDO::ATTR_EMULATE_PREPARES
como falso.
Exemplo de código:
#php 7.x
<?php
$pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, true);
?>
Subodh is a proactive software engineer, specialized in fintech industry and a writer who loves to express his software development learnings and set of skills through blogs and articles.
LinkedIn