Why do they say that $ _GET in PHP is insecure against sql injection?

5

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.

    
asked by anonymous 06.03.2017 / 23:47

1 answer

13

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 a bind_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();
}

bindValue and bindParam

  • 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?

    
07.03.2017 / 00:08