
JSONP , o JSON-P (JSON con relleno), es una técnica de JavaScript para solicitar datos a través del <script>elemento HTML . [ 1 ] Fue propuesta por Bob Ippolito en 2005. [ 2 ] JSONP permite compartir datos eludiendo la política del mismo origen, que no permite que el código JavaScript en ejecución lea elementos DOM de medios o datos XMLHttpRequest obtenidos desde fuera del sitio de origen de la página. El sitio de origen se indica mediante una combinación de esquema URI , nombre de host y número de puerto .
Las solicitudes JSONP son vulnerables a que la fuente de datos responda con código malicioso, razón por la cual se ha mejorado mediante CORS ( intercambio de recursos de origen cruzado , disponible desde 2009 [ 3 ] ) en las aplicaciones modernas.
Funcionalidad
Generalmente, el elemento HTML puede ejecutar código JavaScript obtenido de fuentes externas. Antes de la adopción de CORS, los servicios que respondían con datos JSON puros no podían compartir datos de fuentes externas. <script>
Por ejemplo, una solicitud CORS a un servicio externo http://server.example.com/Users/1234puede devolver una respuesta JSON. Sin embargo, intentar usar los datos entre dominios sin CORS produce un error de JavaScript.
Cuando http://server.example.com/Users/1234se pasa como srcatributo a una <script>etiqueta, el navegador descarga el archivo, evalúa su contenido, interpreta erróneamente los datos JSON sin procesar como un bloque y genera un error de sintaxis. Incluso si los datos JSON sin procesar se interpretaran como un literal de objeto JavaScript, los literales de objeto son inaccesibles sin una asignación de variable.
JSONP resuelve esto mediante un acuerdo entre el cliente y el servidor sobre un argumento de consulta codificado en URL, convencionalmente `<script>` jsonpo ` callback<script>`, que el cliente utilizará para definir el texto que el servidor antepondrá a su respuesta, y envolverá la carga útil JSON entre paréntesis, lo que dará como resultado un documento JavaScript. Cuando la URL codificada se pasa al srcatributo del elemento, el cliente envía la solicitud JSONP y el documento JavaScript de respuesta del servidor se carga en el navegador. Normalmente, esto se utiliza para llamar a una función definida en el entorno JavaScript y manipular los datos JSON de la respuesta.<script>
Un ejemplo de solicitud JSONP ahttp://server.example.com/Users/1234
<script type="application/javascript" src="<nowiki>http://server.example.com/Users/1234?jsonp=parseResponse</nowiki>"> </script>
En este ejemplo, el cliente definió parseResponseel texto como texto de preámbulo. La respuesta del servidor sería:
parseResponse({"Name": "Foo", "Id": 1234, "Rank": 7});Aquí parseResponse()está la "P" de JSONP: el "relleno" alrededor del JSON puro. [ 4 ]
Inyección de elementos de script
JSONP solo tiene sentido cuando se usa con un elemento de script. Para cada nueva solicitud JSONP, el navegador debe agregar un nuevo elemento o reutilizar uno existente. La primera opción (agregar un nuevo elemento de script) se realiza mediante manipulación dinámica del DOM y se conoce como inyección de elementos de script . El elemento se inyecta en el DOM HTML, con la URL del punto final JSONP deseado establecida como atributo. Esta inyección dinámica de elementos de script generalmente se realiza mediante una biblioteca auxiliar de JavaScript. jQuery y otros frameworks tienen funciones auxiliares de JSONP; también existen opciones independientes.<script><script>src
Un ejemplo de cómo usar jQuery para inyectar dinámicamente un elemento de script para una llamada JSONP se ve así:
$ . getScript ( "http://server.example.com/Users/192.168.73.96?callback=parseResponse" );Una vez inyectado el elemento, el navegador lo evalúa y realiza una solicitud HTTP GET a la URL de origen, recuperando el contenido. A continuación, el navegador interpreta la respuesta como JavaScript. Normalmente, se trata de una llamada a una función. De este modo, el uso de JSONP permite que las páginas web eludan la política de mismo origen mediante la inyección de elementos de script. [ 5 ]
El script se ejecuta dentro del ámbito de la página que lo incluye y, por lo tanto, sigue sujeto a las restricciones de dominio cruzado relativas al dominio de dicha página. Esto significa que una página web no puede, por ejemplo, cargar una biblioteca alojada en otro sitio mediante JSONP y luego realizar solicitudes XMLHttpRequest a ese sitio (a menos que se admita el uso compartido de recursos de origen cruzado (CORS)), aunque sí se podría usar dicha biblioteca para realizar solicitudes XMLHttpRequest al propio sitio.
Preocupaciones de seguridad
Código de terceros no confiable
Incluir elementos de script desde servidores remotos permite que estos inyecten cualquier contenido en un sitio web. Si los servidores remotos presentan vulnerabilidades que permiten la inyección de JavaScript, la página servida desde el servidor original queda expuesta a un mayor riesgo. Si un atacante puede inyectar JavaScript en la página web original, dicho código puede obtener JavaScript adicional de cualquier dominio, eludiendo la política del mismo origen . [ 6 ] El encabezado HTTP de la Política de Seguridad de Contenido permite que los sitios web indiquen a los navegadores web de qué dominio pueden provenir los scripts.
En torno a 2011 se emprendió un esfuerzo para definir una definición de subconjunto estricto más segura para JSONP [ 1 ] que los navegadores podrían aplicar a las solicitudes de script con un tipo MIME específico , como "application/json-p". Si la respuesta no se analizaba como JSONP estricto, el navegador podía generar un error o simplemente ignorar la respuesta completa. Sin embargo, este enfoque se abandonó en favor de CORS , y el tipo MIME correcto para JSONP sigue siendo [ 7 ]application/javascript .
Diferencias de espacio en blanco
JSONP presentaba los mismos problemas que la resolución de JSON con eval(): ambos interpretaban el texto JSON como JavaScript, lo que implicaba diferencias en el manejo de U+2028 ( separador de línea ) y U+2029 ( separador de párrafo ) con respecto al JSON propiamente dicho. Esto hacía que algunas cadenas JSON no fueran válidas en JSONP; los servidores que servían JSONP tenían que escapar estos caracteres antes de la transmisión. [ 8 ] Este problema se ha corregido en ES2019. [ 9 ]
Manipulación del nombre de la función de devolución de llamada y ataque de descarga de archivos reflejados
Los nombres de devolución de llamada no sanitizados pueden usarse para pasar datos maliciosos a los clientes, eludiendo las restricciones asociadas con application/jsonel tipo de contenido, como se demostró en el ataque de descarga de archivos reflejada (RFD) de 2014. [ 10 ]
Los puntos finales JSONP inseguros también pueden ser inyectados con datos maliciosos. [ 11 ]
Falsificación de solicitudes entre sitios
Las implementaciones ingenuas de JSONP son vulnerables a ataques de falsificación de solicitudes entre sitios (CSRF o XSRF). [ 12 ] Debido a que el elemento HTML no respeta la política del mismo origen en las implementaciones de los navegadores web , una página maliciosa puede solicitar y obtener datos JSON pertenecientes a otro sitio. Esto permitirá que los datos codificados en JSON se evalúen en el contexto de la página maliciosa, lo que podría revelar contraseñas u otros datos confidenciales si el usuario ha iniciado sesión en dicho sitio.<script>
Flash de Rosetta
Rosetta Flash es una técnica de explotación que permite a un atacante explotar servidores con un endpoint JSONP vulnerable, haciendo que Adobe Flash Player crea que un applet Flash especificado por el atacante se originó en el servidor vulnerable. Flash Player implementa la política de mismo origen , lo que permite realizar solicitudes (con cookies) y recibir respuestas del sitio de alojamiento. El applet puede entonces enviar los datos recuperados de vuelta al atacante. Se trata de una explotación de origen cruzado con un impacto similar al de incrustar un applet Flash arbitrario en el dominio vulnerable. La explotación utiliza una carga útil de ActionScript compilada en un archivo SWF compuesto completamente por caracteres alfanuméricos, mediante la creación de un flujo zlib con un encabezado específico y bloques DEFLATE con codificación Huffman ad-hoc. El archivo SWF resultante, que solo contiene caracteres alfanuméricos, se utiliza como parámetro de devolución de llamada de una llamada JSONP. Sitios de alto perfil como Google, YouTube , Twitter , Yahoo!, Yandex, LinkedIn , eBay, GitHub, Instagram y Tumblr fueron vulnerables hasta julio de 2014. [ 13 ] Esta vulnerabilidad fue descubierta inicialmente por Erling y Alok Menghrajani, con una presentación pública en una conferencia de seguridad. La explotación de la vulnerabilidad fue posteriormente mejorada por Gábor Molnár. El ingeniero de seguridad de Google Michele Spagnuolo acuñó el término [ 14 ] y tiene CVE - 2014-4671 [ 15 ] y CVE- 2014-5333 . [ 16 ] La versión 14.0.0.145 de Adobe Flash Player, publicada el 8 de julio de 2014, introdujo una validación más fuerte de los archivos Flash, [ 17 ] y en la versión 14.0.0.176, publicada el 12 de agosto de 2014, finalizó la corrección, [ 18 ] impidiendo que este exploit funcionara.
Antes de la solución de Adobe, los sitios web podían protegerse anteponiendo un comentario JavaScript vacío (/**/) o incluso simplemente un salto de línea como primeros bytes de la respuesta JSONP.
Historia
En julio de 2005, George Jempty sugirió que se antepusiera una asignación de variable opcional a JSON. [ 19 ] [ 20 ] La propuesta original para JSONP, donde el relleno es una función de devolución de llamada, parece haber sido hecha por Bob Ippolito en diciembre de 2005 [ 21 ] y ahora es utilizada por muchas aplicaciones Web 2.0 como Dojo Toolkit y Google Web Toolkit .
Véase también
Referencias
- 1 2 "Ajax entre dominios más seguro con JSON-P/JSONP" . JSON-P.org . Archivado del original el 4 de marzo de 2016. Recuperado el 30 de octubre de 2011 .
- ↑ Ippolito, Bob (5 de diciembre de 2005). "Remote JSON - JSONP" . Bob Ippolito sobre Haskell, Python, Erlang, JavaScript, etc. Archivado del original el 8 de junio de 2012. Recuperado el 10 de febrero de 2017 .
- ↑ "Intercambio de recursos de origen cruzado" . ¿Puedo usarlo... ? Consultado el 4 de mayo de 2020 .
- ↑ "Traductor experimental de conjunto de resultados RDF a JSON" . Archivado del original el 15 de noviembre de 2014. Recuperado el 20 de febrero de 2012 .
- ↑ "¿Cómo funciona realmente JSONP? Algunos ejemplos sencillos" . Jason Schock . 5 de febrero de 2013. Archivado del original el 26 de diciembre de 2021. Consultado el 26 de diciembre de 2021 .
- ^ Ben Hayak (17 de octubre de 2014). "Ejecución del método del mismo origen" (PDF) . Consultado el 22 de octubre de 2014 .
- ↑ Grey, Eli (27 de junio de 2010). "¿Es seguro esto para proporcionar JSONP?" . stackoverflow.com . Consultado el 7 de septiembre de 2012 .
- ↑ "JSON: El subconjunto de JavaScript que no es" . Magnus Holm. Archivado del original el 13 de mayo de 2012. Recuperado el 16 de mayo de 2011 .
- ^ "Subsumir JSON (también conocido como JSON ⊂ ECMAScript)" . GitHub . 24 de octubre de 2022 . Consultado el 24 de octubre de 2022 .
- ↑ Oren Hafif (2014). "Reflected File Download - A New Web Attack Vector" . TrustWave . Consultado el 25 de marzo de 2015 .
- ↑ "Inyección práctica de JSONP" . 18 de enero de 2017.
- ↑ Grossman, Jeremiah (27 de enero de 2006). "Técnicas avanzadas de ataque web usando GMail" . Recuperado el 3 de julio de 2009 .
- ↑ Michele, Spagnuolo. "Abuso de JSONP con Rosetta Flash" . Archivado del original el 21 de julio de 2014. Recuperado el 20 de julio de 2014 .
- ↑ "Google - lista de vulnerabilidades de software descubiertas o corregidas por empleados de Google" . Consultado el 29 de julio de 2014 .
- ↑ "MITRE: CVE-2014-4671" . Consultado el 29 de julio de 2014 .
- ↑ "MITRE: CVE-2014-5333" . Consultado el 21 de agosto de 2014 .
- ↑ "Boletín de seguridad de Adobe APSB14-17" . Consultado el 29 de julio de 2014 .
- ↑ "Boletín de seguridad de Adobe APSB14-18" . Consultado el 21 de agosto de 2014 .
- ↑ "evaluando JSON" . 19 de julio de 2005. Archivado del original el 12 de febrero de 2006.
- ↑ "json: Message: Re: Comments" . 17 de agosto de 2005.
{{cite web}}: CS1 maint: servicio de archivado obsoleto ( enlace ) - ↑ "Remote JSON - JSONP" . from __future__ import * . Bob.pythonmac.org. 5 de diciembre de 2005. Archivado del original el 4 de diciembre de 2009. Consultado el 8 de septiembre de 2008 .
Enlaces externos
- El filtro del lado del servidor encapsula cualquier respuesta en una función de devolución de llamada JSONP , implementado con el código fuente de JSONP Java.
- Posibles problemas de seguridad relacionados con JSON
- Fuente de datos JSONP para dominios remotos
- Ajax (programación)
- JSON