Cuarta Parte -> Subiendo archivos
Hace algún tiempo, un usuario creó un tema para debatir sobre los riesgos que hay al subir imágenes al servidor y la posibilidad de ejecutar código PHP malicioso por ese medio:
http://www.forosdelweb.com/f18/ataqu...agenes-964823/
Pasaremos este tema por alto, ya que la solución es sencilla y la vimos en la primera parte: "Jamás incluir un archivo sin saber de qué se trata"; aparte, si validamos correctamente la subida, no nos tenemos que preocupar por estas cosas raras.
Lo primero que tenemos que hacer al subir archivos a nuestro servidor es asegurarnos de que se trata de una extensión permitida, después, de ser posible, verificamos que el contenido corresponda a esa extensión y, finalmente,
nunca lo vamos a usar en una sentencia include o require.
Por supuesto, puede haber proyectos en los que tengamos que subir archivos o scripts ejecutables (php, js, html, etc.) y nunca debemos dejarlos accesibles desde URL, forzándolos para descarga cuando sean solicitados.
Cita:
Iniciado por Sugerido por Abimaelrc Usando la librería
Fileinfo podemos obtener más información de los archivos y, en base a eso, determinar las acciones a realizar.
Código PHP:
Ver original// Si vamos a subir imágenes, tenemos que saber cuáles permitir
$extensiones = array('jpg', 'jpeg', 'gif', 'png', 'bmp');
// Verificamos si existe el campo de archivo de nuestro formulario
if( ! isset($_FILES['imagen'])) { // Ups!, no hay archivo
die('No modifiques mi formulario, por favor.'); }
// Ahora revisamos que realmente se subió un archivo
if($_FILES['imagen']['error'] == 4) {
// El error 4 corresponde a campo de archivo vacío
die('Selecciona un archivo de tu PC para subir.'); }
if($_FILES['imagen']['error'] == 0) {
// El error 0 quiere decir que se subió el archivo correctamente
// Obtenemos la extensión, en minúsculas para poder comparar
// Si no sabes que hacen strtolower(), end() o alguna otra función... consulta el manual de PHP
// verificamos que sea una extensión permitida
if( ! in_array($extension, $extensiones)) { die('Sólo se permite subir archivos con estas extensiones: ' . implode(', ', $extensiones); }
// Ahora, con la librería GD verificamos la imagen (o podrías usar imagick)
if($extension == 'jpg' || $extension == 'jpeg') {
$imagen = createimagefromjpeg($_FILE['imagen']['tmp_name']);
} else if($extension == 'gif') {
$imagen = createimagefromgif($_FILE['imagen']['tmp_name']);
}
// Haz lo mismo para png, bmp o cualquier otro archivo de imagen
// Consulta el manual de PHP -> GD para saber más
// Ahora verificamos que el archivo sea realmente una imagen
// Si la función falla, devolverá falso y, aunque podría ser una imagen real que no se reconoció
// correctamente, mejor consideramos que se trata de un intento de ataque :borracho:
if($datos === false) {
// Nótese el triple signo igual, para comparar valor y tipo
die('No se pudo subir la imagen, intenta con otro formato.'); }
// Ok, aquí movemos la imagen a su destino final con move_uploaded_file()
// Y, si corresponde, actualizamos base de datos
// Ojo, hay que revisar si se va a sobreescribir un archivo
// y crear la lógica para renombrar en caso de ser necesario
} else {
// Más info sobre códigos de error subiendo
// archivos en el manual de PHP
die('Hubo un error subiendo la imagen.'); }
Como mencionaba, si vamos a subir archivos que puedan ejecutarse, los guardamos en una ruta no disponible desde URL y forzamos a que sean descargados:
http://www.forosdelweb.com/f18/forza...2/#post2303479 Quinta Parte -> Acceso a datos importantes
Hace algunos ayeres, se tenía la costumbre de guardar la configuración del sitio en archivos con extensiones diferentes de php, tal vez con la finalidad de identificarlos fácilmente, pero esa práctica es un error, ya que los archivos con extensiones no registradas como aplicación podrían mostrarse como archivos de texto o quedar disponibles para descarga.
Entre otras extensiones, solía usarse: inc, dat, cfg, txt, etc.; a PHP no le importa la extensión del archivo, si tiene código PHP válido, lo ejecutará.
De hecho, todavía existen aplicaciones prefabricadas que incurren en esta mala práctica y por ahora no recuerdo alguna.
Supongamos que tenemos un script para guardar la configuración del sitio, llamado config.inc
Código PHP:
Ver original<?php
$dbhost = 'localhost';
$dbuser = 'usuario';
$dbpass = 'contraseña';
// Fin de archivo
Si un usuario malintencionado coloca en la barra de direcciones del navegador sitio.com/config.inc, obtendrá información que le dará acceso a la base de datos.
Cómo soluciono este problema?
- Registra la extensión inc como ejecutable de PHP (no recomendado)
- Modifica tu .htaccess para evitar que los archivos .inc sean accesibles desde URL (no recomendado)
-
NUNCA uses otras extensiones para tus scripts PHP!!!
- En tu servidor de producción debes desactivar todos los mensajes de error, ya que estos podrían revelar información de estos archivos. Si siempre usas la extensión php, codificas correctamente y validas todas tus variables, nunca verás mensajes de error, excepto cuando haya problemas en el servidor.
Otra medida que podemos tomar es evitar acceso por URL a scripts que están pensados exclusivamente para ser incluidos, como el del ejemplo anterior o uno donde tenemos funciones comunes para todo el sitio, etc.
Sólo tenemos que definir una constante (de preferencia) o una variable para saber si el ingreso a los scripts es válido
Código PHP:
Ver original<?php
// index.php - Nuestra página principal
// Establecemos la constante
// Cargar info y establecer conexión a base de datos
include 'config.php';
Código PHP:
Ver original<?php
// config.php y cualquier otro script que no deba accederse por URL
die('No tienes acceso a esta carpeta o archivo.'); }
Igualmente, debes evitar que se liste el contenido de tus carpetas, ya sea creando un index.php vacío en cada carpeta o modificando el .htaccess en la raíz del sitio agregando la siguiente línea:
Cita:
Iniciado por Sugerido por Abimaelrc También es recomendable que archivos importantes estén en una ruta no accesible desde web, por ejemplo:
misitio.com está hospedado en un sistema linux donde la carpeta de usuario es /home/misitio y la carpeta pública (web) es /home/misitio/public_html, entonces, podemos crear una carpeta en el mismo nivel de public_html para almacenar estos archivos, que serían accesibles por script (PHP) pero no directamente desde un navegador, ejemplo: /home/misitio/config
Sexta Parte -> Funciones peligrosas
Directivas include, include_once, require y require_once - Se usan para incluir e interpretar scripts PHP.
Por si todavía no ha quedado claro, nunca se deben incluir archivos que no sabemos su procedencia o mediante variables que no fueron verificadas apropiadamente; así mismo, debemos evitar incluir archivos de otros sitios (include 'http://www.ejemplo.com/script.php';), a menos que sean de fuentes confiables.
eval() - El manual de PHP para esta función hace la siguiente advertencia:
Cita: Precaución
El constructor de lenguaje eval() es muy peligroso porque permite la ejecución de código de PHP arbitrario. Su uso está totalmente desaconsejado. Si se ha verificado cuidadosamente que no existe otra opción que usar este constructor, se ha de poner especial atención en no pasar ninguna información proporcionada por el usuario a esta función sin haberla validado apropiadamente con anterioridad.
Enlace:
http://www.php.net/eval exec(), system() y shell_exec() - Ejecutar comandos.
Básicamente, shell_exec() permite ejecutar comandos directamente relacionados con el sistema operativo, como obtener listado de archivos y carpetas, mientras que exec() y system() permiten ejecutar cualquier comando.
Más info en:
http://www.php.net/exec
No voy a abarcar mucho sobre este tema porque es muy extenso, me voy a limitar a decir que no se deben usar a menos que sea estrictamente necesario y sepas lo que haces. En mi caso, sólo he usado exec() porque debo convertir videos a diferentes formatos mediante ffmpeg y nunca se debe incluir información manipulable por el usuario.
Seguramente hay otras directivas y funciones que comprometen la seguridad del sitio o del servidor mismo al ser usadas sin buena planeación, agrega un comentario si sabes (o tienes duda) de alguna.
-- Continuará --