2008-09-02 32 views
21

Mi sitio web ha sido recientemente atacado por, lo que me pareció como un código de inocentes:La mejor manera de evitar la inyección de código en PHP

<?php 
    if (isset($ _GET['page'])) { 
    include($ _GET['page'] . ".php"); 
    } else { 
    include("home.php"); 
    } 
?> 

Allí donde no hay llamadas SQL, así que no tenía miedo a la inyección de SQL . Pero, aparentemente, SQL no es el único tipo de inyección.

Este sitio web tiene una explicación y algunos ejemplos de evitar la inyección de código: http://www.theserverpages.com/articles/webmasters/php/security/Code_Injection_Vulnerabilities_Explained.html

¿Cómo proteger el código de inyección de código?

Respuesta

39

Utilice una lista blanca y asegúrese de que la página está en la lista blanca:

$whitelist = array('home', 'page'); 

    if (in_array($_GET['page'], $whitelist)) { 
     include($_GET['page'].'.php'); 
    } else { 
     include('home.php'); 
    } 
+1

Si es posible, evite incluir archivos dinámicamente por completo. 'include', como has experimentado, es casi tan peligroso como' eval'. – tdammers

4

Estoy asumiendo que lidiar con los archivos en el mismo directorio:

<?php 
if (isset($_GET['page']) && !empty($_GET['page'])) { 
    $page = urldecode($_GET['page']); 
    $page = basename($page); 
    $file = dirname(__FILE__) . "/{$page}.php"; 
    if (!file_exists($file)) { 
    $file = dirname(__FILE__) . '/home.php'; 
    } 
} else { 
    $file = dirname(__FILE__) . '/home.php'; 
} 
include $file; 
?> 

Esto no es demasiado bonita, pero debería solucionar el problema.

+0

1. no es necesario 'urldecode' $ _GET. PHP siempre lo descifra por ti. Debería dejar en claro que 'basename' es crucial en este código. Sin él, el atacante podría leer archivos confidenciales de los directorios principales. – Kornel

5

La regla n. ° 1 al aceptar la entrada del usuario siempre es desinfectarla. Aquí, no estás desinfectando tu página con la variable GET antes de pasarla a incluir. Debe realizar una comprobación básica para ver si el archivo existe en su servidor antes de incluirlo.

+1

¡Eso aún no resuelve un ataque de inyección n = n! Para desinfectarlo, debe estar seguro de que la entrada es un archivo seguro y permitido. Solo una lista blanca será suficiente. – DGM

14

Otra forma de desinfectar la entrada es para asegurarse de que sólo los caracteres permitidos (no "/", ", "": ", ...) están en eso. Sin embargo, no use una lista negra para malos personajes, pero una lista blanca de caracteres permitidos:

$page = preg_replace('[^a-zA-Z0-9]', '', $page); 

... seguido de un file_exists.

De esta manera puede asegurarse de que solo se ejecuten las secuencias de comandos que desea ejecutar (por ejemplo, esto excluiría un "blabla.inc.php", porque "." No está permitido).

Nota: Esto es como un "truco", porque entonces el usuario podría ejecutar "h.o.m.e" y le daría a la página "de inicio", porque lo único que hace es eliminar todos los caracteres prohibidos. No tiene la intención de detener a los "listos" que quieren cosas lindas con tu página, pero detendrá a la gente haciendo cosas realmente malas.

Por cierto: Otra cosa que podría hacer que en .htaccess archivo es prevenir intentos de ataque obvias:

RewriteEngine on 
RewriteCond %{QUERY_STRING} http[:%] [NC] 
RewriteRule .* /–http– [F,NC] 
RewriteRule http: /–http– [F,NC] 

De esta manera todos los accesos a las páginas con "http:" url (y cadena de consulta) como resultado un mensaje de error "Prohibido", que ni siquiera llega al script php. Eso resulta en menos carga del servidor.

Sin embargo, tenga en cuenta que no se permite "http" en la cadena de consulta. Su sitio web PUEDE PEDIRLO en algunos casos (quizás al completar un formulario).

BTW: Si puede leer alemán: También tengo un blog post sobre ese tema.

+0

Ahora poco sobre los archivos htaccess. Tengo algo que se parece a eso, para un sistema de enrutamiento que podría usar caracteres especiales y espacios. ¿Podría publicar algunos ejemplos de url prohibido, bloqueado por su archivo de configuración? Gracias –

+0

¿Funcionará este enfoque mejor que la función de caracteres especiales html? –

3

pek, para una solución a corto plazo, aplique una de las soluciones sugeridas por otros usuarios. Para un plan de mediano a largo plazo, debe considerar migrar a uno de los marcos web existentes.Manejan todas las cosas de bajo nivel, como el enrutamiento y la inclusión de archivos de manera confiable y segura, para que pueda concentrarse en las funciones principales.

No reinventar la rueda. Usa un marco. Cualquiera de ellos es mejor que ninguno. La inversión de tiempo inicial en aprender devuelve casi al instante.

5

Pek, hay muchas cosas de las que preocuparse por la adición a la inyección sql, o incluso diferentes tipos de inyección de código. Ahora podría ser un buen momento para mirar un poco más hacia la seguridad de las aplicaciones web en general.

Desde una pregunta anterior sobre moving from desktop to web development, escribí:

