¿Por qué Google antepone mientras (1); a sus respuestas JSON?
Frecuentes
Visto 555,651 veces
4215
¿Por qué Google antepone while(1);
a sus respuestas JSON (privadas)?
Por ejemplo, aquí tienes una respuesta al encender y apagar un calendario en Calendario de Google:
while (1);
[
['u', [
['smsSentFlag', 'false'],
['hideInvitations', 'false'],
['remindOnRespondedEventsOnly', 'true'],
['hideInvitations_remindOnRespondedEventsOnly', 'false_true'],
['Calendar ID stripped for privacy', 'false'],
['smsVerifiedFlag', 'true']
]]
]
Asumiría que esto es para evitar que la gente haga un eval()
en él, pero todo lo que realmente tienes que hacer es reemplazar el while
y luego estarías listo. Asumiría que la prevención de evaluación es asegurarse de que las personas escriban un código de análisis JSON seguro.
También he visto este uso en un par de otros lugares, pero mucho más con Google (correo, calendario, contactos, etc.). Curiosamente, Google Docs comienza con &&&START&&&
en su lugar, y los Contactos de Google parecen comenzar con while(1); &&&START&&&
.
¿Que está pasando aqui?
8 Respuestas
4401
Previene Secuestro de JSON, un importante problema de seguridad JSON que es formalmente fijas en todos los principales navegadores desde 2011 con ECMAScript 5.
Ejemplo artificial: 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 malvados en otros dominios no pueden realizar solicitudes AJAX para obtener estos datos debido a la política del mismo origen, pero pueden incluir la URL a través de un <script>
etiqueta. La URL se visita con a tu cookies, y por anulando el constructor de matriz global o los métodos de acceso pueden tener un método llamado cada vez que se establece un atributo de objeto (matriz o hash), lo que les permite leer el contenido JSON.
EL while(1);
or &&&BLAH&&&
previene esto: una solicitud AJAX en mail.google.com
tendrá acceso completo al contenido del texto y podrá eliminarlo. Pero un <script>
La inserción de etiquetas ejecuta ciegamente JavaScript sin ningún procesamiento, lo que da como resultado un bucle infinito o un error de sintaxis.
Esto no aborda la cuestión de solicitud de falsificación a través del sitio.
respondido 10 mar '19, 18:03
¿Por qué la solicitud para obtener estos datos no requiere un token CSRF en su lugar? - jakub p.
¿Afecta la regulación de la for(;;);
hacer el mismo trabajo? He visto esto en las respuestas de ajax de Facebook. - Rey julien
@JakubP. Almacenar y mantener tokens CSRF a la escala de Google requiere una gran cantidad de infraestructura y costo. - Abrahán
@JakubP. Los tokens anti-CSRF interfieren con el almacenamiento en caché y requieren cierta cantidad de evaluación criptográfica del lado del servidor. A escala de Google, eso requeriría mucha CPU. De esta forma, se lo descarga al cliente. - luna azul
Me parece que una mejor manera sería dejar que el servidor solo envíe el JSON si se ha configurado el encabezado correcto. Puede hacerlo en una llamada AJAX, pero no con etiquetas de script. De esa manera, la información confidencial ni siquiera se envía y no tiene que depender de la seguridad del lado del navegador. - mcv
602
Evita la divulgación de la respuesta mediante el secuestro de JSON.
En teoría, el contenido de las respuestas HTTP está protegido por la Política del mismo origen: las páginas de un dominio no pueden obtener información de las páginas del otro dominio (a menos que se permita explícitamente).
Un atacante puede solicitar páginas en otros dominios en su nombre, por ejemplo, utilizando un <script src=...>
or <img>
etiqueta, pero no puede obtener ninguna información sobre el resultado (encabezados, contenido).
Por lo tanto, si visita la página de un atacante, no podrá leer su correo electrónico de gmail.com.
Excepto que cuando se usa una etiqueta de secuencia de comandos 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 u Object o algún otro método utilizado durante la construcción del objeto, cualquier cosa en el JSON pasaría a través del código del atacante y se revelaría.
Tenga en cuenta que esto sucede en el momento en que JSON se ejecuta como JavaScript, no en el momento en que se analiza.
Existen múltiples contramedidas:
Asegurarse de que JSON nunca se ejecute
Colocando un while(1);
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 resto como JSON.
Cosas como for(;;);
se han visto en Facebook, por ejemplo, con los mismos resultados.
Asegurarse de que JSON no sea JavaScript válido
Del mismo modo, agregar tokens no válidos antes del JSON, como &&&START&&&
, se asegura de que nunca se ejecute.
Siempre devuelva JSON con un objeto en el exterior
Es Forma recomendada por OWASP para protegerse del secuestro de JSON y es el menos intrusivo.
De manera similar a las contramedidas anteriores, se asegura de que JSON nunca se ejecute como JavaScript.
Un objeto JSON válido, cuando no está incluido por nada, no es válido en JavaScript:
eval('{"foo":"bar"}')
// SyntaxError: Unexpected token :
Sin embargo, esto es JSON válido:
JSON.parse('{"foo":"bar"}')
// Object {foo: "bar"}
Por lo tanto, asegurarse de devolver siempre un Objeto en el nivel superior de la respuesta asegura que el JSON no sea JavaScript válido, mientras sigue siendo JSON válido.
Como señaló @hvd en los comentarios, el objeto vacío {}
es JavaScript válido, y saber que el objeto está vacío puede ser en sí mismo información valiosa.
Comparación de los métodos anteriores
La forma OWASP es menos intrusiva, ya que no necesita cambios en la biblioteca 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ñaló @oriadam, no está claro si los datos podrían filtrarse en un error de análisis a través de un manejo de errores o no (por ejemplo, window.onerror).
El método de Google requiere una biblioteca de cliente para que admita la deserialización automática y pueda considerarse más seguro con respecto a los errores del navegador.
Ambos métodos requieren cambios en el lado del servidor para evitar que los desarrolladores envíen accidentalmente JSON vulnerable.
Respondido 19 Oct 20, 03:10
La recomendación de OWASP es interesante por su simplicidad. ¿Alguien sabe una razón por la que el método de Google es más seguro? - funroll
yo lo creo no es más seguro de cualquier manera. Proporcionar OWASP aquí parece una razón suficiente para hacer +1. - usuario719662
Puede valer la pena señalar el porqué devolver un objeto literal falla el script
etiqueta o eval
función. Los tirantes {}
se puede interpretar como un bloque de código o un objeto literal y, por sí mismo, JavaScript prefiere lo primero. Como bloque de código, por supuesto, no es válido. Según esta lógica, no puedo ver ningún cambio previsible en el comportamiento futuro del navegador. - Manngó
El código incorrecto no es suficiente porque un atacante también puede secuestrar el controlador de error de script del navegador (window.onerror
) No estoy seguro de cuál es el comportamiento de onerror
con errores de sintaxis. Supongo que Google tampoco estaba seguro. - Oriadam
"Un objeto JSON válido, cuando no está encerrado por nada, no es válido en Javascript:" - Excepto por el caso trivial de un objeto vacío ({}
), que también es un bloque vacío válido. Si saber que el objeto está vacío puede ser en sí mismo información valiosa, esto podría ser explotable. - usuario743382
379
Esto es para asegurar que algún otro sitio no pueda hacer trucos desagradables para intentar robar sus datos. Por ejemplo, por reemplazando el constructor de la matrizy luego incluir esta URL JSON a través de un <script>
, un sitio de terceros malintencionado podría robar los datos de la respuesta JSON. Poniendo un while(1);
al principio, la secuencia de comandos se bloqueará en su lugar.
Una solicitud del mismo sitio usando XHR y un analizador JSON separado, por otro lado, puede ignorar fácilmente la while(1);
prefijo.
Respondido el 31 de enero de 14 a las 23:01
Técnicamente, un analizador JSON "normal" debería dar un error si tiene un prefijo. - matthew crumley
Los atacantes solo usarían un viejo <script>
elemento, no un XHR. - Laurence Gonsalves
@Matthew, claro, pero puede eliminarlo antes de pasar los datos al analizador JSON. No puedes hacer eso con un <script>
etiqueta - bdonlan
¿Hay ejemplos de esto? Se hace referencia nuevamente al reemplazo del constructor de matriz, pero ese es un error que se corrigió hace mucho tiempo. No entiendo cómo se tendría acceso a los datos recibidos a través de la etiqueta de secuencia de comandos. Me encantaría ver una implementación ficticia que funcione en un navegador reciente. - Dennis G.
@joeltine, no, no lo es. Ver stackoverflow.com/questions/16289894/… . - usuario69173
112
Eso sería dificultar que un tercero inserte la respuesta JSON en un documento HTML con la <script>
etiqueta. Recuerda que el <script>
la etiqueta está exenta de la Política del mismo origen.
Respondido el 30 de diciembre de 13 a las 03:12
Esta es solo la mitad de la respuesta. Si no fuera por el truco de anular el Object
y Array
constructores, ejecutar una respuesta JSON válida como si fuera JavaScript sería totalmente inocuo en todas las circunstancias. Sí el while(1);
evita que la respuesta se ejecute como JavaScript si está dirigida por un <script>
etiqueta, pero su respuesta no explica por qué es necesario. - marca amery
pero ¿cómo evitará los iframes? viejoguardia01
La etiqueta de secuencia de comandos nunca está exenta de la política del mismo origen. ¿Podrías aclararme eso? - Suraj jainista
XHR / AJAX no se puede ejecutar entre dominios sin CORS. Sin embargo, puede servir <script src="http://victim.com/target-api-with-secrets.js">
on attacker.com
. - Mikko Rantalainen
82
Nota:: a partir de 2019, muchas de las viejas vulnerabilidades que conducen a las medidas preventivas discutidas en esta pregunta ya no son un problema en los navegadores modernos. Dejaré la respuesta a continuación como una curiosidad histórica, pero realmente todo el tema ha cambiado radicalmente desde 2010 (!!) cuando se preguntó esto.
Evita que se utilice como objetivo de un simple <script>
etiqueta. (Bueno, no lo previene, pero lo hace desagradable). De esa manera, los malos no pueden simplemente poner esa etiqueta de script en su propio sitio y depender de una sesión activa para que sea posible buscar su contenido.
editar - anote el comentario (y otras respuestas). El problema tiene que ver con las instalaciones empotradas subvertidas, específicamente el Object
y Array
constructores. Esos pueden modificarse de manera que JSON, que de otro modo sería inocuo, cuando se analiza, podría activar el código del atacante.
respondido 18 mar '19, 02:03
Esta es solo la mitad de la respuesta. Si no fuera por el truco de anular el Object
y Array
constructores, ejecutar una respuesta JSON válida como si fuera JavaScript sería totalmente inocuo en todas las circunstancias. Sí el while(1);
evita que la respuesta se ejecute como JavaScript si está dirigida por un <script>
etiqueta, pero su respuesta no explica por qué es necesario. - marca amery
¿Qué pasa si el while
¿Se modificó el constructor de funciones? ¿Es eso posible? - Anónimo
@Anónimo no hay while
constructor de funciones; no es una función, es un elemento de sintaxis. No se puede anular. - Puntiagudo
11
Puesto que el <script>
la etiqueta está exenta de la Política del mismo origen, que es una necesidad de seguridad en el mundo web, while(1)
cuando se agrega a la respuesta JSON evita el uso indebido de la misma en el <script>
etiqueta.
Respondido 28 ago 18, 10:08
0
Una vez implementada la autenticación, la protección contra el secuestro de JSON puede adoptar diversas formas. Google agrega mientras (1) en sus datos JSON, de modo que si algún script malicioso lo evalúa, el script malicioso entra en un ciclo infinito.
Referencia: Libro de cocina de pruebas de seguridad web: Técnicas sistemáticas para encontrar problemas rápidamente
respondido 02 mar '20, 01:03
0
Como esta es una publicación de alto tráfico, espero proporcionar aquí una respuesta un poco más indeterminada a la pregunta original y, por lo tanto, brindar más antecedentes sobre un ataque de secuestro de JSON y sus consecuencias.
El secuestro de JSON, como su nombre indica, es un ataque similar a la falsificación de solicitudes entre sitios, donde un atacante puede acceder a datos JSON confidenciales entre dominios desde aplicaciones que devuelven datos confidenciales como literales de matriz para solicitudes GET. A continuación, se muestra un ejemplo de una llamada JSON que devuelve un literal de matriz:
[{"id":"1001","ccnum":"4111111111111111","balance":"2345.15"},
{"id":"1002","ccnum":"5555555555554444","balance":"10345.00"},
{"id":"1003","ccnum":"5105105105105100","balance":"6250.50"}]
Este ataque se puede lograr en 3 pasos principales:
Paso 1: Consiga que un usuario autenticado visite una página maliciosa. Paso 2: La página maliciosa intentará acceder a los datos confidenciales de la aplicación en la que el usuario inició sesión. Esto se puede hacer incrustando una etiqueta de secuencia de comandos en una página HTML, ya que la política del mismo origen no se aplica a las etiquetas de secuencia de comandos.
<script src="http://<jsonsite>/json_server.php"></script>
El navegador realizará una solicitud GET a json_server.php
y las cookies de autenticación del usuario se enviarán junto con la solicitud. Paso 3: En este punto, mientras el sitio malicioso ha ejecutado el script, no tiene acceso a ningún dato sensible. Se puede obtener acceso a los datos mediante el uso de un generador de prototipos de objetos. En el código siguiente, una propiedad de prototipos de objeto se vincula a la función definida cuando se intenta establecer el "ccnum
" propiedad.
Object.prototype.__defineSetter__('ccnum',function(obj){
secrets =secrets.concat(" ", obj);
});
En este punto, el sitio malicioso ha secuestrado con éxito los datos financieros confidenciales. (ccnum)
devuelto byjson_server.php
JSON
Cabe señalar que no todos los navegadores admiten este método; la prueba de concepto se realizó en Firefox 3.x.Este método ahora ha sido obsoleto y reemplazado por el useObject.defineProperty
También hay una variación de este ataque que debería funcionar en todos los navegadores donde JavaScript con nombre completo (p. Ej. pi=3.14159
) se devuelve en lugar de una matriz JSON.
Hay varias formas de prevenir el secuestro de JSON:
Dado que las etiquetas SCRIPT solo pueden generar solicitudes HTTP GET, solo devuelven objetos JSON a solicitudes POST.
Evite que el navegador web interprete el objeto JSON como código JavaScript válido.
Implemente la protección contra la falsificación de solicitudes entre sitios requiriendo que se requiera un valor aleatorio predefinido para todas las solicitudes JSON.
así que como puedes ver While(1)
viene bajo la última opción. En los términos más simples, while(1)
es un bucle infinito que se ejecutará hasta que se emita explícitamente una declaración de interrupción. Y por lo tanto, lo que se describiría como un bloqueo para que se aplique la clave (declaración de ruptura de Google). Por lo tanto, un secuestro de JSON, en el que el hacker no tiene clave, se descartará constantemente. Además, si lee el bloque JSON con un analizador, el bucle while (1) se ignora.
Entonces, en conclusión, el while(1)
El bucle se puede visualizar más fácilmente como un sencillo Cifrado de declaración de ruptura que Google puede usar para controlar el flujo de datos.
Sin embargo, la palabra clave en esa declaración es la palabra 'sencillo'. Afortunadamente, el uso de bucles infinitos autenticados se ha eliminado de la práctica básica en los últimos años. desde 2010 debido a su reducción absoluta del uso de la CPU cuando aislado (y el hecho de que Internet se ha alejado de forzar a través de crudos 'arreglos rápidos'). Hoy, en cambio, el código base tiene medidas preventivas integradas y el sistema ya no es crucial ni efectivo. (parte de esto es el alejamiento del secuestro de JSON a técnicas de cultivo de datos más fructíferas en las que no entraré en la actualidad)
*
Respondido el 24 de diciembre de 20 a las 11:12
No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas javascript json ajax security or haz tu propia pregunta.
Creo que tu primera impresión es correcta. Si comienza a buscar código e intenta recortar el flujo de entrada según la fuente, lo reconsiderará y lo hará de manera segura (y debido a las acciones de Google, más fácil). - Esteban Küber
probablemente una pregunta de seguimiento: ¿Por qué google antepone
)]}'
ahora en lugar dewhile(1);
? ¿Serían las mismas respuestas? - GizmoEvitaría eval, pero no con un bucle infinito. - Mardoxx
Este
)]}'
también puede ser para ahorrar bytes, como Facebook usafor(;;);
que guarda un byte :) - Gras DoubleEstrictamente hablando, eso no es JSON, es Javascript. - nilskp