Php es un lenguaje potente, y el interprete puede ejecutar comandos en el sistema del servidor web o puede abrir conexiones de red, lo que hace al lenguaje inseguro si se omiten ciertas reglas de seguridad, tanto en el servido como en la aplicación o página web que se ejecute. En éste caso hablaremos sobre la el lado del desarrollador, la persona encargada de preparar la aplicación o la página web.
Sobre el sistema de archivos:
PHP ofrece la posibilidad de abrir, escribir, eliminar, mover, copiar y hacer una infinidad de acciones con los archivos del servidor, una parte de la responsabilidad de estos permisos recae en el administrador del servidor (No siempre el desarrollador) y la otra sobre los hombros del desarrollador.
Imaginemos un script capas de eliminar un archivo cualquiera que solo reciba por parámetro el nombre, el desarrollador tendería a pensar que con recibir el nombre es suficiente para eliminarlo;
Este script esta esperando un nombre tipo “archivo.txt”, pero que pasaría si en lugar de eso se ingresara un nombre “../index.php”?
Como arreglar esto?. Hay que estar seguros que el nombre enviados desde el formulario no contiene ninguna dirección o parámetros de dirección, como lo son “..” y “/”, una forma rápida sería:
Otro detalle a tener en cuenta es que PHP usa funciones de C para administrar archivos lo cual nos lleva a la posibilidad de poder utilizar los Bytes nulos (\0), que son la forma en como c da como finalizada un string, aquí un ejemplo de esta vulnerabilidad:
Por consiguiente cuando se utilizan funciones que manipulan archivos hay que validarlos correctamente, he aquí el script mejorado:
Sobre las Bases de Datos:
Hoy en día difícilmente construyamos una aplicación sin tener una base de datos por lo cual considero importante agregar éste apartado.
Si la base de datos corre sobre diferentes servidores la mejor forma de comunicación es usando ssh para encriptar la comunicación entre la base de datos y el servidor web.
Al conectarse con la base de datos hay que tomar en cuenta los permisos que tiene el usuario con que se conecta, si el usuario es el dueño de la base de datos (Por lo general es el que ejecuta la creación del esquema) tiene control total sobre la base de datos, pudiendo eliminar tablas completas e incluso la base de datos a su antojo, es mejor tener un usuario que solo pueda hacer los INSERT, DELETE y UPDATE sobre las tablas, así dificultas más el trabajo del atacante.
Almacenar los datos mas importantes encriptados, como son las contraseñas en la base de datos, si la base de datos cae en malas manos no queremos que ellos sepan las contraseñas de nuestros clientes por supuesto, esta es una buena forma de hacerlo, no recomiendo nunca usar un mecanismo genérico para la encriptación, por ejemplo md5 y sha1, que hay varias paginas que las desencriptan en un par de segundos como http://md5.rednoize.com/, prefiero usar crypt() que permite usar una semilla o si prefieren pueden usar algo mas elaborado como http://www.emm-gfx.net/2008/11/encriptar-y-desencriptar-cadena-php/.
Limpiar las variables que vengan del usuario hacia la base de datos, para evitar inyecciones SQL, en muchas ocasiones solemos dejar el código en espera de variables exactas, por ejemplo números si estamos en una paginado, veamos a continuación:
Si en este caso la variable $_GET['page'] fuera
1; delete from mi_tabla where id=12;
Eliminaría el registro de esa tabla donde el id fuera 12, claro supondría que el usuario supiera el nombre de la tabla, el del campo id y que acertara a una id que existiera pero con un poco de tiempo lo lograrías, igual puede ejecutar mas comandos peligrosos incluso llegar a ejecutar comandos a nivel de servidor.
Para evitar este tipo de detalles es necesario verificar las variables que vienen del usuario, verificando el tipo de dato que se espera, en el caso anterior era un dígito, podría utilizarse la función is_numeric() para estar seguro, dejando el script de la siguiente forma:
En el caso que estemos hablando de una string al momento de recibirla hay que pasarla por el filtro del driver de conexión que estemos usando para evitar que las comillas corten nuestra query:
Nota: Si usas mysqli en lugar de mysql sería $var = mysqli::escape_string($_GET['var']);
Sobre el reporte de errores:
Muchas veces mientras desarrollamos necesitamos saber que sucede con la aplicación para poder reparar un error, por lo cual utilizamos los errores para guiarnos, en desarrollo esta bien hacer eso, pero en producción es una debilidad mostrar errores al usuario pues puede recolectar información valiosa sobre nuestro código que luego utilizaría en nuestra contra.
En ocasiones se utiliza cosas como die(mysql_error()) para saber que pasó en una query a la base de datos que no funcionó como lo esperábamos, al momento de sacar esa aplicación a producción debemos de deshacernos de todas esas muestras de errores mostrando solamente errores personalizados como die('Ocurrió un error interno del servidor, estamos trabajando en eso, disculpe').
Igual el interprete de PHP suele mostrar warnings y errores, por lo cuál deberíamos usar, si el servidor lo permite:
Sobre XSS (Cross-Site Scripting):
Este ataque consiste en ejecutar código html o javascript en nuestra página, eso sucede cuando nosotros imprimimos una variable que contiene html peligroso que el navegador interpreta, por ejemplo:
Sí $_GET['msj'] llevara “<script type='text/javascript'>alert('hola')</script>” cuando se imprimiera aparecería una ventana en el navegador del cliente diciendo hola, parece bastante débil, pero con ese tipo de ataques pueden llegar a cambiar la apariencia de nuestra página o hasta robar las cookies de nuestros usuarios, esa variable también pudo haber sido ingresada a la base de datos y al salir seguiría teniendo el mismo poder, para evitar este tipo de ataques habría que limpiar la variable como aparece a continuación:
htmlspecialchars() convierte los caracteres peligrosos en sus valores html evitando que se puedan ejecutar, si el valor se fuera a ingresar a la base de datos sería aquí:
Claro, recordemos que ahí también tendríamos que ponerle el filtro de inyección sql para estar completamente seguros, pero para el ejemplo es válido.
Son unos cuantos tips de todos los que tenemos que tener en cuenta a la hora de programar, porque hay una gran cantidad de ataques mas, pero son los principales, espero que les sea de ayuda.
Excelente artículo!
ResponderEliminarGracias brother
Eliminar