El OWASP Guide to Building Secure Web Applications and Web Services debería ser lectura obligatoria para cualquier desarrollador web que desea tomar en serio la seguridad (que debe ser todos desarrolladores web). Hay muchos principios a seguir que ayudan con la mentalidad requerida cuando se piensa en la seguridad.

Si leer un documento grande y gordo no es para usted, entonces eche un vistazo al video del seminario que Mike Andrews dio en Google hace un par de años acerca de How To Break Web Software.

1

Algunas buenas respuestas hasta el momento, también cabe destacar un par de aspectos específicos de PHP:

el archivo de funciones abiertas utilizan wrappers para soportar diferentes protocolos. Esto incluye la capacidad de abrir archivos a través de una red local de Windows, HTTP y FTP, entre otros. Por lo tanto, en una configuración predeterminada, el código en la pregunta original puede usarse fácilmente para abrir cualquier archivo arbitrario en Internet y más allá; incluyendo, por supuesto, todos los archivos en los discos locales del servidor (que el usuario de webbserver puede leer). /etc/passwd es siempre divertido.

Modo seguro y open_basedir se pueden utilizar para restringir que se acceda a archivos fuera de un directorio específico.

También es útil la configuración de configuración allow_url_fopen, que puede deshabilitar el acceso URL a los archivos, al utilizar las funciones de abrir archivos. ini-set se puede utilizar para establecer y deshacer este valor en tiempo de ejecución.

Estos son todos bonitos protectores de seguridad de retroceso, pero utilice una lista blanca para la inclusión de archivos.

0

@pek - Eso no funcionará, ya que sus teclas de matriz son 0 y 1, no 'casa' y 'página'.

Este código debe hacer el truco, creo:

<?php 

$whitelist = array(
    'home', 
    'page', 
); 

if(in_array($_GET['page'], $whitelist)) { 
    include($_GET['page'] . '.php'); 
} else { 
    include('home.php'); 
} 

?> 

Como usted tiene una lista blanca, no debería haber una necesidad de file_exists() tampoco.

1

Sé que esta es una publicación muy antigua y espero que ya no necesite una respuesta, pero todavía echo de menos un aspecto muy importante y me gusta compartirlo con otras personas que leen esta publicación. En su código para incluir un archivo basado en el valor de una variable, establece un vínculo directo entre el valor de un campo y el resultado solicitado (la página se convierte en page.php). Creo que es mejor evitar eso. Hay una diferencia entre la solicitud de una página y la entrega de esa página. Si haces esta distinción, puedes utilizar URL agradables, que son muy amigables para el usuario y SEO. En lugar de un valor de campo como 'página', podría crear una URL como 'Spinoza-Ethica'.Esa es una clave en una lista blanca o una clave principal en una tabla de una base de datos y devolverá un nombre de archivo o valor codificado. Ese método tiene varias ventajas además de una lista blanca normal:

  1. la respuesta de la parte posterior es efectivamente independiente de la solicitud de la parte delantera. Si desea configurar su sistema de fondo de manera diferente, no tiene que cambiar nada en la interfaz.

  2. Siempre asegúrese de terminar con nombres de archivos codificados o equivalentes de la base de datos (preferiblemente un valor devuelto de un procedimiento almacenado), porque está causando problemas cuando utiliza la información de la solicitud para generar la respuesta .

  3. Como sus URL son independientes de la entrega desde el back end, nunca tendrá que volver a escribir las URL en el archivo htAccess para este tipo de cambio.

  4. Las URL representadas para el usuario son fáciles de usar, informando al usuario sobre el contenido del documento.

  5. Las URL agradables son muy buenas para SEO, porque los motores de búsqueda están en busca de contenido relevante y cuando su URL está en línea con el contenido obtendrá una mejor tarifa. Por lo menos, una tasa mejor cuando su contenido definitivamente no está en línea con su contenido.

  6. Si no enlaza directamente a un archivo php, puede traducir la buena URL a cualquier otro tipo de solicitud antes de procesarla. Eso le da al programador mucha más flexibilidad.

  7. Deberá desinfectar la solicitud, ya que obtendrá la información de una fuente estándar poco confiable (el resto de la Web). Usar solo URL agradables como entrada posible hace que el proceso de desinfección de la URL sea mucho más simple, porque puede verificar si la URL devuelta cumple con su propio formato. Asegúrese de que el formato de la bonita URL no contiene caracteres que se utilizan ampliamente en hazañas. (Como' ", <,>, -, &,, etc ..)

0

pienso en la URL es en este formato:

www.yourwebsite.com/index.php?page= http://malicodes.com/shellcode.txt

Si el shellcode.txt ejecuta SQL o inyección de PHP, entonces su sitio web estará en riesgo, ¿no te parece? , usar una lista blanca sería de ayuda.

Hay una forma de filtrar todas las variables para evitar el pirateo. Puede usar PHP IDS o OSE Security Suite para ayudar a evitar el pirateo. Después de instalar el paquete de seguridad, es necesario activar la suite, aquí está la guía:

http://www.opensource-excellence.com/shop/ose-security-suite/item/414.html

yo sugeriría que activa la protección de la capa 2, entonces todos POST y GET variables se filtran en especial la que yo mencionado, y si hay ataques conocidos, se le informará de inmediato/

la seguridad es siempre la prioridad

Cuestiones relacionadas