seguridad en scripts y aplicaciones php

Hora y Fecha: 21 de Mayo de 2007 a las 10:24 am Autor: jorge albaladejo
Categorías:

Hemos visto en publicaciones anteriores cómo conectar a una base de datos mysql desde php, y cómo usar la función mysql_query para consultar datos.

Ahora vamos a hablar de seguridad en php. La aparente sencillez de uso de php muchas veces oculta su potencia, y no tener en cuenta ciertos detalles puede hacer que nuestra aplicación se vaya al traste con un solo ‘click’. Recordemos nuestra anterior función readTable

/* consulta los campos seleccionados de una tabla concreta de la base de datos
*@param table la tabla concreta
*@param fields los campos a consultar
*/
function readTable($table,$fields,$identifier)
{
//variables
$resultsArray = array();
//campos
$fieldsList = "";
foreach($fields as $key=>$value)
{
$fieldsList .= $value . ",";
}
//quitamos la última coma
$fieldsList = substr($fieldsList,0,strlen($fieldsList)-1);
//consulta
$query = "SELECT " . $fieldsList . " FROM " . $table;
$resultset = @mysql_query($query,$identifier);
if (@mysql_num_rows($resultset) > 0)
{
$i = 0;
while ($result = mysql_fetch_array($resultset))
{
$resultsArray[$i] = $result ;
$i++;
}
}
return($resultsArray);
}

Resumiendo, la llamada a la función readTable(’superheroes’,$fields,$token); podría permitir ejecutar código sql que no deseamos, y que podría dejar al aire nuestra aplicación.

Por ejemplo, la llamada
$results = readTable('superheroes, users','*',$token);
Suponiendo que tenemos una tabla llamada users con información personal, claves de acceso, etc, la llamada a esta función ejecutaría la sentencia SQL
$query = "SELECT * FROM superheroes, users";
la cual nos devolvería absolutamente todos los campos de la tabla users

Si nuestro script permite la llamada de esta función con parámetros que se pasan desde la url del navegador, por ejemplo
$results = readTable($_GET["table"],$_GET["fields"],$token);
sería realmente fácil para cualquier hacker no muy experimentado, atacar nuestro sistema con “sql injection”.

Otro ejemplo habitual sucede en las autenticaciones de usuarios. Supongamos que controlamos el acceso de un usuario a una intranet con la siguiente sentencia sql
SELECT * FROM `tabla` WHERE `user` = '$_POST[usuario]' && `pass` = '$_POST[pass]'
la cual recibe valores de un formulario html. Bien, si los datos introducidos por el usuario son
Login: user
Password: ‘|| 1 = ‘1

entonces la consulta quedará así
SELECT * FROM `tabla` WHERE `user` = 'user' && `pass` = '' || 1 = '1'
la cual nos autenticará siempre (|| 1 = ‘1′, es decir, o 1 = 1 siempre dará 1 booleano).
(Ejemplo propuesto por Issel Guberna)

Solución

La solución pasa por filtrar los datos en nuestro script principal, impidiendo que tome datos cualquiera de las variables $_GET[] y $_POST[] que le estén proporcionando datos. Por ejemplo:

$table = $_GET["table"];
list ($table) = split(" ", $table, 1); //nos quedamos con el primer valor posible de tablas
if ($table == "users")
die('no puedes acceder directamente');

Esto es un mero ejemplo, ya que en algunos casos nos interesará consultar los datos de los usuarios y querremos permitir la lectura de ciertos campos. La clave está en hacer un uso inteligente de la carga de parámetros por $_GET, leer únicamente los que sean estrictamente necesarios y filtrarlos para que sólo puedan tomar los valores que queremos permitir, bien con un switch, eliminando ciertas palabras clave de sintaxis sql de la cadena de entrada, etc.




« Anterior post: lectura de datos de una base de datos | Próximo post: clase dbhandler para manejar datos de una base de datos »

Un Comentario para “seguridad en scripts y aplicaciones php”

[…] hemos visto en capítulos anteriores sobre problemas de seguridad y sql injection, hay una serie de aspectos relacionados con la seguridad a tener en cuenta a la hora de diseñar […]

Deja tu comentario

Si tu comentario no aparece inmediatamente no te preocupes, los comentarios se moderan antes de publicarlos por problemas con los spammers. Cuando hayas enviado varios comentarios y seas una persona de confianza, tus comentarios aparecerán inmediatamente sin necesidad de moderación.