Vous êtes sur la page 1sur 9

SEGURIDAD EN PHP ORIENTADO A OBJETOS PHP es un lenguaje muy fcil a aprender, y muchos programadores lo aprenden como manera de agregar

interactividad a sus Sitio Web. Desafortunadamente, eso significa a menudo los programadores de PHP, especialmente sos ms nuevos al desarrollo web, cometen ciertos riesgos de seguridad y desaprovechan el potencial que sus usos pueden contener. Aqu estn algunos de los problemas ms comunes de seguridad y cmo evitarlos.

Regla nmero uno: Nunca, confiar en los usuarios


Nunca debes confiar en que los usuarios te van a mandar los datos que tu esperas. Mucha gente responde a esto con algo comoOh, nadie estara interesado en mi sitio. Esta afirmacin no podra ser mas incorrecta , siempre hay un usuario malvolo que quiere explotar un agujero de seguridad ademas los problemas pueden presentarse fcilmente debido a un usuario que hace algo mal inintencionalmente. Por todo esto la regla de todo desarrollador web tiene que ser "Nunca, confiar en los usuarios" . Asumir que cada pieza de datos que tu sitio recoge de un usuario puede convertirse en un agujero de seguridad, siempre. Si la seguridad de tu sitio web es importante para ti, este un buen puntopara comenzar a aprender. Sera conveniente tener una hoja de seguridad para PHP al lado de tu escritorio con los puntos mas importantes en texto negrita grande.
Variables globales

En muchas lenguajes debes crear explcitamente un variable para utilizarlas. En PHP, hay una opcin, las register_globals, que puedes fijar en php.ini y que permite que utilices variables globales. Considera el cdigo siguiente: if ($password == my_password) { $authorized = 1; } if ($authorized == 1) { echo Mis cosas importantes ; } A muchos de vosotrosos puede parecer que este cdigo esta funcionando perfectamente. Sin embargo, si un servidor tiene register_globals encendidos, entonces simplemente agregando? authorized=1 al URL dar a cualquier persona el acceso libre a exactamentelo que no quisieras que todo el mundo viera. ste es uno de los problemas mas comunes de la seguridad de PHP. Afortunadamente, esto tiene un par de soluciones simples y posibles. La primera, y quizs la mejor, es fijar desactivar register_globals. La segunda es asegurarse de que utilizas

solamente las variables que has fijado explcitamente t mismo. En el ejemplo anterior, eso significara la adicin $authorized = 0; al principio de la escritura: $authorized = 0; if ($password == my_password) { $authorized = 1; } if ($authorized == 1) { echo Lots of important stuff.; }

Lo primero que tenemos que hacer para que nuestra aplicacin sea segura, es asegurarnos que comprobamos todos los datos que introduce el visitante y actuar si no es un dato esperado por la aplicacin. El siguiente paso es comprobar si nuestra aplicacin es segura, pero, como lo comprobamos? Existe un proyecto llamado phpsecinfo, que nos comprueba la web en busca de vulnerabilidades en formato de phpinfo. Para poder usarlo no hay ms que descargarlo de la web del proyecto, descomprimirlo en una carpeta de nuestro servidor (accesible desde la web) y llamar al script desde el navegador. Tambin podemos hacer un script propio (suponiendo que lo hemos extraido en la carpeta PhpSecInfo): Cita:<?php require_once("PhpSecInfo/PhpSecInfo.php"); phpsecinfo(); ?>

Hay que tener mucho cuidado de no dejarla accesible por nadie (inluidos los robots de los buscadores) ya que mostraramos nuestras vulnerabilidades al pblico. El resultado ser ms o menos as:

Cabe destacar que es un test sencillo para saber si nuestra web cumple con un mnimo de seguridad. Que no nos d ningn error no quiere decir que nuestra aplicacin sea totalmente segura.

Proteccin contra la inyeccin de cdigo SQL


