Fluid Attacks logo
Login
Contact Us
Young hacker smiling
Zero false positives

Expert intelligence + effective automation

Contact logo Contact Us
GET A DEMO

Prevenir Inyección SQL

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

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.

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

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

<?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}%"));

Service status - Terms of Use