Joven hacker sonriendo

Hackeamos su software

cero falsos positivos

Inteligencia experta + automatización eficaz

Prevenir Inyección SQL

Nuestros ethical hackers explican cómo evitar vulnerabilidades de seguridad mediante la programación segura en el framework Yii al prevenir las inyecciones SQL. La validación de entradas a la aplicación es un proceso fundamental para crear aplicaciones seguras y robustas.

Necesidad

Prevenir que se produzca una inyección SQL en el Framework Yii.

Contexto

A continuación se describen las circunstancias bajo las cuales la siguiente solución tiene sentido:

  1. Se utiliza el lenguaje de programación PHP.

  2. Se utiliza el framework de desarrollo Yii [1].

  3. La aplicación requiere de una conexión a una base de datos relacional a través del lenguaje de consulta SQL.

Solución

Las entradas en las aplicaciones representan una de las fuentes más comunes de vulnerabilidades. Para construir aplicaciones computacionalmente seguras se recomienda realizar un proceso de validación en cada una de las entradas, para evitar diversos tipos de ataque. Entre ellos podemos encontrar la inyección de sentencias SQL o SQLi. Esta vulnerabilidad se produce cuando una aplicación que usa una base de datos relacional no valida apropiadamente sus entradas permitiendo que el usuario ejecute consultas SQL sin ningún tipo de restricción.

Un ejemplo de código vulnerable a una inyección SQL en Yii framework se aprecia en el siguiente ejemplo:

insecure.php
1
2
3
4
5
6
<?php
// WARNING: Insecure code
Yii::app()->db
  ->createCommand("DELETE FROM mytable WHERE id = " . $_GET['id'])
  ->execute();
$comments = Comment::model->findAll("user_id = " . $_GET['id']);

En el ejemplo anterior no se realiza ninguna validación de la variable de entrada id, permitiendo esto ingresar código SQL arbitrario. Si en el primer ejemplo el valor de la variable id fuese 4 OR 1=1 # ocasionaría que todos los registros de la tabla sean borrados. En el segundo ejemplo si el valor de la variable id fuera de la forma 9 UNION SELECT 1,2,3 — -, se podrían obtener todos los registros.

Para prevenir inyecciones de código en el framework Yii se recomienda el uso del método findAllByAttributes. Esto se realiza en caso de que se desee realizar búsquedas por criterios simples.

1
Comment::model->findAllByAttributes(array("post_id" => $postId, "author_id" => $ids));
  1. En caso de que se construya una consulta SQL dinámica usando los datos de entrada del usuario, la validación puede realizarse de dos maneras:

    • Escapando cada parámetro (no recomendado).

    • Usando sentencias parametrizadas (recomendado).

  2. En una sentencia parametrizada se crea un consulta SQL dinámica declarando las variables a ser usadas, estas sentencias son compiladas en el servidor protegiendo de cualquier riesgo de inyección SQL en los parámetros.

1
2
3
4
5
6
7
<?php
// WARNING: Insecure code
$date = $_GET['date'];
$text = $_GET['text'];
$sql = "SELECT CONCAT(prefix, title) AS title, author_id, post_id, submit_date
  FROM t_comment
  WHERE (date > '{$date}' OR date IS NULL) AND title LIKE '%{$text}%'";

En en el ejemplo anterior se hace uso de una sentencia SQL dinámica la cual es vulnerable a una inyección SQL, para el uso de sentencias SQL parametrizadas se usa parámetros de la forma :param::

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
<?php
$date = $_GET['date'];
$text = $_GET['text'];
$sql = "SELECT CONCAT(prefix, title) AS title, author_id, post_id, date "
  . "FROM t_comment "
  . "WHERE (date > :date OR date IS NULL) AND title LIKE :text"
  $command = Yii::app()->db->createCommand($sql);
$command->bindParam(":date", $date, PDO::PARAM_STR);
$command->bindParam(":text", "%{$text}%", PDO::PARAM_STR);
$results = $command->execute();
  1. Otra forma de usar sentencias parametrizadas es:

1
2
3
4
5
6
7
8
<?php
$date = $_GET['date'];
$text = $_GET['text'];
$sql = "SELECT CONCAT(prefix, title) AS title, author_id, post_id, date "
  . "FROM t_comment "
  . "WHERE (date > :date OR date IS NULL) AND title LIKE :text"
  $command = Yii::app()->db->createCommand($sql);
$results = $command->execute(array(':date' => $date, ':text' => "%{$text}%"));



Haz un comentario

Estado de los servicios - Términos de Uso