Actualización del análisis de invulnerabilidad de Koa.js

Nov 26 2022
No hace mucho escribí sobre una vulnerabilidad que afectó a Koa.js en 2018.

No hace mucho tiempo, escribí sobre una vulnerabilidad que afectó a Koa.js en 2018. Estaba frustrado porque tenía que lidiar con un problema de 2018 cuando la fecha era 2022 y estaba usando la última versión de Koa. han pasado 4 años Eso es un largo tiempo. ¿¡Seguramente el problema ya no existe!? Y fue y no fue al mismo tiempo. Eso significa que estaba equivocado y correcto al mismo tiempo. Entonces, aquí hay una actualización de la publicación anterior para decirle cómo:

  • Acusé injustamente a Sonatype y Dependency Track de no operar con información de versión en casos específicos
  • Puedo tener razón y estar equivocado al mismo tiempo sobre una vulnerabilidad

El índice OSS tiene información de la versión

Si ha leído mi publicación anterior, probablemente recuerde que llegué a la conclusión de que el problema no me afectaba. La buena noticia es que tenía razón. La mala noticia es que acusé injustamente a Sonatype de no tener los números de versión en los datos proporcionados por OSS Index para Dependency Track para trabajar. Resulta que tienen la información. Simplemente no era visible donde esperaba que debería haber sido visible. Vea la siguiente captura de pantalla tomada el 22/11/2022.

Falta información sobre las versiones afectadas

Es muy probable que Dependency Track (DT) no funcione exactamente con lo que se muestra en la página anterior, pero no me importó verificar cómo se veían los datos que DT obtiene del índice OSS. DT acaba de mostrar un enlace a OSS Index, donde pude obtener más información. Hice clic y aterricé en esta página.
Sonatype me informó hoy que los números de versión están disponibles; Tengo que buscar en otro lado. De hecho, si inicia sesión en su cuenta y busca Koa o hace clic en el botón "Ver detalles de koa" en la captura de pantalla anterior, puede encontrarlo. Vea la captura de pantalla a continuación.

Contador de Koa por versión y vulnerabilidad básica

Así que estaba equivocado. Sonatype tiene la información en la base de datos. Entonces, el problema está en la capa de presentación. Sería mejor si tuvieran las versiones afectadas enumeradas en la página donde se analiza la vulnerabilidad para que podamos ver y verificar si es necesario.

Acusé injustamente a Sonatype OSS Index de no tener la información de la versión. También acusé injustamente a Dependency Track de estar dispuesto a informar basándose únicamente en el nombre de la dependencia si la información de la versión no estaba disponible. (Todavía necesito averiguar si esto último es verdadero o falso, no lo verifiqué).

¡No te rindas todavía! Las cosas más emocionantes para discutir son la vulnerabilidad real y los próximos cambios (con suerte) en el informe de vulnerabilidad en OSS Index. Comencemos con la vulnerabilidad.

Secuencias de comandos entre sitios

Sonatype atribuyó XSS a Koa basándose en el siguiente proceso de pensamiento.

Koa es la entidad que escribe la URL en la respuesta HTML, no el desarrollador que usa Koa

Definitivamente, es razonable esperar que el desarrollador valide la URL proporcionada, probablemente contra una lista de permitidos, para evitar una redirección abierta y no Koa, ya que Koa no tendría idea de qué URL le gustaría permitir o no. Sin embargo, como desarrollador, no creo que deba preocuparme por realizar una desinfección XSS para una URL que estoy pasando a un método redirect().

Koa parece preocuparse por XSS en este contexto, ya que ya tienen un código allí para evitarlo, la entidad HTML codifica la URL cuando la escriben en el HTML.

Estoy de acuerdo hasta cierto punto. No estoy de acuerdo con es el siguiente, por ejemplo.

No creo que deba preocuparme por realizar una desinfección XSS para una URL que estoy pasando a un método de redirección ()

Si pasa una URL válida y segura a un método de redirección que usted (el desarrollador) proporcionó, no tiene que preocuparse por XSS (obviamente). Si pasa total o parcialmente datos proporcionados por el usuario, eso es algo de lo que siempre debe preocuparse, ya sea un desarrollador o un profesional de la seguridad. Aún así, no es descabellado esperar que Koa ayude al desarrollador.

