hashes de contenido para ayudar a proteger los recursos que se obtienen de un CDN

17

Durante una conversación en The DMZ , se sugirió que se podría usar un hash SHA256 para verificar que el contenido que se entrega desde un CDN no haya cambiado antes de ejecutarse, de manera similar a como lo intentó el MEGA de Kim Dotcom hacer recientemente con CBC-MAC.

El mecanismo se implementaría a nivel del navegador, por lo que se incluiría un hash de contenido en el enlace al contenido. Por ejemplo:

<script src="http://example.cdn/jq/jquery-1.2.3.js"hash="sha256:kMufczNYKx9B2A7x7eICQVu18YDzEMqUe3G+h5QSifw=" />

El hash se proporcionaría como parte del código del sitio, de modo que solo se ejecutaría el contenido que coincida con el hash. Esto protegería al usuario contra los casos en que la CDN estaba comprometida. También ofrecería una manera de proporcionar seguridad mínima si se opera en modo de contenido mixto en el que todo excepto el CDN operaba con SSL.

¿Hay algún defecto en este enfoque? ¿Habría algún caso importante a considerar durante la implementación?

    
pregunta Polynomial 25.01.2013 - 14:18
fuente

3 respuestas

21

Actualización: Hay más información sobre Subresource Integrity en MDN , que (hasta 12/12/16) muestra soporte en Chrome 45+ y FireFox (Gecko) a partir de 43+

Actualización: Hay un borrador de w3c llamado Subresource Integrity que describe una característica como esta.

Ya está implementado en Chromium .

Por ejemplo:

<script src="file.js" integrity="ni://sha256;BpfBw7ivV8q2jLiT13…"></script>

El enfoque básico es una IMO sólida, pero hay algunos detalles que cuidar:

  • Debes admitir varios hashes en una sola etiqueta. El navegador no necesita validarlos todos, basta con validar un hash resistente a la colisión.
  • Ser capaz de especificar el tamaño parece útil para evitar algún tipo de DoS en el que su sitio recibe un gran recurso
  • A menos que esté usando un hash de árbol, no puede verificar archivos incompletos. Eso no es un problema para los archivos javascript de 100kB, pero es para un video de 5 GB. Por lo tanto, la compatibilidad con hashes de árbol se debe agregar más adelante.
  • Usaría identificadores de algoritmos que coincidan con NI - Nombrando cosas con hash , y use urlsafe Base64 sin relleno
  • Yo especificaría SHA-256 como el algoritmo estándar que todos los navegadores deberían admitir, pero permitiría a los navegadores agregar otros algoritmos. SHA-256 es:

    • resistente a colisiones a un nivel de 128 bits
    • un estándar NIST, las implementaciones están ampliamente disponibles (a diferencia de SHA-3)
    • el rendimiento no es excelente, pero es lo suficientemente rápido como para mantenerse al día con las velocidades de red típicas en dispositivos móviles.

    IMO SHA-256 es la opción ideal para el algoritmo predeterminado / obligatorio.

  • Debería admitir todos los recursos incrustados, CSS, imágenes, videos, etc. y no solo scripts

  • Uno podría considerar usar URL de NI en su lugar, pero prefiero el enfoque basado en atributos aquí. Un atributo es más flexible y no requiere la cooperación del host objetivo para implementarlo. NI solo puede especificar un solo hash por url.
  • Puede deshabilitar las advertencias de contenido mixto para el contenido de hash seguro que se obtuvo a través de http
  • Es una excelente manera de ver si su caché sigue siendo válida. Es válido si y solo si el hash coincide. No es necesario volver a verificar, fechas, etc. Esto también funciona si descargó el recurso desde una URL diferente. Por ejemplo, si ya tiene jquery de google en su caché, no necesita volver a cargarlo desde otra URL, ya que el mismo hash garantiza [asumiendo que la resistencia a la colisión] que serán los mismos.
  • Probablemente hay algunos problemas relacionados con la autenticación de los encabezados http, ya que influyen en la interpretación del recurso. Por ejemplo, el tipo mime y el conjunto de caracteres / codificación son tales encabezados.

Entonces, un ejemplo podría verse así:

<script src="http://example.cdn/jq/jquery-1.2.3.js"hash="sha-256:UyaQV-Ev4rdLoHyJJWCi11OHfrYv9E1aGQAlMO2X_-Q; size:103457;
           other-hash: abc..." />
    
respondido por el CodesInChaos 25.01.2013 - 14:29
fuente
3

Para agregar puntos positivos de @CodesInChaos: existía un mecanismo mucho más antiguo para admitir Javascript firmado . Esto viene de los días de Netscape 4 y aún está documentado , pero no está claro Si esto todavía es compatible con Firefox. Internet Explorer nunca lo admitió, aunque la gente de Microsoft jugó con la idea . El sistema se complementó con el formato de archivo Jar, que provenía del mundo Java.

Su método tiene el atractivo de parecer sencillo de implementar; y se podría hacer en Javascript directamente (el orden de magnitud del rendimiento de Javascript para el hashing es de aproximadamente 1 MB / s, lo que debería ser suficiente para los scripts).

Un inconveniente de su sistema, a tener en cuenta: si modifica la secuencia de comandos, debe alterar todas las páginas que lo hacen referencia con un hash explícito; esto puede ser bastante inconveniente en un sitio grande (¿está listo para buscar y reemplazar más de 10000 archivos estáticos?). Aquí es donde firmas puede ofrecer más flexibilidad.

    
respondido por el Thomas Pornin 25.01.2013 - 17:11
fuente
0

El problema más importante a resolver es cómo manejar una falta de coincidencia de hash. En ese caso, no debe aceptar el contenido, ya que de lo contrario perdería toda la ganancia de seguridad potencial. Pero una falta de coincidencia de hash puede tener razones bastante inocentes, como el recurso que se sirve en un nuevo formato / codificación de conexión (piense en un compresor sin pérdidas que reescribe una imagen PNG para obtener los mismos píxeles utilizando una representación diferente para una compresión gzip ligeramente mejor). O una codificación de caracteres diferente o manejo de nueva línea para sus Javascripts que no los modifique maliciosamente pero le da al archivo un nuevo hash ...

Para mí, la solución es encontrar fuentes que no cambien, por ejemplo. su propio CDN, o esos CDN públicos, como jsdelivr y cdnjs.com , que utiliza la versión explícita en lugar de servir la actualización automática mutable. Usando dichas fuentes, a continuación agregue confiabilidad mediante la codificación de las alternativas en ubicaciones alternativas.

Sé de dos implementaciones de eso, no en los propios navegadores, sino como implementaciones de Javascript de cargadores de recursos con verificación de integridad basada en sha256:

  1. VerifyJS
  2. needjs

Ambos también ofrecen una alternativa a direcciones URL de origen alternativas, lo que parece sensato considerando que la verificación de hash introduce un modo de falla adicional, la falta de coincidencia de hash.

Descargo de responsabilidad: Soy el autor de needjs y todavía no lo recomendaría para uso en producción. Tampoco he estudiado su uso para otros recursos que no sean Javascript y CSS todavía.

    
respondido por el pyramids 02.05.2014 - 18:19
fuente

Lea otras preguntas en las etiquetas