A principios de este año, se le pidió a nuestro equipo que ampliara nuestras herramientas de seguridad existentes y nuestras prácticas de desarrollo y prueba de software para el cumplimiento de PCI-DSS y SOC-2. Una de las áreas clave que tuvimos que ampliar fue el escaneo de vulnerabilidades para nuestros microservicios basados en K8s y un par de servicios monolíticos. Como resultado, nuestro equipo de DevOps tuvo que elegir entre algunas herramientas comerciales y soluciones de código abierto para implementar el escaneo de vulnerabilidades para nuestro software. Todas estas herramientas hacen cosas muy similares: escanean dependencias (ya sean bibliotecas de proyectos o paquetes del sistema operativo) y las comparan con bases de datos de vulnerabilidades (como NVD de NIST y otras).
Hay algunas herramientas de código abierto que se pueden utilizar para crear su propia solución de escaneo de vulnerabilidades, o puede utilizar un producto comercial que agregue características adicionales al escaneo básico que pueden facilitarle la vida. Los ejemplos incluyen:
La mayoría de las soluciones comerciales amplían las bases de datos de vulnerabilidades públicas con su propia base de datos de vulnerabilidades para eliminar falsos positivos/negativos y ofrecerle resultados más relevantes. Dicho esto, todas estas herramientas comerciales se vuelven realmente caras a medida que aumenta el número de desarrolladores. Por lo tanto, debe considerar si es “mejor” para usted comprar o construir su propia solución utilizando herramientas de código abierto existentes.
Inicialmente, decidimos que la herramienta comercial se adaptaría mejor a nuestras necesidades dada la limitación de tiempo que teníamos. Sin embargo, después de pasar 3 meses implementando y probando un producto comercial líder en la industria, enfrentamos muchos desafíos: soporte limitado para golang, seleccionaba dependencias incorrectas y no salía correctamente, problemas con contenedores creados desde cero vs. aquellos creados con alguna imagen base, etc. Como resultado, decidimos darnos por vencidos y pasar a construir nuestra propia herramienta utilizando las tecnologías de código abierto disponibles.
En esta publicación, te brindaré una base sólida para comenzar si decides optar por el código abierto. ¡Además, al final de la publicación encontrarás el enlace a nuestro repositorio de código abierto para que puedas comenzar!
Básicamente, hay dos cosas que conviene analizar en busca de vulnerabilidades:
En el futuro, es posible agregar más capacidades como verificación de licencias o análisis de código estático, pero eso está fuera del alcance de esta publicación.
En primer lugar, debes asegurarte de que tu código o el cambio de imagen de Docker no introduzcan ninguna vulnerabilidad nueva, por lo que es una buena idea escanear cada solicitud de fusión antes de fusionarla.
Pero también es necesario escanear periódicamente , ya que con el tiempo pueden aparecer nuevas vulnerabilidades. Además, la gravedad puede cambiar: una gravedad baja que inicialmente ignoraste puede volverse crítica con el tiempo a medida que se encuentra un nuevo vector de ataque o exploit. Mientras que las herramientas comerciales recuerdan el último escaneo y le notificarán si se encuentra una nueva vulnerabilidad, en nuestra solución de código abierto simplemente repetimos el escaneo sobre la rama maestra del proyecto.
Hay muchas herramientas de código abierto disponibles, pero nuestra elección fue Trivy porque es fácil de usar, está en desarrollo activo y puede escanear múltiples proyectos y tipos de sistemas operativos.
Trivy es un escáner de vulnerabilidades simple y completo para contenedores y otros artefactos. Una vulnerabilidad de software es un fallo, falla o debilidad presente en el software o en un sistema operativo. Trivy detecta vulnerabilidades de paquetes de SO (Alpine, RHEL, CentOS, etc.) y dependencias de aplicação (Bundler, Composer, npm, yarn, etc.). Trivy es fácil de usar: ¡simplemente instala el binario y estarás listo para escanear! Todo lo que necesita hacer para escanear es especificar un objetivo, como por ejemplo el nombre de la imagen del contenedor.
Se puede instalar y ejecutar fácilmente de forma local contra la imagen de Docker creada o la raíz del proyecto. También admite múltiples salidas, incluidas JSON y salida de tabla:
Lamentablemente, hay proyectos que Trivy no puede escanear (por ejemplo, Golang), por lo que tuvimos que confiar en OWASP Dependency-Check ya que gran parte de nuestro código está en golang.
Dependency-Check es una herramienta de análisis de composición de software (SCA) que intenta detectar vulnerabilidades divulgadas públicamente contenidas dentro de las dependencias de un proyecto. Esto se logra determinando si existe un identificador de enumeración de plataforma común (CPE) para una dependencia determinada. Si se encuentra, se generará un informe vinculado a las entradas CVE asociadas.
Puede generar páginas html con informes, salida JUnit y JSON (y algunos otros).
Ahora nos vamos acercando a cosas más interesantes 😊
Como ya utilizamos Elasticsearch + Kibana + Fluentd en nuestros equipos de DevOps y SRE, fue natural utilizar la infraestructura existente para analizar la salida JSON de nuestros análisis de seguridad.
Solo necesitábamos encontrar una forma de enviar datos desde una infraestructura no confiable (ejecutores de CI) a nuestro Elasticsearch seguro. Para este propósito, decidimos tener una cola de mensajes en el medio. Fluentd tiene el complemento in_sqs para leer mensajes de Amazon SQS y también es fácil de usar, por lo que la arquitectura final se ve así:
Una vez que los datos llegan a Elasticsearch, es sencillo crear algunos paneles con Kibana o usar Discover para consultar vulnerabilidades con todos los detalles según sea necesario.
Ahora que tenemos escaneos y un lindo panel, ¿qué sigue? No podemos esperar que los desarrolladores vean estos paneles periódicamente. En lugar de eso, decidimos hacer fallar la CI cuando se encuentra un problema de alta gravedad o superior y tiene una solución disponible, de esa manera la responsabilidad se traslada a los desarrolladores y propietarios del proyecto.
Naturalmente, necesitábamos tener una opción para incluir en la lista blanca algunos CVE o anular este comportamiento predeterminado para cada proyecto. Así, creamos un repositorio con perfiles de escaneo de seguridad que son consumidos por nuestra herramienta de escaneo que envuelve la ejecución de Trivy y maneja su comportamiento y salida.
Ahora cualquier desarrollador puede enviar una solicitud de fusión contra este repositorio y solicitar una excepción. Ejemplo de perfil para el proyecto Kibana :
Esta implementación de escaneo de seguridad es una base sólida que puede extenderse más allá de nuestros casos de uso iniciales. Por ejemplo:
Puede encontrar Dockerfile y herramientas en nuestro repositorio público de Gitlab: https://gitlab.com/volterra.io/security-scanning
Gracias a Jakub Pavlík .