Es muy comn trabajar contra una base de datos (MySQL, PostgreSQL, Oracle, etc.) y estas consultas dependen de parmetros llegados desde GET o POST, por lo que permitimos al usuario de cada web que en cierta manera modifique las consultas SQL de nuestra web. Esto podra provocar que un usuario que construya una consulta SQL malintencionada pudiera obtener resultados indeseados, como poder hacer un login en una zona restringida de nuestra web sin conocer ningn usuario / contrasea. Supongamos la siguiente situacin: tenemos un nombre de usuario pruebas y una contrasea clave_pruebas guardados en base de datos. Para realizar la identificador obtenemos los parmetros por POST mediante las variables $_POST['usuario'] y $_POST['clave']. Tras ello realizamos la siguiente consulta SQL:
1 mysql_query('select id from usuariosWeb where usuario = '".$_POST['usuario']."' and password = '".$_POST['clave']."'');

Si existe un usuario con ese nombre y usuario, es que la identificacin es correcta y por tanto debemos hacer el login. Pero sin embargo, si construysemos el siguiente parmetro
1 $_POST['clave'] ="m' or 1='1"

podemos observar que nos devuelve un valor vlido para identificarse conociendo slo el nombre de usuario. Para solucionarlo, tenemos diversos mtodos pero lo ms cmodo es substituir las comillas simples y dobles de todos los parmetros parmetros POST mediante el siguiente cdigo:

1 foreach($_POST as $key => $value) { 2 $_POST[$key] = str_replace("'","",$value); 3 4} $_POST[$key] = str_replace('"','',$value);

Guardar contraseas, nmeros de tarjeta de crdito, direccin de correo, etc. de forma segura con MD5 SHA1
Para guardar las contraseas de los usuarios en las bases de datos debemos guardarlas de manera que no puedan ser visibles a simple vista ya que si alguna persona malintencionada consiguiera acceder a la base de datos, adems de conseguir el control de nuestra web, adems tendr acceso a informacin sensible de los usuarios que nos visitan. Para ello podemos dificultarlo mediante los resmenes hash MD5 o SHA-1, que aunque se tratan de algoritmos crackeados, por lo menos no mostraremos como texto plano esta informacin. Ejemplo:
01 $a = "clave_pruebas"; 02 03 echo "clave original: ".$a." "; 04 05 $b = md5($a); 06 07 echo "Hash MD5 de la clave original: ".$b." "; 08 09 $c = sha1($a); 10 11 echo "Hash SHA-1 de la clave original: ".$c." ";

Como podemos ver, con ello conseguimos ocultar mnimamente la contrasea de cada usuario. Cuando un usuario se identifique con su contrasea, realizaremos el clculo del hash de su contrasea y compararemos contra la base de datos, no el texto plano de la contrasea, si no del hash.

Uso de variables de sesin y no de cookies


Normalmente, alguna zona de nuestra web necesite acceso mediante usuario y contrasea. Para que el usuario no tenga que introducirlas repetidamente podemos guardarla mediante cookies pero es una prctica muy insegura ya que si lo hiciramos, esta informacin es transmitida mediante la red en texto plano y podra ser leda por cualquier persona que realice un sniffing de red o que lea las cookies guardadas en nuestro ordenador mediante un virus o troyano.

Por ello lo mejor es hacer uso de las variables de sesin. Estas variables se guardan en el servidor por lo que en cualquier caso, la informacin transmitida slo es sensible la primera vez que se enva y no las sucesivas veces (por tanto esto sera evitable haciendo uso del protocolo HTTPS en vez de HTTP). Como ejemplo del usuario de variables de sesin, haremos uso de dos archivos. En el primero creamos una variable de sesin:
1 session_start(); 2 $_SESSION['clave'] = "clave_pruebas";

y en el segundo mostramos el valor en pantalla.


1 session_start(); 2 echo $_SESSION['clave'];

Suplantacin de sesiones (Session hijacking o Man in the middle)


