¿Puedo confiar al 100% en $_SERVER[]
para ser una fuente segura de datos que no necesito sanear como hago $_GET[]
y $_POST[]
?
¿Puedo confiar al 100% en $_SERVER[]
para ser una fuente segura de datos que no necesito sanear como hago $_GET[]
y $_POST[]
?
Esto está tomado de una de mis preguntas sobre desbordamiento de pila: ¿Qué variables $ _SERVER son seguras?
Estas variables las establece el entorno del servidor y dependen completamente de la configuración del servidor.
'GATEWAY_INTERFACE'
'SERVER_ADDR'
'SERVER_SOFTWARE'
'DOCUMENT_ROOT'
'SERVER_ADMIN'
'SERVER_SIGNATURE'
Estas variables dependen de la solicitud específica que envió el cliente, pero solo pueden tomar un número limitado de valores válidos, ya que todos los valores no válidos deben ser rechazados por el servidor web y no provocar que comience la invocación del script. Por lo tanto, pueden considerarse confiables .
'HTTPS'
'REQUEST_TIME'
'REMOTE_ADDR'
* 'REMOTE_HOST'
* 'REMOTE_PORT'
* 'SERVER_PROTOCOL'
'HTTP_HOST'
† 'SERVER_NAME'
† 'SCRIPT_FILENAME'
'SERVER_PORT'
'SCRIPT_NAME'
* Se garantiza que los valores REMOTE_
son la dirección válida del cliente, como lo verifica un protocolo de enlace TCP / IP. Esta es la dirección a la que se enviará cualquier respuesta. Sin embargo, REMOTE_HOST
se basa en búsquedas de DNS inversas y, por lo tanto, puede ser falsificado por ataques de DNS contra su servidor (en cuyo caso, de todos modos, tiene mayores problemas). Este valor puede ser un proxy, que es una simple realidad del protocolo TCP / IP y nada de lo que pueda hacer nada.
† Si su servidor web responde a la solicitud de cualquier independientemente del encabezado HOST
, esto también debe considerarse inseguro. Consulte ¿Qué tan seguro es $ _SERVER [“HTTP_HOST”]? .
También vea enlace .
Estos valores no se verifican en absoluto y no dependen de ninguna configuración del servidor, son información completamente arbitraria enviada por el cliente.
'argv'
, 'argc'
(solo aplicable a la invocación de CLI, no suele ser una preocupación para los servidores web) 'REQUEST_METHOD'
‡ 'QUERY_STRING'
'HTTP_ACCEPT'
'HTTP_ACCEPT_CHARSET'
'HTTP_ACCEPT_ENCODING'
'HTTP_ACCEPT_LANGUAGE'
'HTTP_CONNECTION'
'HTTP_REFERER'
'HTTP_USER_AGENT'
'AUTH_TYPE'
§ 'PHP_AUTH_DIGEST'
§ 'PHP_AUTH_USER'
§ 'PHP_AUTH_PW'
§ 'PATH_INFO'
'ORIG_PATH_INFO'
'REQUEST_URI'
(puede contener datos contaminados) 'PHP_SELF'
(puede contener datos contaminados, es decir, /index.php/evilstring) 'PATH_TRANSLATED'
'HTTP_'
‡ Puede considerarse confiable siempre que el servidor web permita solo ciertos métodos de solicitud.
§ Puede considerarse confiable si la autenticación es manejada completamente por el servidor web.
El superglobal $_SERVER
también incluye varias variables de entorno. Si estos son "seguros" o no dependen de cómo (y dónde) se definen. Pueden variar desde completamente controlado por el servidor hasta completamente controlado por el usuario.
¿Puedo confiar al 100% en $ _SERVER [] para que sea una fuente segura de datos que no necesito limpiar como hago con $ _GET [] y $ _POST []?
Su pregunta indica inmediatamente el fracaso. Todas las fuentes de entrada deben estar desinfectadas. La entrada no solo se considera canales que el usuario puede controlar directamente, sino también todas las fuentes de datos fuera de su aplicación.
Piénselo de esta manera, su aplicación tiene 2 formas de obtener datos: información que está codificada en su aplicación e ingreso. Incluso si es generado por otro programa en el mismo sistema, sigue ingresando en su programa.
El idioma común Filter-In, Escape-Out
se aplica no solo a la entrada del usuario, sino a cualquier cosa que entre y salga de su aplicación.
Entonces, si está en $_SERVER
, DEBE ser filtrado / saneado. Nunca debe confiar en nada que no esté codificado en su aplicación.
¿Por qué es esto importante? Imaginemos que filtra todas las entradas del usuario, pero luego confía en los datos que provienen de su base de datos. Si puedo explotar un agujero en su filtro, puedo inyectar datos que luego se vuelven confiables. Esto puede resultar en XSS o SQLi de segundo orden. Pero si filtras todo lo que entra en tu aplicación, cuando llega, sin importar de dónde venga, ¡estarás a salvo!
Así que no, nunca puedes confiar al 100% en nada en $_SERVER
, $_GET
, $_POST
, $_COOKIE
, $_REQUEST
, $_ENV
, $argc
, $argv
, desde tu base de datos , desde el sistema de archivos (aparte de su código controlado por versión), etc ...
No es una pregunta tonta en absoluto!
Muchas (pero no todas) de las variables $ SERVER se pasan desde el navegador de los usuarios (o pueden ser influenciados por el usuario), por ejemplo, QUERY_STRING, REQUEST_URI y todas las variables HTTP_ *.
Incluso la variable REMOTE_ADDR puede falsificarse utilizando sockets sin formato (aunque solo con IP válidas, según tengo entendido).
Me escaparía de ellos como una buena política.
No existe tal cosa como "una fuente segura de datos". Siempre debe asegurarse de que los datos estén en el formato correcto al pasarlos a otra cosa.
Si está enviando a SQL dentro de una cadena delimitada por apóstrofe (') [1], debe escapar de los apóstrofes (o cualquier otra cosa que pueda romper la cadena). Si está enviando a una cadena delimitada por apóstrofe de Javascript [2], debe escapar tanto de HTML como de apóstrofes. Todo depende de a lo que estés enviando. Una cadena perfectamente segura puede romper la secuencia de comandos de destino, incluso si no es maliciosa. (Sin embargo, a menudo, si puede romperse, también puede ser explotado).
[1] Ejemplo: $db->query("SELECT * FROM users WHERE name = '$username'");
[2] Ejemplo: <script>alert('Hi <?php echo $username;?>');</script>
He hablado de esto en mi blog, aunque mi publicación es específicamente sobre XSS, creo que el mismo principio se aplica aquí también: ¿Qué es XSS y cómo proteger su sitio web? .
A menos que sepa que el propio PHP ya impone un formato específico, y casi nunca puede estar seguro de eso, puede considerar que todo es inseguro. Las direcciones IP usualmente vienen en el formato x.x.x.x, pero también puede ser x: x: x: x: x: x: x: x para IPv6. O incluso 0: 0: 0: 0: 0: ffff: x.x.x.x para destinos IPv4 en paquetes IPv6. Si no estás al tanto de esto, es posible que tengas algunos errores muy interesantes.
Ahora una dirección IP nunca contendrá un apóstrofe, ¿verdad ..? Bueno, hay personas que buscan el encabezado $ _SERVER ["HTTP_X_FORWARDED_FOR"] antes de usar la dirección remota. Esto es genial, siempre y cuando el encabezado esté configurado correctamente (como también lo señaló @Ladadadada en un comentario a la respuesta de @ GBC), pero eso también puede ser una falsificación. Luego, cuando utiliza los datos que otras personas almacenan en la base de datos, es posible que recupere información maliciosa ... Entonces, al final, nunca confíe en la información. Es mejor asegurarlo demasiado que olvidarlo una vez.
Lea otras preguntas en las etiquetas web-application source-code appsec php encoding