¿Por qué Google precede mientras (1); a sus respuestas JSON?

¿Por qué Google precede while(1); a sus respuestas (privadas) JSON?

Por ejemplo, aquí hay una respuesta al encender y apagar un calendario en Google Calendar :

 while(1);[['u',[['smsSentFlag','false'],['hideInvitations','false'], ['remindOnRespondedEventsOnly','true'], ['hideInvitations_remindOnRespondedEventsOnly','false_true'], ['Calendar ID stripped for privacy','false'],['smsVerifiedFlag','true']]]] 

Supongo que esto es para evitar que las personas eval() una eval() , pero lo único que tendrías que hacer es reemplazar el while y luego estarías listo. Asumiría que la prevención de evaluación es para asegurarse de que la gente escriba el código de análisis seguro de JSON.

También he visto esto usado en un par de otros lugares, pero mucho más con Google (Correo, Calendario, Contactos, etc.). Curiosamente, Google Docs comienza con &&&START&&& , y parece que los Contactos de Google comienzan con while(1); &&&START&&& while(1); &&&START&&& .

¿Que está pasando aqui?

Previene el secuestro de JSON , un importante problema de seguridad de JSON que se ha corregido formalmente en todos los principales navegadores desde 2011 con EMCA5.

Ejemplo de error: digamos que Google tiene una URL como mail.google.com/json?action=inbox que devuelve los primeros 50 mensajes de su bandeja de entrada en formato JSON. Los sitios web malignos en otros dominios no pueden realizar solicitudes AJAX para obtener estos datos debido a la política de origen mismo, pero pueden incluir la URL a través de una etiqueta . La URL se visita con sus cookies, y anulando el constructor de matriz global o los métodos de acceso pueden llamar a un método cada vez que se establece un atributo de objeto (matriz o hash), lo que les permite leer el contenido JSON.

El while(1); o &&&BLAH&&& previene: una solicitud de AJAX en mail.google.com tendrá acceso completo al contenido de texto y podrá quitarlo. Pero la inserción de una etiqueta ejecuta ciegamente el JavaScript sin ningún procesamiento, lo que da como resultado un bucle infinito o un error de syntax.

Esto no aborda el problema de la falsificación de solicitudes entre sitios .

Impide la divulgación de la respuesta a través del secuestro de JSON.

En teoría, el contenido de las respuestas HTTP está protegido por la misma política de origen: las páginas de un dominio no pueden obtener información de las páginas de otro dominio (a menos que esté explícitamente permitido).

Un atacante puede solicitar páginas en otros dominios en su nombre, por ejemplo, utilizando una etiqueta o , pero no puede obtener ninguna información sobre el resultado (encabezados, contenidos).

Por lo tanto, si visita la página de un atacante, no podría leer su correo electrónico desde gmail.com.

Excepto que cuando se usa una etiqueta de script para solicitar contenido JSON, el JSON se ejecuta como Javascript en el entorno controlado de un atacante. Si el atacante puede reemplazar el constructor Array o Object u otro método utilizado durante la construcción del objeto, cualquier elemento en el JSON pasará por el código del atacante y se divulgará.

Tenga en cuenta que esto sucede en el momento en que JSON se ejecuta como Javascript, no en el momento en que se analiza.

Hay múltiples contramedidas:

Asegurándose de que el JSON nunca se ejecute

Al colocar un while(1); statement antes de los datos JSON, Google se asegura de que los datos JSON nunca se ejecuten como Javascript.

Solo una página legítima podría obtener todo el contenido, quitar el while(1); , y analizar el rest como JSON.

Cosas como for(;;); se han visto en Facebook, por ejemplo, con los mismos resultados.

Asegurándose de que el JSON no sea válido Javascript

Del mismo modo, agregar tokens no válidos antes de JSON, como &&&START&&& , asegura que nunca se ejecute.

Siempre devuelve JSON con un objeto en el exterior

Esta es la forma recomendada por OWASP para protegerse del secuestro de JSON, y es la menos intrusiva.

De forma similar a las contramedidas anteriores, se asegura de que el JSON nunca se ejecute como Javascript.

Un objeto JSON válido, cuando no está cerrado por nada, no es válido en Javascript:

 eval('{"foo":"bar"}') // SyntaxError: Unexpected token : 

Sin embargo, esto es válido JSON:

 JSON.parse('{"foo":"bar"}') // Object {foo: "bar"} 

Por lo tanto, asegurándose de que siempre devuelve un objeto en el nivel superior de la respuesta, se asegura de que el JSON no sea un código JavaScript válido, mientras siga siendo JSON válido.

Según lo observado por @hvd en los comentarios, el objeto vacío {} es Javascript válido, y saber que el objeto está vacío puede ser información valiosa.

Comparación de los métodos anteriores

El modo OWASP es menos intrusivo, ya que no necesita cambios de la biblioteca del cliente y transfiere JSON válido. Sin embargo, no está seguro si los errores del navegador pasados ​​o futuros podrían vencer esto. Como señala @oriadam, no está claro si los datos pueden filtrarse en un error de análisis mediante un tratamiento de error o no (por ejemplo, window.onerror).

El camino de Google requiere la biblioteca del cliente para que admita la deserialización automática, y se puede considerar que es más seguro con respecto a los errores del navegador.

Ambos métodos requieren cambios en el servidor para evitar que los desarrolladores accidentalmente envíen JSON vulnerable.

Esto es para asegurar que algún otro sitio no pueda hacer trucos desagradables para tratar de robar sus datos. Por ejemplo, al reemplazar el constructor de la matriz , y luego incluir esta URL JSON a través de una etiqueta , un sitio de terceros malintencionado podría robar los datos de la respuesta JSON. Al poner un while(1); al principio, el script se bloqueará en su lugar.

Por otro lado, una solicitud en el mismo sitio que usa XHR y un analizador JSON separado pueden ignorar fácilmente el while(1); prefijo.

Eso sería para dificultar que un tercero inserte la respuesta JSON en un documento HTML con la etiqueta . Recuerde que la etiqueta está exenta de la misma política de origen .

Evita que se use como el objective de una simple etiqueta . (Bueno, no lo previene, pero lo hace desagradable.) De esa manera, los chicos malos no pueden poner esa etiqueta de script en su propio sitio y confiar en una sesión activa para que sea posible recuperar su contenido.

editar - tenga en cuenta el comentario (y otras respuestas). El problema tiene que ver con las instalaciones subvertidas incorporadas, específicamente los constructores de Object y Array . Esos pueden ser alterados de tal forma que, de otro modo, un JSON inocuo, cuando se analiza, podría desencadenar un código de atacante.

Dado que la etiqueta está exenta de la Política de Mismo origen que es una necesidad de seguridad en el mundo de la web, while(1) cuando se agrega a la respuesta JSON evita el uso indebido de la misma en la etiqueta .