SQL Injection via url [duplicate]

1

At the moment my site is like www.site.com.br/blablabla_id_ 2 to define pages.

I use mysqli to search the database with this id.

$id = $_GET['id'];

$result = mysqli_query($con,"SELECT * FROM post WHERE id_post = '$id'");

if(mysqli_num_rows($result) == 0){

    header("Location: 404.php");

}else{

    //Resto do código

}

Will I have a problem with sql injection?

    
asked by anonymous 07.11.2014 / 21:47

4 answers

3

Putting together what I had already commented on with Q & A pointed out by Marcio, follows a modification that solves the problem in the first two lines of code, saving an unnecessary application layer for the case in question:

mysqli_set_charset( 'utf8' );                   // pode usar 'latin1' ou 'ascii'
$id = mysqli_real_escape_string( $_GET['id'] ); // aqui estamos 100% sanitizados.

$result = mysqli_query($con,"SELECT * FROM post WHERE id_post = '$id'");
if(mysqli_num_rows($result) == 0){
    header("Location: 404.php");
}else{
    //Resto do código
}

Notes:

  • The first line is extremely important to avoid a vulnerability that allows certain characters to escape from sanitization. By setting the correct page, the escape interpretation works as expected.

  • In the second line we do the actual sanitization.

  • It's important to note that although you're working with numeric data, I did not deliberately remove quotation marks from your query as extra protection. If you prefer, you can remove them, but forcing something to $id be even numeric (adding with zero, for example).

08.11.2014 / 03:15
2

Your code is totally vulnerable to SQL injection, so you can use two very useful features to prevent intrusions, input filters and the PDO for your query to be parameterized.

Your code with the use of these features becomes:

$id = filter_input(INPUT_GET, 'id', FILTER_SANITIZE_NUMBER_INT);

// Depois de criar o objeto PDO com o driver do seu banco de dados, utilize o código abaixo

$Ps = $Pdo->prepare('SELECT * FROM post WHERE id_post = :id');

$Ps->execute(array(':id', $id));

if ($Ps->rowCount() == 0) {
    header('Location: 404.php');
    die();
} else {
    // Pelo menos um registro foi localizado
}
    
07.11.2014 / 22:58
2

I would do as the marcio Simao proposed, using PDO, but if in your case it is complex to change all the code from mysqli to PDO, here is 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);
    ?>
    
08.11.2014 / 00:03
1

Friend, to solve this problem and make your life easier in relation to database queries among other functions, try using "PHP PDO", an example that would solve your problem would be this:


prepare("INSERT INTO REGISTRY (name, value) VALUES (:name, :value)");
$stmt->bindParam(':name', $name);
$stmt->bindParam(':value', $value);

// insert one row
$name = 'one';
$value = 1;
$stmt->execute();

// insert another row with different values
$name = 'two';
$value = 2;
$stmt->execute();
?>

Take a look at the Prepared Statements PHP documentation and in the PDO

    
07.11.2014 / 22:45