Del uso de variables de sesin se deriva otra posible brecha de seguridad que es una persona malintencionada intente suplantar el cliente de cara al servidor. Cuando iniciamos una sesin, creamos una cookie con un identificador nico para esa sesin. Si una persona malintencionada interceptase ese identificador nico y mandase esa cookie al servidor, podra suplantar nuestra identidad y tener acceso a nuestras zonas restringidas de la web. Lo solucin ideal sera el uso del protocolo HTTPS que encriptara toda nuestra conexin, pero si esto no es posible, podemos crear una serie de comprobaciones en las que intentemos asegurarnos de la real identidad de cada usuario. Para ello podemos guardar una serie de variables de sesin de los datos que el usuario nos proporciona en cada visita, como son la direccin IP o la informacin de su navegador, etc. Si estos cambian significara que es un intento de session hijacking y por tanto es un usuario que realiza un ataque. En el siguiente ejemplo tenemos dos archivos, en el que en el primer archivo realizamos un login satisfactorio y guardamos los datos iniciales de direccin IP y tipo del navegador con el que lo hemos hecho:
1 session_start(); 2 $_SESSION['REMOTE_ADDR'] = $_SERVER['REMOTE_ADDR']; 3 $_SESSION['HTTP_USER_AGENT'] = $_SERVER['HTTP_USER_AGENT'];

En pantallas posteriores, comprobaremos si en cada pantalla los datos actuales de direccin IP y datos del navegador se corresponden con los que se realiz el login como usuario en la web:
1 session_start(); if($_SESSION['REMOTE_ADDR'] != $_SERVER['REMOTE_ADDR'] || 2 $_SESSION['HTTP_USER_AGENT'] != $_SERVER['HTTP_USER_AGENT']) {

3 4}

exit();

Parmetros GET/POST explotables


Para finalizar, si hacemos uso de parmetros GET y POST deberemos comprobar siempre que se correspondan con el usuario actual o si tiene permisos. Por ejemplo, si tenemos un archivo que edita productos llamado editarProducto.php y recibe el parmetro GET idproducto, que se corresponde con el identificador nico del producto a editar y llamamos al archivo de la siguiente manera:
1 http://www.miweb.com/editarProducto.php?idproducto=15

deberemos comprobar en cualquier caso que en primer lugar seamos un usuario registrado y logueado y despus que el producto de identificador nico 15 corresponde a uno de los productos del usuario logueado.

Seguridad con PHP / MySQL


Al montar un servidor o programar un sitio web basado en PHP orientado a objetos y MySQL, hay que tener en consideracin algunos conceptos de seguridad. En esta ocasin, hablar de 3 problemas de seguridad bsicos:

Los usuarios y sus privilegios (en MySQL) La configuracin de apache El filtrado de formularios y URLs

Este post est enfocado, principalmente, a quienes pretenden montar un servidor en su computador (localhost) pues, por lo menos en los servidores pagados, la seguridad con los privilegios de MySQL est implementada.

Los problemas de seguridad


Los usuarios y sus privilegios (en MySQL)

El principal problema de montar un servidor en casa (localhost), es que los software que se utilizan para esto EasyPHP, Appserv, etc vienen con usuarios por defecto el famoso _root sin contrasea. Esto implica que cualquier persona con un poco de conocimientos de hackeo, pueda botar la base de datos u obtener informacin de ella si es que el usuario por defecto no se cambia (ya que el hacker sabra que el nombre de usuario es _root y no tiene contrasea).

La configuracin de apache

Adems de eso, est el problema de configuracin de apache, pues appserv, por ejemplo, establece todas las variables como globales por defecto (por ejemplo, si recibo una variable por el metodo POST, simplemente escribo echo $nombre_de_la_variable para mostrarla en pantalla). Si bien las variables globales son ms cmodas, implican riesgos en seguridad y confusin, porque si se necesita recibir la variable admin_pass por el mtodo POST y el hacker escribe una url como index.php?admin_pass=miclave, se estara recibiendo la variable por otro mtodo y poniendo en riesgo la seguridad del sitio.
El filtrado de formularios y URLs

Otro problema es la seguridad con PHP, pues si no se filtra la informacin recibida a travs de formularios o de la URL, se esta dando pie para que gente mal intencionada ejecute scripts que pongan en riesgo la seguridad de nuestro sitio.

Las soluciones
Antes que nada, se debe definir el software a utilizar. Por mi parte, y por conceptos de seguridad, yo recomiendo EasyPHP, pues es mucho mas paranoico que Appserv, y viene mucho ms limitado en conceptos de seguridad y mensajes de error; es decir, que viene mejor configurado (en conceptos de seguridad) por defecto, y no hay que preocuparse de cambiar muchas cosas. Por esto, la siguiente solucin la veremos especficamente para EasyPHP (aunque tambin se aplica para Appserv).
Los usuarios y sus privilegios (en MySQL)

Lo primero que se debera hacer, al montar un servidor en casa, es definir un usuario que tenga todos los privilegios necesarios para administrar nuestro sitio. Para esto, hay que realizar las siguientes operaciones:
1. Ir a PhpMyAdmin (la administracin de MySQL) y crear un nuevo usuario (o modificar _root) con un username y un password que no sea tan obvio. 2. Abrir el archivo de configuracin llamado config.inc.php (ubicado en EasyPHP18\phpmyadmin\), las variables $cfg['Servers'][$i]['user'] = _root; y $cfg['Servers'][$i]['password'] = ;, y poner ah el username y password definido para el administrador de MySQL en el paso anterior. 3. Eliminar el usuario _root (en el caso de haber creado otro usuario para la administracin), pues si se deja, el sitio seguir siendo inseguro.

A partir de este punto, si se quiere, se puede crear otro usuario con menos privilegios (por ejemplo que no pueda crear o eliminar tablas), que sea con el que nos conectemos desde el sitio y, de esta manera, correr menos riesgos.

La configuracin de apache

El tema de la configuracin pasa, primero, por elegir el servidor adecuado. En el caso de EasyPHP, la configuracin por defecto es bastante buena si hablamos de seguridad, pero hay que fijarse bien (a la hora de programar) en solucionar todos los errores y en los mensajes de error que devuelve, pues aveces dice imposible conectar a la base de datos MiBase, por lo que estaramos entregando informacin privada el importante. Hay otros conceptos que son ms tcnicos (y que no sern abordados en este post), como la cantidad de usuarios mximos conectados a la base de datos, y que hacer cuando se sobrepasan los lmites; los tamaos de los archivos que se pueden subir; los privilegios de las carpetas, etc que se deben tener en cuenta a la hora de configurar el servidor.
El filtrado de formularios y URLs

Personalmente, he ido creando mis propias funciones de seguridad para filtrar las entradas por cookies, formularios, y los mtodos GET y POST. Las funciones, las almaceno en un archivo validar.php y luego, simplemente, las inserto al principio de cada uno de mis archivos donde necesite validar variables (a travs del comando include(validar.php);). La manera de utilizarlas, es definiendo las variables de la manera:
$mi_variable=varpost("nombre_de_la_variable_a_recibir" , "valor en caso de no encontrarse la variable" , largo en caracteres);

Despus de eso, solo queda utilizar $mi_variable en mi archivo php. Esto asegura que la variable quedar definida (y no aparecern mensajes de error por variables no definidas). Tambin asegura recibir la variable por el mtodo especificado (y no por otro) y definirle un tamao mximo (para no recibir, por ejemplo, mensajes de 12404502345023 caracteres). Las funciones son las siguientes:
function validar( $variable, $tam ){ $va=htmlentities($variable,ENT_QUOTES,"UTF-8"); mysql_escape_string($va); $va=substr ($va, 0, $tam); return $va; } function varget($valor, $vacio, $tam){ if (empty($_GET[$valor])) { $res=$vacio; } else { $res=validar($_GET[$valor],$tam); } return $res; } function varpost($valor, $vacio, $tam){

if (empty($_POST[$valor])) { $res=$vacio; } else { $res=validar($_POST[$valor],$tam); } return $res; } function varcookie($valor, $vacio, $tam){ if (empty($_COOKIE[$valor])) { $res=$vacio; } else { $res=validar($_COOKIE[$valor],$tam); } return $res; } function varsess($valor, $vacio, $tam){ if (empty($_SESSION[$valor])) { $res=$vacio; } else { $res=validar($_SESSION[$valor],$tam); } return $res; }

Conclusin
Estas son algunas de las medidas de seguridad bsicas para no pasar por inculto a la hora de disear un sitio y de montar un servidor casero. Espero que quien las lea las tome en cuenta, las aproveche; mejoren las funciones de seguridad y las adecuen para satisfacer las necesidades de su sitio.