Déjame darte un excelente ejemplo que espero ayude a entender de dónde vengo. En el siguiente ejemplo, paso los datos proporcionados por el usuario al navegador en el cuerpo de la respuesta. Hago esto sin ninguna validación, desinfección o codificación.

const Koa = require('koa');
const app = new Koa();

app.use(async ctx => {
  ctx.body = ctx.query.payload;
});

app.listen(4444);

*   Trying 127.0.0.1:4444...
* Connected to 127.0.0.1 (127.0.0.1) port 4444 (#0)
> GET /?payload=<img%20src=x%20onerror=alert(1)> HTTP/1.1
> Host: 127.0.0.1:4444
> User-Agent: curl/7.79.1
> Accept: */*
> 
* Mark bundle as not supporting multiuse
< HTTP/1.1 200 OK
< Content-Type: text/html; charset=utf-8
< Content-Length: 28
< Date: Wed, 23 Nov 2022 10:59:17 GMT
< Connection: keep-alive
< Keep-Alive: timeout=5
< 
* Connection #0 to host 127.0.0.1 left intact
<img src=x onerror=alert(1)>%

  • Piense en qué y cómo le paso al navegador en el cuerpo de la respuesta.
  • Considere (¡y probablemente sea mejor controlar explícitamente!) el valor del encabezado Content-Type para la respuesta
  • Sepa que Koa, de forma predeterminada, ajusta automáticamente el valor del encabezado Content-Type en función del valor pasado a ctx.body. (Prueba a pasar, por ejemplo aaa, y verás cómo cambia)

Teniendo en cuenta el ctx.bodyejemplo "XSS" anterior, parece que estuviéramos culpando a Koa por implementar medidas específicas para prevenir un desastre al usar ctx.redirect(). Citando de nuevo a Sonatype:

Koa parece preocuparse por XSS en este contexto, ya que ya tienen código allí.

¿Significa esto que si a Koa no le importara XSS en este contexto, del mismo modo que no les importaba (y no deberían) importarle cuando se trata de ctx.body, nadie lo habría marcado como una vulnerabilidad XSS? Eso es bastante divertido. Noté algunas similitudes con mi análisis anterior sobre Formidable documentado aquí y aquí .

Habiendo dicho lo que dije hasta ahora, un XSS está ahí... y no al mismo tiempo. ¿Cómo es eso posible? ¡Simple! Está ahí, pero no puedes explotarlo a menos que:

  1. La víctima utiliza un navegador web antiguo, Y
  2. Hay una redirección abierta implementada por el desarrollador usando Koa's ctx.redirect(), AND
  3. El desarrollador confía completamente en todos los datos proporcionados por el usuario y los pasa textualmente actx.redirect()

La página del informe de Sonatype decía, como puede ver en la captura de pantalla de hoy, "Abrir redirección que conduce a Cross-Site Scripting". Mi publicación anterior cuestionó la parte de "redireccionamiento abierto":

En primer lugar, no había una redirección abierta. Solo está abierto si lo abre y la diferencia entre los dos PoC (el original y el mío) lo muestra claramente.

Sonatype también acepta que Koa no es responsable de evitar los redireccionamientos abiertos. Su preocupación, mi preocupación y la principal preocupación de todos los demás era el XSS. Participar en la redirección abierta fue simplemente confuso. Al mismo tiempo, técnicamente no era descabellado, como veremos más adelante. (También afectará la puntuación de vulnerabilidad).

Como se mencionó anteriormente, explotar con éxito el comportamiento de Koa requiere una redirección abierta. Pero:

  • Koa no es responsable de evitar los redireccionamientos abiertos (como se concluyó anteriormente)
  • Koa no se ejecutará ctx.redirect()sin la aprobación del desarrollador.
  • Koa no obliga a los desarrolladores a usar redireccionamientos

Entonces, hay otra capa de protección: los casos de uso. ¿Qué tan probable es que un desarrollador no quiera cierto control sobre a dónde se redirige un navegador? Muy improbable. Esto significa que, muy probablemente, los desarrolladores pasarán datos controlados por el usuario para ctx.redirect()agregarlos a otra cadena. Entonces, algo similar a los ejemplos que se muestran a continuación es lo más probable que suceda:

ctx.redirect(`http://website.example.org/search?q=${userInput}`);
ctx.redirect(`/search?topic=${userInput}`);

Puntuación de vulnerabilidad

Deben cumplirse tres (3) condiciones para que el error sea explotable, como se explica al final de la sección anterior.

  • La versión de un navegador que se utiliza depende del usuario final.
  • El uso del método de redirección y cómo se usa depende del desarrollador.

Lo que también requiere énfasis es que el uso del método de redireccionamiento de manera insegura es el vector de ataque. Se requiere un vector de ataque para una explotación exitosa. Koa no proporciona el vector de ataque; lo hace el desarrollador.

Correlacionemos esto con la definición de "vulnerabilidad de software" proporcionada por NIST:

https://csrc.nist.gov/glossary/term/software_vulnerability

La parte que me gustaría destacar es “podría ser explotada”. Tome Koa como una biblioteca de software. ¿Puede explotarlo sin crear primero el vector de ataque requerido? No. Entonces, desde la perspectiva de Koa, una biblioteca de software, no se presenta ningún vector de ataque; sin eso, la explotación es imposible. Si interpretáramos la definición estrictamente (lo cual hago), no podríamos llamar vulnerabilidad al comportamiento de Koa.
Intentemos calcular una puntuación CVSS sin un vector de ataque:

Cálculo de la puntuación CVSS sin vector de ataque

No hay puntuación si no hay vector de ataque. Diría que esto es consistente con la definición de vulnerabilidad de software proporcionada por NIST.
Experimentemos y creemos un escenario imaginario donde exista un vector de ataque.

Vector de ataque ficticio

Todavía hay varios problemas aquí, además del vector de ataque imaginario. La Complejidad del ataque se configuró en Alta porque la explotación exitosa requiere un navegador antiguo. Un atacante debe convencer a las víctimas para que descarguen e instalen un navegador antiguo.
En ese sentido, se requiere la interacción del usuario, aunque las métricas base de la interacción del usuario no se tratan realmente de eso. En este escenario, si explotar el XSS requiere la interacción del usuario depende de cómo la aplicación web usó los redireccionamientos y no de Koa. También vale la pena mencionar que el JavaScript inyectado no se ejecutaría por sí solo, ya que requería la interacción del usuario en primer lugar: hacer clic en el enlace en la respuesta HTML.

Entonces, ¿qué podemos hacer para forzar un puntaje de vulnerabilidad en esto? Debemos seleccionar algo. Ilusiones, suponiendo lo peor, lo que prefieras. Una cosa es segura, estás haciendo un cálculo que se supone que no debes hacer en primer lugar, y el resultado está tan lejos de la realidad que ni siquiera puedo encontrar las palabras para ello.

La próxima gran novedad son las métricas de impacto. Debe saber de qué se trata la Aplicación Web para contar el impacto. Pero no estamos calculando un puntaje de vulnerabilidad para una aplicación web... Dado el contexto, este XSS tiene un impacto cero en Koa. Koa no maneja ni procesa información confidencial por su cuenta. El error no tiene ningún impacto en la disponibilidad o la integridad. Eso nos deja con una puntuación final de 0,0, incluso después de forzar un vector de ataque en el cálculo.

Entonces la pregunta es, ¿reportamos hechos o ficción?

Sonatype me llamó la atención sobre la guía oficial para la puntuación de vulnerabilidades en las bibliotecas de software , que se lanzó en 2019 con CVSSv3.1. Admito que no lo sabía, lo cual es bueno y malo. Bueno porque habría resultado en una publicación despotricante, malo porque tal vez si lo hubiera visto antes, habría perdido toda esperanza antes de esforzarme tanto en tratar de explicar que no es la forma correcta de hacerlo. Entonces, ¿qué dice la guía oficial?

Al puntuar el impacto de una vulnerabilidad en una biblioteca... El analista debe puntuar para el peor escenario de implementación razonable. Cuando sea posible, la información del CVSS debe detallar estos supuestos.

Entonces, la respuesta es que la puntuación de vulnerabilidad se basa en la ficción.

Además, ¿qué es un “ escenario de implementación razonable en el peor de los casos”? Si analizamos muchos proyectos que usaron Koa y descubrimos que la mayoría de los desarrolladores implementaron redireccionamientos abiertos usando el ctx.redirect()método de Koa, podría ser razonable suponer lo peor. Hice una búsqueda rápida de código en proyectos de JavaScript ctx.redirect(en GitHub. Obtuve 16,827 resultados de código. Buscando context.redirect(Recibí 15,751 resultados de código. Serían 32.578 resultados de código para analizar. Algunos de estos usarán Koa, algunos Express y algunos pueden ser algo más. (Por supuesto, el contexto podría recibir cualquier nombre, no solo ctxo context, por lo que podría haber aún más código para ver).

La pregunta es: ¿pasar datos proporcionados por el usuario sin cerebro para redirigir con tanta frecuencia? Tomé un enfoque semiautomatizado para el análisis escribiendo un pequeño script para verificar todos los proyectos que coincidían con los criterios de búsqueda. Desafortunadamente, no pude superar las primeras 1000 visitas ya que GitHub rechazó más solicitudes:

{
    "message":"Only the first 1000 search results are available",
    "documentation_url":"https://docs.github.com/v3/search/"
}

Según lo que he visto y teniendo en cuenta lo que se analiza en la siguiente sección ("El antiguo navegador web"), no creo que sea razonable asumir una implementación en el peor de los casos. No en este caso específico.

La guía oficial también dice que:

Al puntuar una vulnerabilidad en una implementación determinada utilizando la biblioteca afectada, la puntuación debe volver a calcularse para esa implementación específica.

Esto es razonable y mitiga el aspecto de ciencia ficción de la situación hasta cierto punto. Así es como este problema de Koa, con un puntaje de vulnerabilidad de 9.8, terminó siendo 0.0 en nuestro caso.

Lo bueno es que Sonatype estuvo de acuerdo en que el puntaje de vulnerabilidad de 9.8 no era razonable y están dispuestos a reducirlo. Lo aprecio, y probablemente muchos otros también lo harán.

Además, Sonatype me dijo que cuando agregaron el problema a su sistema, creyeron que sería mejor que sus clientes supieran sobre esta situación potencialmente inesperada. Dijeron, "era mejor alertar que ignorar lo que vimos y potencialmente tener un resultado negativo". Y, por supuesto, tenían razón.

Nunca cuestioné si los problemas de seguridad deberían comunicarse o no. Sí, los problemas de seguridad deben hacerse visibles. Lo que me preocupa es cómo se comunican estos problemas:

  • ¿Es apropiado llamar a algo una vulnerabilidad o más apropiado llamarlo una debilidad de seguridad o un comportamiento predeterminado inseguro, etc.?
  • ¿Es razonable la puntuación de vulnerabilidad asignada?
  • ¿Se proporcionan suficientes detalles y contexto?

Ahora hablemos un poco sobre los antiguos navegadores web.

El antiguo navegador web

Sin la buena gente de Sonatype, no habría pensado en navegadores web antiguos, probablemente nunca más.

Continuaré sin considerar los navegadores antiguos también en el futuro. En primer lugar, hay demasiadas cosas a tener en cuenta; No puedo preocuparme por los navegadores web antiguos. En segundo lugar, ¿qué edad tiene ( ¡no hagas clic en el enlace si no tienes sentido del humor! ) un navegador web antiguo? ¿Qué significa realmente "viejo"? Si alguien usa solo un navegador de ~ 1 año, es muy probable que ya tenga problemas mucho más grandes que XSS.

Aún así, investigué un poco y encontré que:

  • Google Chrome 48.0.2564.109 (64 bits) de 2016 (!) ni siquiera mostraba el cuerpo de la respuesta. Como el problema de Koa se encontró en 2018, pensé que retroceder hasta 2016 debería ser suficiente, pero resultó que no lo fue.
  • Firefox 4.0 de 2011 mostraba el cuerpo de la respuesta, pero requería que los usuarios hicieran clic en el enlace para que se ejecutara la carga útil de JavaScript. (¡Por supuesto, es un enlace!)
  • Firefox 52.0 de 2017, 1 año antes de que se informara el problema de Koa XSS, ya no mostraba el cuerpo de respuesta con la carga útil de JavaScript. Firefox acaba de arrojar un error que dice "Error de contenido dañado" debido a una "violación del protocolo de red".

Koa 0.0.1 se lanzó en 2013, por lo que hubo algunos años en los que el problema podría haberse aprovechado. A partir de ahora, probablemente sería aceptable marcar este problema (todavía no con una puntuación de 9,8) hasta Koa 2.5.0 en 2018. Después de eso, sin embargo, nada justifica nada por encima de 1,0.

Mientras investigaba, encontré algo interesante en Wikipedia . Permítanme citar:

Firefox 15 se lanzó el 28 de agosto de 2012... Firefox 15 introdujo actualizaciones silenciosas, una actualización automática que actualizará Firefox a la última versión sin notificar al usuario, [65] una característica que tienen los navegadores web Google Chrome e Internet Explorer 8 y superior ya implementado

Por lo tanto, todos los principales navegadores web tenían una función de actualización automática antes de que se lanzara la primera versión de Koa, lo que significa que es probable que la mayoría de los usuarios estuvieran usando un navegador web actualizado. Veamos el estado en el momento del “big bang”: 2013.

  • Firefox 15 : devolvió un error que decía "Error de contenido dañado", lo que significa que el cuerpo de la respuesta no se mostró al usuario.
  • Chrome 24.0.1312 (WebKit 537.17) : no mostró ningún cuerpo de respuesta. Mientras miraba la pestaña de red de las herramientas de desarrollo, apenas había nada visible, así que tuve que ejecutar Wireshark para ver si el navegador realizó la solicitud en primer lugar. En Wireshark, era visible que Chrome se comunicó con mi servicio PoC y recibió la respuesta con la carga útil de JavaScript. No representó el cuerpo de la respuesta. Aún mejor, no pasó nada.
  • Internet Explorer 11 (11.0.9600.19180) : obtuvo la respuesta de mi servicio PoC, que verifiqué con Wireshark. No mostraba el cuerpo de la respuesta al usuario. Regresó con la clásica página de error incorporada que dice: "Esta página no se puede mostrar".

Habiendo hecho la investigación anterior, volvamos a una cita de Sonatype por un segundo:

Koa parece preocuparse por XSS en este contexto, ya que ya tienen un código allí para evitarlo, la entidad HTML codifica la URL cuando la escriben en el HTML.

Si bien esta afirmación es correcta, el hecho de que ninguno de los principales navegadores permitiera la explotación en el momento en que se lanzó la primera versión de Koa sugiere algo interesante, algo diferente de lo que la oración quisiera sugerir. Tenga en cuenta que estoy a punto de escribir especulaciones ya que no puedo saber con precisión cómo estaban pensando los desarrolladores de Koa. Puedo imaginar fácilmente que los desarrolladores probaron el comportamiento en cuestión usando un navegador web actualizado. Es posible que hayan descubierto que la codificación HTML era adecuada porque ya era imposible inyectar código JavaScript ejecutado desde la hrefpropiedad delaetiqueta. Esto plantea una pregunta seria. Habiendo pasado los últimos cinco años más en el lado del desarrollo de software, también se aplica a mí: como desarrollador, si estoy a punto de crear una nueva tecnología web para el backend, ¿debería preocuparme por los navegadores web antiguos? Y si debería, ¿cuál es la recomendación oficial de la comunidad de seguridad con respecto a cuánto tiempo atrás en el tiempo debo considerar los navegadores web antiguos? ¿No deberíamos considerar que la mejor práctica de seguridad para los usuarios finales es mantener sus navegadores actualizados, y la función de actualización automática también está ahí para ayudar con eso? Además, si esperamos que los desarrolladores tengan en cuenta y prueben con navegadores antiguos, ¿no podemos esperar que los profesionales de seguridad hagan lo mismo y nombren todos los navegadores web y sus versiones que contribuyen a un problema específico en lugar de simplemente referirse a "navegadores antiguos"? ”? Sería justo.

Una cosa es segura, no hay nada de qué preocuparse desde hace años...

El navegador moderno

En mi análisis, usando mi navegador web, revisé el cuerpo de la respuesta y lo encontré vacío. No verifiqué si la respuesta enviada por cable tenía un cuerpo. Resulta que fue solo Google Chrome el que ignoró por completo el cuerpo de la respuesta; por lo tanto, no se mostró. Eso fue lo suficientemente bueno para mí. Razonablemente, tengo que añadir.

Desde entonces, he analizado la respuesta de mi servicio web de prueba con la última versión de Koa. Podemos ver a continuación que había un cuerpo de respuesta HTML con el código JavaScript inyectado allí:

*   Trying 127.0.0.1:4444...
* Connected to 127.0.0.1 (127.0.0.1) port 4444 (#0)
> GET /?payload=javascript:alert(1); HTTP/1.1
> Host: 127.0.0.1:4444
> User-Agent: curl/7.79.1
> Accept: */*
> 
* Mark bundle as not supporting multiuse
< HTTP/1.1 302 Found
< Location: javascript:alert(1);
< Content-Type: text/html; charset=utf-8
< Content-Length: 71
< Date: Tue, 22 Nov 2022 17:55:12 GMT
< Connection: keep-alive
< Keep-Alive: timeout=5
< 
* Connection #0 to host 127.0.0.1 left intact
Redirecting to <a href="javascript:alert(1);">javascript:alert(1);</a>.

*   Trying 127.0.0.1:4444...
* Connected to 127.0.0.1 (127.0.0.1) port 4444 (#0)
> GET /?payload=%22><%2f HTTP/1.1
> Host: 127.0.0.1:4444
> User-Agent: curl/7.79.1
> Accept: */*
> 
* Mark bundle as not supporting multiuse
< HTTP/1.1 302 Found
< Location: %22%3E%3C/
< Content-Type: text/html; charset=utf-8
< Content-Length: 61
< Date: Tue, 22 Nov 2022 22:18:49 GMT
< Connection: keep-alive
< Keep-Alive: timeout=5
< 
* Connection #0 to host 127.0.0.1 left intact
Redirecting to <a href="&quot;&gt;&lt;/">&quot;&gt;&lt;/</a>.

Próximos cambios

A continuación se muestra la lista de actualizaciones que Sonatype planea implementar con respecto a este problema:

  • Actualización de la línea Resumen/Título para eliminar malentendidos (ya sucedió)
  • Reducir el puntaje de vulnerabilidad a 4.7 (ya sucedió)
  • Mencione que la vulnerabilidad solo se puede explotar si un usuario está ejecutando un navegador más antiguo

Cambios adicionales que me gustaría ver

Además de los cambios mencionados en la sección anterior, algunas cosas podrían mejorarse aún más. Estos son:

  • Reduciendo aún más el puntaje de vulnerabilidad, especialmente para las versiones de Koa lanzadas después de 2018.
  • Incluyendo el número de versión de al menos los principales navegadores web y sus fechas de lanzamiento incluidas en el informe cuando se hace referencia a los "navegadores más antiguos". Esto ayudaría significativamente a cualquier persona al "puntuar una vulnerabilidad en una implementación determinada utilizando la biblioteca afectada". Por ejemplo, si vi que un usuario tenía que usar un navegador de 2011, habría marcado el problema como "no afectado" en SCA en un segundo. Es mucho tiempo ahorrado.
  • Las versiones de Koa afectadas se listarán en la página de vulnerabilidades .

Por cierto, Sonatype también mencionó que tienen algunos controles geniales en su oferta comercial que, por ejemplo, realizan controles reales en el nivel de código para ver si una aplicación se vio afectada por las vulnerabilidades informadas. Eso suena genial, y dada la naturaleza de ciencia ficción de cómo se calculan los puntajes de vulnerabilidad para las bibliotecas, este tipo de controles son imprescindibles para reducir la carga de los equipos de ingeniería, especialmente si las cosas continúan así.

Conclusión

Eso es casi todas las actualizaciones que tengo. Me alegro de haber contactado con Sonatype porque son muy profesionales y amables. Fue un placer trabajar con ellos en esto.

En cuanto al XSS en Koa: es algo que ninguno de nosotros debería haber estado preocupado desde hace varios años.