I would do as Rcio Simao proposed, using PDO, but if in your case it is complex change all the code from mysqli to PDO, follows below, an alternative:
<?php
class DB{
private $conn;
public function getConnection(){
$this->conn = new mysqli("localhost", "root", "", "mvc");
}
public function execReader($SQL){
return $this->conn->query($SQL);
}
}
$id = filter_input(INPUT_GET, 'id', FILTER_SANITIZE_NUMBER_INT);
$SQL = "SELECT * FROM produtos WHERE id = ". addslashes($id);
$DB = new DB();
$DB->getConnection();
$query = $DB->execReader($SQL);
if ($query == 0) {
header('Location: 404.php');
exit();
}
$vo = new ProdutoVO();
while($reg = $query->fetch_array(MYSQLI_ASSOC)){
$vo->setId($reg["id"]);
$vo->setNome($reg["nome"]);
$vo->setMarca($reg["marca"]);
$vo->setPreco($reg["preco"]);
}
var_dump($vo);
?>
Yes you will have problem, do not just change the driver mysql_* by mysqli you need to handle the form entries and use Prepared statements. Here has other information about sql Injection
– rray
A good practice is to take your code in a "sandbox" environment and try to hack it. See if you can do something like try to access the URL "www.site.com.br/blablabla_id_2'-DROP TABLE (put the name of a table here)"
– Oralista de Sistemas
Thanks. I tested it in my code and the drop table didn’t work, as did other functions. Thanks for the help, I will read the best practices not to regret later.
– yuri
You don’t need anything fancy, just use
$id = mysql_real_escape_string( $_GET['id'] );
and do this in all the parameters that already solve the problem of Injection. Then, to make the code more elegant, you can even use Prepared statements if you want, instead of Escaping. And if you don’t want to change databases, you better stay in mysqli anyway. No need to use intermediate layers and resource simulation like others libs fashion do. Remembering that Prepared statements were made for performance in loops, the protection is just a "toast".– Bacco
@Bacco, allow me to disagree, but mysql_real_escape_string() does not solve the problem. Some very interesting links: SQL Injection that gets Around mysql_real_escape_string() and Why mysql_real_escape_string() isn’t enough to stop SQL Injection Attacks!
– Marcio Mazzucato
@Marcio You’re right that you don’t solve in all cases, but in this question-specific query you do. Numerical parameters require another type of treatment.
– bfavaretto
@Marciosimao ok, I typed wrong, it was supposed to be mysqli_ :) But I liked the link, because it also shows that PDO does not escape the problem nor with Prepared statements, because they are emulated and will suffer the Injection of any way, good to alert people who think it is the best thing in the world. At least we can reach a consensus: mysqli + Prepared statements is the safest way.
– Bacco
For those who don’t want to read the entire Q&A that @Marciosimao recommended, follow the summary: Pro
mysqli_real_escape_string()
be safe, remember to usemysqli_set_charset()
before, setting for one of these 3 parameters:utf8
,latin1
orascii
, otherwise some special characters can "leak" and still allow some attack (although the pointed bug is formysql
and notmysqli
, but it costs nothing to do right).– Bacco
@bfavaretto, The problem is that an application, however small it is, will hardly turn around just a query, so it is better to adopt techniques that close as many gaps as possible.
– Marcio Mazzucato
@Bacco, For Mysql users is a nice way, but it is good to always seek more comprehensive solutions. If tomorrow it will work with Postgresql, Oracle, SQL Server or any other database, I believe that the key is never to trust the inputs, for this PHP already provides excellent sanitizers, combining this to the use of PDO, the application will get a good degree of security. PDO also has the advantage of abstracting communication with the bank, so for any bank, the methods are the same.
– Marcio Mazzucato
I read the indicated Q&A, and what it says there is the opposite. PDO simulates the Prepared statements, therefore with PDO you have the bug with and without PS. Other than that, I can’t speak for others, but I particularly prefer to use native layer than these compatibility masks (just like using Jquery for something that solves with JS, for example). But I understand perfectly well that everyone knows what they do best with their experience. I know I’ll probably never need a PDO for anything, but I respect who you prefer. I just can’t imagine that this whole switching bank thing is always normal.
– Bacco
@Bacco, My interpretation was different, I did not see there opposite of what I am saying, in fact what I said is something universal. About PS, this cannot be called a bug, but rather vulnerability. Also, it is quite simple to activate the Prepared statements natively in the PDO. About the bank, I never talked about changing, what I said was that today it is possible that a good developer has to work with more than one bank, at that time the PDO will be a hand in the wheel.
– Marcio Mazzucato