Stack Overflow em Português Asked by Gonçalo on October 21, 2020
Bom, a minha dúvida, é simples.
Tenho andado ultimamente, a ouvir muitas histórias a dizer que o $_GET no PHP é inseguro contra sql injection.
Poderiam-me dizer porquê?
Obrigado.
Não é o $_GET
que é inseguro, o problema é como usa ele. Os dados podem vir por $_GET
, $_POST
, $_COOKIE
ou até uma string gravada previamente em um arquivo e posteriormente adicionada a execução de uma query.
O problema está em como passar diretamente os valores na query, por exemplo:
SELECT * FROM tabela WHERE nome LIKE '%{$_GET['nome']}%'
Desta forma seria possível fazer algo como http://site/pagina.php?nome=';QUERY
e geraria isto:
SELECT * FROM tabela WHERE nome LIKE '';QUERY'
Claro que no caso acima no máximo obteria uma falha de sintaxe, no geral a API não permite múltiplas queries, agora imagine que os dados de uma SELECT são baseados em um id salvo na sessão e os produtos que o usuário pode visualizar em um painel são somente os com a ID (id_dono
) dele:
SELECT * FROM produtos WHERE id_produto={$_GET['idproduto']} AND id_dono={$_SESSION['idautenticado']}
Mas se digitar isso acessar isto http://site/pagina.php?idproduto=6 --
e geraria isto:
SELECT * FROM produtos WHERE id_produto=6 -- OR id_dono=5
Desta maneira o usuário ignorou tudo que vier depois de --
e pode obter os dados privados de produtos de outros usuários em um suposto painel aonde controlaria os seus produtos.
Outro exemplo seria manipular qualquer coluna de uma tabela:
UPDATE dados SET nome='%{$_GET['nome']}%' WHERE id={$_GET['id']}
Suponhamos que temos colunas que não deveria poder ser alteradas, mas se você fizer algo como http://site/pagina.php?id=1&nome=',outracoluna='xxxxxx
você irá ter controle sobre qualquer coluna da tabela, pois vai gerar algo como:
UPDATE dados SET nome='',outracoluna='xxxxxx' WHERE id=1
Leia isto de como evitar:
Um exemplo simples é usar o bindValue
ou bindParam
:
PDO
+bindValue
:
$db = new PDO('mysql:host=localhost dbname=teste', 'usuario', 'senha');
$stmt = $db->prepare('SELECT * FROM tabela WHERE nome LIKE ?');
$stmt->bindValue(1, '%' . $_GET['busca'] . '%'); // passado diretamente
$stmt->execute();
PDO
+bindParam
:
$stmt = $db->prepare('SELECT * FROM tabela WHERE nome LIKE :consulta');
$stmt->bindParam(':consulta', $nome);
$nome = '%' . $_GET['consulta'] . '%';
Mysqli
+bind_param
:
mysqli só trabalha com
bind_param
, ou seja não existe umbind_value
$db = new mysqli('localhost', 'usuario', 'senha', 'teste');
$stmt = $db->prepare('SELECT * FROM tabela WHERE nome LIKE ?');
if(!$stmt){
echo 'erro na consulta: '. $db->errno .' - '. $db->error;
} else {
$stmt->bind_param('s', $nome);
$nome = '%' . $_GET['consulta'] . '%';
$stmt->execute();
}
bindParam
trabalha com referencias, ou seja só deve-se usar variáveis e constantes. Se for uma variável o valor pode ser alterado posteriormente, mas antes do execute
bindValue
trabalha com qualquer tipo de valor, variável constante ou passado diretamente
Leia mais em: Qual a diferença entre bindParam e bindValue?
Correct answer by Guilherme Nascimento on October 21, 2020
Get help from others!
Recent Questions
Recent Answers
© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP