#1 [PHP] Tu codigo es seguro? Consejos de seguridad PREMISA FUNDAMENTAL
- En ingles se dice: "Filter input, Escape output". Seria, filtrar la informacion que entra, y "escapar" la info que se muestra. (nose como traducir escape
)Esto significa que hay que verificar toda la informacion que ingresa el usuario para ver que sea SOLO la que nosotros quremos. Este es el punto mas importante en la seguridad de nuestro script/programa.
Tambien significa que hay que tomar las medidas necesarias, para que cuando mandemos informacion al usuario, esta se muestre sin problemas de seguridad.
Para que quede claro...no confien en ninguna informacion ingresada por el usuario. Verifiquen todo ustedes mismos!
Si no lo hacemos, el usuario puede ingresar (a proposito o no) informacion que hara actuar a nuestro script de forma distinta a la que nosotros queremos. Este puede llevar a que nos hackeen el sitio, la base de datos, el servidor, etc...
VALIDAR FORMULARIOS
- Siempre filtren/validen toda la info que ingresen los usuarios. Si solo tienen que ingresar su edad (un numero entero) validen que solo esten ingresando numeros. Si solo tienen que ingresar su nombre...entonces no necesitan ingresar el simbolo ?. Validen eso tambien.
- Para Validar numeros usen la funcion ctype_digit(), is_numeric() o expresiones regulares para cosas mas complejas.
- Para validar caracteres usen ctype_alnum() o ctype_alpha().
- Validen el formato de las direcciones de email. Para eso pueden usar expresiones regulares.
- Cuando tengan que asegurarse que un numero es entero, otra opcion es usar (int) antes de la variable (Type Casting). Eso se va a asegurar que todo dato en esa variable sea un entero.
- No usen solamente Javascript para validar datos. Javascript no ofrece real seguridad. Siempre validen todos sus datos del lado del servidor (con PHP en este caso).
Lo ideal es validar los datos con Javascript Y PHP. Javascript lo hace rapido,facil y lindo para el usuario. Pero PHP se encarga de que nadie nos hackee

