Well, my question is simple.
I've been lately hearing many stories saying that $ _GET in PHP is insecure against sql injection.
Could you tell me why?
Thank you.
Well, my question is simple.
I've been lately hearing many stories saying that $ _GET in PHP is insecure against sql injection.
Could you tell me why?
Thank you.
It is not the $_GET
that is insecure, the problem is how to use it. The data can come from $_GET
, $_POST
, $_COOKIE
or even a previously saved string in a file and then added to the execution of a query.
The problem is how to pass the values directly into the query, for example:
SELECT * FROM tabela WHERE nome LIKE '%{$_GET['nome']}%'
In this way it would be possible to do something like http://site/pagina.php?nome=';QUERY
and it would generate this:
SELECT * FROM tabela WHERE nome LIKE '';QUERY'
Of course in the case above at most syntax would fail, in general the API does not allow multiple queries, now imagine that the data of a SELECT is based on a saved id in the session and the products that the user can view in a panel are only those with the ID ( id_dono
) of it:
SELECT * FROM produtos WHERE id_produto={$_GET['idproduto']} AND id_dono={$_SESSION['idautenticado']}
But if you type this access this http://site/pagina.php?idproduto=6 --
and it would generate this:
SELECT * FROM produtos WHERE id_produto=6 -- OR id_dono=5
In this way the user ignored everything that comes after --
and can get private data of products from other users in an alleged panel where he would control his products.
Another example would be to manipulate any column in a table:
UPDATE dados SET nome='%{$_GET['nome']}%' WHERE id=%{$_GET['id']}%
Suppose we have columns that should not be able to be changed, but if you do something like http://site/pagina.php?id=1&nome=,outracoluna='xxxxxx'
you will have control over any column of the table, because it will generate something like:
UPDATE dados SET nome='',outracoluna='xxxxxx' WHERE id=1
Read this how to avoid:
A simple example is to use bindValue
or 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 only works with
bind_param
, that is no there is abind_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
works with references, ie you should only use variables and constants. If it is a variable the value can be changed later, but before execute
bindValue
works with any type of value, constant variable or passed directly
Read more at: What's the difference between bindParam and bindValue?