Desde hace días, trato de hacerme una idea general de cómo escribir una aplicación web segura en PHP, y resulta ser particularmente difícil. Cuanto más leo, más me hundo en profundos pantanos llenos de vulnerabilidades que no son mencionadas por personas amables como Matt Robinson o Chris Shiflett .
Para algunos ejemplos, toma:
En resumen, veo los siguientes problemas:
- Al filtrar la entrada, no está muy claro cómo se descodificarán esos datos más adelante y, por lo tanto, la codificación de caracteres y los sistemas de escape pueden omitir el filtrado de entrada. (como la decodificación de doble url)
- Al escapar de la salida, uno usa funciones estándar como htmlspecialchars . Está bien que htmlspecialchars tenga un parámetro de codificación, sin embargo, eso no impide que le envíes una entrada UTF-16, y eso probablemente podría romper el valor de seguridad de la función.
Parece que hay un módulo mbstring en php, pero si es vagamente tan seguro como su documentación es comprensible, entonces probablemente será inútil incluso si puedo averiguar cómo usarlo. Solo una muestra de los documentos para ilustración :
mbstring.strict_detection boolean
Enables the strict encoding detection.
Genial, eso es útil.
Lamentablemente, las funciones también dependen de lo que establezca en las opciones de configuración ... Parece que hay una función llamada mb_convert_encoding
, pero los documentos no dicen nada sobre el aspecto de seguridad y parece que necesita conocer la codificación de entrada (una zona de no acceso para la seguridad). También hay mb_check_encoding
. Lo que parece estar destinado al propósito, pero leer los comentarios de los usuarios en los documentos no inspira exactamente la confianza.
Entonces, a la luz de todo esto, la pregunta es ¿cómo se realiza el filtrado de entrada seguro ? Algo como esto?
-
mb_convert_encoding
a utf-8 -
mb_check_encoding
para rechazar la entrada no válida - bucle url_decode hasta que la cadena deje de cambiar
- Realice su filtrado de entrada normal con comparación de texto y expresiones regulares, etc. ...
editar: tenga en cuenta que 3 es problemático porque su filtro de entrada normal podría introducir entidades de nuevo que pueden decodificarse por url
editar
Encontré una respuesta parcial aquí , de Shiflett. Parece que para htmlspecialchars usar su parámetro de codificación y asegurarse de que establece el encabezado de codificación de caracteres para el navegador, evitaría que el navegador interprete los caracteres de manera diferente a como lo hace htmlspecialchars. Esto es todo asumiendo que la entrada de htmlspecialchars es válida para la codificación dada o que para cada entrada inválida posible htmlspecialchars interpreta la cadena exactamente de la misma manera que lo hace cada navegador. Sabemos que si no encontramos una manera de desinfectar nuestra entrada, no podemos asegurar que la entrada de htmlspecialchars esté codificada de manera válida, ya que un atacante podría preparar una cadena con una codificación no válida. Esto nos lleva a la segunda posibilidad, que htmlspecialchars se comportará de forma idéntica al navegador para todas las entradas posibles. Esto es un problema, ya que no podemos usar el mismo tokenizador para escapar y usar, ya que uno sucede en el servidor y otro en el navegador.
Todo esto es similar a lo que hace msql_real_escape para una base de datos, aunque creo que puedes resolver este problema correctamente para msql usando en su lugar declaraciones preparadas.
Una tercera salida problemática es el sistema de archivos cuando se usa php para realizar cargas de archivos u otras manipulaciones del sistema de archivos. Sobre este último parece que hay muy poca información disponible. Ni siquiera conozco una función de escape específica, y mucho menos una que sea robusta cuando se obtiene una entrada torcida.