(Javascript puede ser deshabilitado con unos clicks en su navegador)
- Comprueben que el formulario es enviado desde su sitio chequeando el valor de $_SERVER['HTTP_REFERER'] (Gracias Tux). Esto se hace simplemente comprobando que el valor de HTTP_REFERER sea igual al nombre de nuestro sitio.
Tengan en cuenta que esto no es muy confiable, ya que el valor enviado por los navegadores puede ser facilmente altereado por cualquier usuario. Igualmente, es una medida mas que podemos implementar para, entre otras cosas, frenar el spam desde nuestros formularios.
Ejemplo de Type Casting:
$numero = 10.90;
$variable = (int) $numero;
echo $variable; // Imprime 10
$numero = 'Nicolas';
$variable = (int) $numero;
echo $variable; // Imprime 0
if (ctype_digit($edad)) {
echo 'La edad es valida.';
} else {
echo 'La edad NO es valida.';
}
if (!preg_match("/^[a-zA-Z0-9_\.\-]+@[a-zA-Z0-9\-]+\.[a-zA-Z0-9\-\.]+$/", $email)) {
exit('El formate del email ingresado no es correcto.');
}
$hosts_permitidos = array('www.misitio.com.ar', 'misitio.com.ar');
$referer = $_SERVER['HTTP_REFERER'];
$temp_referer = explode('/', $referer);
if (!in_array($temp_referer[2], $hosts_permitidos)) {
// ESTE HOST NO TIENE PERMISO
exit('No tenes permiso para acceder al formulario.');
}
http://ar.php.net/manual/en/function.ctype-digit.php
http://ar.php.net/manual/en/function.ctype-alnum.php
http://ar.php.net/manual/en/function.ctype-alpha.php
http://ar2.php.net/manual/en/reserved.variables.php
SQL INJECTIONS
- Usar mysql_real_ecape_string() cuando se ingresa info a la base de datos.
Si usan una base de datos distinta a MySQl, ver si hay alguna funcion nativa para ella o usar addslahses()
Ejemplo:
$nombre = mysql_real_escape_string($_POST['nombre']);
mysql_query("SELECT campo FROM tabla WHERE nombre='$nombre'");
http://en.wikipedia.org/wiki/SQL_injection
http://ar.php.net/manual/en/security...-injection.php
- Poner comillas cuando armen un query en MySQL y esten ingresando datos que no sean numeros enteros:
// Ejemplo 1
$query("SELECT * FROM tabla WHERE id='$id'");
// Ejemplo 2
$query("SELECT * FROM tabla WHERE id=$id");
Es una recomendacion de la gente de MySQL: http://dev.mysql.com/doc/refman/4.1/...uidelines.html
CROSS SITE SCRIPTING (XSS)
- Cuando muestren datos al usuario "escapeen" (nose que palabra usar) los datos con, por ejemplo: htmlentities(). Esto ayuda a prevenir los XSS.
Links:
http://es.wikipedia.org/wiki/XSS
http://www.cgisecurity.com/articles/xss-faq.shtml
http://shiflett.org/archive/177
ARCHIVOS SEGUROS FUERA DEL ROOT
- No guarden archivos con informacion importante en el root. Guardenlos afuera y usen include() o require() para usarlos.
Para los que no saben, todo lo que este en el ROOT (directorio principal de su servidor) puede ser accedido desde internet.
Entonces, si ustedes guardan la informacion de su base de datos aca: /db/db.php
Yo puedo accederla desde aca: http://www.tusitio.com/db/db.php
Lo que tienen que hacer es ponerla fuera del alcance del publico. Fuera del root.
- Si van a incluir archivos asegurense de que no estan incluyendo archivos que cualquiera pueda leer en texto plano. No usen la extension .inc solamente (a menos que usen .htaccess o similar para protegerla). En cambio usen .inc.php. Ej: /db.inc.php
PASSWORDS
- Si van a guardar passwords en su DB (base de datos) encriptenlos. La funcion md5() puede servir, pero ya no se recomienda. Es mejor usar sha1().
SUBIR ARCHIVOS
- Cuando le den la posibilidad al usuario de subir un archivo a su sitio, asegurense de:
* solo suban archivos permitidos y restringan el accesso a cualquier otro tipo de archivo, como los .exe.
* Usen la funcion is_uploaded_file() antes de mover el archivo o de ingresarlo a la db. Esa funcion comprueba que el archivo existe de verdad y que no es un intento de "hacking".
REGISTER GLOBALS
- Desactivar register globals.
Para los que no saben, register globals es una opcion de PHP que cuando esta activada, se encarga de inicializar las variables automaticamente.
Osea...que si yo envio un formulario con un campo 'nombre' y quiero imprimir el nombre en la pagina suiguiente, solo tendria que hacer: echo $nombre;
...en vez de : echo $_POST['nombre'];
Hay mucha info por todos lados sobre porque esto es malo para la seguridad, asi que no voy a entrar en detalles. Solo acuerdense de acceder a las variables de esta forma: $_POST['variable'] o $_GET['variable'] o $_SESSION['variable'] o $_FILES['variable']
Links:
http://ar.php.net/manual/en/security.globals.php
LIBROS DE SEGURIDAD EN PHP
- Lamentablemente no conozco ningun buen libro de seguridad en PHP que este en castellano, asi que les recomiendo estos que estan en ingles:
* Essential PHP security by Chris Shiflett / http://phpsecurity.org/
* php|architect's Guide to PHP Security / http://www.phparch.com/shop_product.php?itemid=98
Espero le sirva a alguno. A mi me hubiera servido saberlo cuando empeze.
De mas esta decir que no es una guia completa, ni un tutorial. Solo algunos tips/consejos basicos de seguridad en PHP.
Hay muchos mas temas a tocar y en mas detalle, quizas lo podamos ir completando entre todos.
Saludos!
Nico
Ya la agregue al post original asi queda todo junto.