jueves, abril 04, 2019

Kubernetes: Cómo gestionar autorización de recursos con RBAC (Parte 2) #docker #kubernetes

Continuamos con nuestro artículo sobre Kubernetes y RBAC justo donde lo dejamos en la primera parte (jugando con los espacios de nombres), así que echa un vistazo al anterior post para repasar y manos a la obra. Ahora vamos a centrarnos en la creación de roles y su asociación a diferentes usuarios y grupos.

Figura 6: Kubernetes: Cómo gestionar autorización de recursos con RBAC (Parte 2)

En este ejemplo, que vamos a usar de base para explicar sus componentes, podemos ver un fichero de creación de un role para tener control total total al espacio de nombres de cybercaronte (luego veremos como se crea):
    kind: Role
    apiVersion: rbac.authorization.k8s.io/v1
    metadata:
        name: cybercaronte-full-control
        namespace: cybercaronte
    rules:
    - apiGroups: [""]
      resources: ["*"]
      verbs: ["*"]
Como todo objeto en Kubernetes, vemos como en este caso tenemos definidos los atributos kind, apiVersion y metadata. Ojo a este caso, como estamos creando un role, tenemos que especificar el espacio de nombres donde queremos crearlo con el atributo namespace dentro de metadata.

Figura 7: Proceso de arranque de minikube

Lo siguiente es definir las reglas (rules). En este case vemos como tenemos entradas bajo rules:
• apiGroups: aquí especificamos la(s) API(s) que queremos autorizar. Si lo dejamos vacío (""), implica que dicha regla (rule), se aplica a las APIs core de Kubernetes. Alguno de los grupos disponibles, además del core, son: extensions, apps, etc. Si quieres ver todas las APIs disponible en tu clúster, puedes ejecutar el siguiente comando:
kubectl api-versions
• resources: aquí, si queremos aplicar la regla a todos los dispositivos, podemos poner un asterisco, o bien listar los recursos que deseamos. Por ejempo: pods, secrets, configmaps, deployments, services, etc.
• verbs: en Kubernetes el recibe todas las peticiones es el component API Server, que no es ni más ni menos que un servicio Rest. Por lo que toda petición se basa en un recurso y un verbo: GET, POST, PUT, etc. En el caso de Kubernetes, éste define su propia lista de verbos como son: get, list, watch, create, update, patch, delete, bind, etcetera.
Si creamos ese role y se lo asignamos a un usuario, dicho usuario prácticamente tendría control total sobre el espacio de nombres donde dicho role es creado. Un apunte importante es que podemos añadir varias reglas a un role:
    rules:
    - apiGroups: [""]
      resources: ["pods"]
      verbs: ["get", "list", "watch"]
    - apiGroups: ["batch", "extensions"]
      resources: ["jobs"]
      verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
En este caso, tenemos dos reglas, la primera indica que podemos leer, listar y observar pods a través del uso de cualquier API de Kubernetes. La segunda indica que podemos obtener, listar, observar, crear, actualizar, parchear y borrar recursos del tipo (Kind) job definidos bajo las APIs batch y extensions.

Ahora sí, vamos a crear los dos roles, uno para el espacio de nombres cybercaronte:
    kind: Role
    apiVersion: rbac.authorization.k8s.io/v1
    metadata:
      name: cybercaronte-full-control
      namespace: cybercaronte
    rules:
    - apiGroups: [""]
      resources: ["*"]
      verbs: ["*"]
Y otro para el espacio de nombres tuxotron:
    kind: Role
    apiVersion: rbac.authorization.k8s.io/v1
    metadata:
      name: tuxotron-full-control
      namespace: tuxotron
    rules:
    - apiGroups: [""]
      resources: ["*"]
      verbs: ["*"]
Creamos dos ficheros (cybercaronte-fullcontrol-role.yaml y tuxotron-fullcontrol-role.yaml) con dicho contenido y ejecuta:
  kubectl apply -f cybercaronte-fullcontrol-role.yaml
  kubectl apply -f tuxotron-fullcontrol-role.yaml
Para comprobar que los roles se han creado:
  kubectl get role -n cybercaronte
  kubectl get role -n tuxotron
Ahora que tenemos los usuarios y los roles creados, tenemos que asignarles los roles a los usuarios. Para ello necesitamos crear los objectos RoleBinding.
Primero vamos a asignar al usuario cybercaronte el role cybercaronte-full-control. Para ello creamos un fichero (cybercaronte-fullcontrol-binding.yaml) con el siguiente contenido
    kind: RoleBinding
    apiVersion: rbac.authorization.k8s.io/v1
    metadata:
      name: full-control
      namespace: cybercaronte
    subjects:
    - kind: User
      name: cybercaronte
      apiGroup: rbac.authorization.k8s.io
    roleRef:
      kind: Role
      name: cybercaronte-full-control
      apiGroup: rbac.authorization.k8s.io
Crea el RoleBinding:
    kubectl apply -f cybercaronte-fullcontrol-binding.yaml
Para probar si funciona, cambiemos de contexto a cybercaronte y a ver si ahora podemos consultar los pods del espacio de nombres cybercaronte:
kubectl config use-context cybercaronte kubectl get pods -n cybercaronte No resources found.
Como podemos ver esta vez no recibimos ningún error. Si intentamos consultar los pods del espacio de nombres tuxotron:
  kubectl get pods -n tuxotron
  Error from server (Forbidden): pods is forbidden: User "cybercaronte" cannot list resource "pods" in API group "" in the namespace "tuxotron"
Vemos como recibimos un error porque el usuario cybercaronte no tiene acceso a los pods del espacio de nombres tuxotron.

Figura 8: Rafael Troncoso (tuxotron), Chema Alonso (sujetando el libro Docker:SecDevOps), Elías Grande
y Fran Ramírez (cybercaronte) en la RootedCon 2019. Al fondo, el poster del "Profesor Alonso" de Cels Piñol.
Hagamos lo mismo con el usuario tuxotron. Crea un fichero (tuxotron-fullcontrol-binding.yaml) con el siguiente contenido:
    kind: RoleBinding
    apiVersion: rbac.authorization.k8s.io/v1
    metadata:
      name: full-control
      namespace: tuxotron
    subjects:
      - kind: User
        name: tuxotron
        apiGroup: rbac.authorization.k8s.io
    roleRef:
      - kind: Role
        name: tuxotron-full-control
        apiGroup: rbac.authorization.k8s.io
Antes de poder crear este RoleBinding tenemos que cambiar de contexto a minikube primero:
    kubectl config use-context minikube
  kubectl apply -f tuxotron-fullcontrol-binding.yaml
Vamos a explicar un poco la estructura de este objeto. Lo primero a recalcar es el nombre (metadata.name), si te fijas bien en los dos RoleBindings que hemos creado usan exactamente el mismo nombre. Esto es posible, porque los RoleBindings pertenecen a un nombre de espacio, y en nuestro ejemplo hemos creado cada RoleBidning en distintos espacios de nombre. Si hubiéramos usado el CLusterRoleBinding, esto no sería posible porque en ese caso habría un conflicto de nombres.

El apartado subjects es donde decimos a quién la vamos a asignar el role. El atributo Kind debe ser User, Group o ServiceAccount. Luego tenemos name, éste corresponde al nombre de usuario, grupo o cuenta de servicio y por último el apiGroup que es rbac.authorization.k8s.io

Luego tenemos el apartado roleRef. Aquí es dónde especificamos el role que queremos asignar. El atributo Kind define el tipo de role: Role o ClusterRole. Name es el nombre del role en sí y finalmente el apiGroup que al igual que el caso anterior es rbac.authorization.k8s.io

Por último, veamos un ejemplo donde daremos acceso al espacio de nombres equipo al grupo developers. Vamos a crear un role a nivel de clúster para dar acceso total sobre pods, deployments, servicios, replicasets y secretos:
    kind: ClusterRole
    apiVersion: rbac.authorization.k8s.io/v1
    metadata:
      name: full-control
    rules:
      - apiGroups: ["extensions", "apps", ""]
        resources: ["pods", "deployments", "secrets", "services", "replicasets"]
        verbs: ["*"]
Copiamos el contenido a un fichero (developers-role.yaml) y ejecuta el siguiente comando:
    kubectl apply -f developers-role.yaml
Un par de apuntes sobre este fichero. Lo primero es que el tipo (Kind) es ClusterRole y como vemos no tiene especificado el espacio de nombres (namespace). Este es un objeto global del clúster. Ahora creemos otro fichero (developers-binding.yaml) con el siguiente contenido:
    kind: RoleBinding
    apiVersion: rbac.authorization.k8s.io/v1
    metadata:
      name: full-control
      namespace: equipo
    subjects:
      - kind: Group
      name: developers
      apiGroup: rbac.authorization.k8s.io
    roleRef:
      kind: ClusterRole
      name: full-control
      apiGroup: rbac.authorization.k8s.io
Como vemos, el contenido de este fichero es similar a los anteriores, con par de diferencias. En el apartado subjects, usamos el tipo Group, porque estamos asignando el role a un grupo y no a un usuario. Y en el apartado roleRef, el tipo es ClusterRole y no Role, ya que el role al que estamos haciendo referencia es del tipo ClusterRole. Para crear dicho RoleBinding:
    kubectl apply -f developers-binding.yaml
Recuerda que cuando creamos los usuarios, ambos los creamos bajo la organización developers `/O=developers`. Por lo tanto, cybercaronte y tuxotron deberían tener acceso a los pods, servicios, secretos, replicasets y deployments del espacio de nombres. Comprobemos que cybercaronte tiene acceso:
kubectl config use-context cybercaronte
Switched to context "cybercaronte". kubectl get pod -n equipo No resources found. kubectl get deployment -n equipo No resources found. kubectl get configmap -n equipo Error from server (Forbidden): configmaps is forbidden: User "cybercaronte" cannot list resource "configmaps" in API group "" in the namespace "equipo"
Como hemos podido comprobar, cuando consultamos los pods y los deployments no recibimos ningún error. “No resources found” es porque no hemos creado nada en el espacio de nombres. Cuando consultamos los configmaps vemos que recibimos un error, ya que ese recurso no tenemos acceso. Si hacemos las mismas pruebas con el usuario tuxotron, los resultados deberían ser el mismo.


Figura 9: Kubernetes: Cómo gestionar autorización de recursos con RBAC [Parte 2]

Kubernetes no sólo permite el control de acceso a un recurso complete, sino que incluso a parte del mismo. Por ejemplo, podrías dar acceso a los logs de los pods, sin dar acceso a los pods en sí. Tienes en el vídeo todo el proceso que hemos realizado en esta parte del artículo.

Esperamos que te hayas animado a llegar al final de este artículo y por lo menos tengas suficiente información para entender como funciona el RBAC en Kubernetes. Os dejamos por aquí también algunas de las referencias que tenemos sobre Docker escritas ya en este blog, para que tengáis toda la información disponible y accesible.

[BlogPost] Docker: SecDevOps: Contenido y descripción del libro
[BlogPost] SecDevOps: Una explicación en 5 minutos (o poco más)
[BlogPost] Cómo montar un entorno de pentesting desde cero en Docker
[BlogPost] SuperLatch Docker: Integrar Latch con Docker y Kubernetes en tus apps
[BlogPost] Docker Distroless Images: Cómo crear imágenes Docker sin SO ni shell
[BlogPost] Dagda Docker Security Suite: Auditoría de seguridad en aplicaciones dockerizadas
[BlogPost] Docker de My WordPress in Paranoid Mode
[BlogPost] Docker de My WordPress in Paranoid Mode (WPM): "The Making of"
[BlogPost] Hacking Kubernetes: Auditoría de seguridad y explotación de vulnerabilidades
[BlogPost] Kubernetes: Cómo gestionar autorización de recursos con RBAC

Fran Ramírez, (@cyberhadesblog) es investigador de seguridad y miembro del equipo de Ideas Locas en CDO en Telefónica, co-autor del libro "Microhistorias: Anécdotas y Curiosidades de la historia de la informática (y los hackers)", del libro "Docker: SecDevOps" y del blog Cyberhades.

Rafael Troncoso (@tuxotron) es Senior Software Engineer en SAP Concur, co-autor del libro "Microhistorias: Anécdotas y Curiosidades de la historia de la informática (y los hackers)", del libro "Docker: SecDevOps" y del blog Cyberhades.

miércoles, abril 03, 2019

2FWB: Second Factor Web Browsing [Parte 3 de 4] "2FWB Mobile App"

Vista la arquitectura general del sistema de Second Factor Web Browsing en el apartado anterior, vamos a ver cómo funciona el sistema con varios ejemplos. Para ello, vamos a explicar primero cuál es el formato de información que intercambian el Agente 2FWB en el sistema operativo desde el que se navega y la App 2FWB instalada en el terminal móvil que habilitará el Second Channel. Esta información se intercambia utilizando el protocolo BlueTooth tal y como ya se ha explicado.

Figura 20: 2FWB. Second Factor Web Browsing
[Parte 3 de 4] "2FWB Mobile App"

Para que se entienda, vamos a suponer que desde el navegador del equipo de una de mis hijas se comienza a navegar a un determinado dominio de Internet. La Extensión 2FWB para Google Chrome extrae cierta información relativa a la respuesta que se recibe desde el servidor y se la entrega al Agente 2FWB que se encuentra corriendo en el sistema operativo. Éste, añade información relativa al propio entorno de red que no puede ser extraída con una extensión del navegador, y por Bluetooth envía un fichero con todos los datos a la App 2FWB que se encuentra en el terminal móvil pareado.

Figura 21: Alerta de seguridad para que llame a papá

Después de realizar todas las comprobaciones, en nuestro caso mediante un servicio en cloud que hace todas las verificaciones, la App 2FWB enviará una respuesta al Agente 2FWB que llegará hasta la Extensión 2FWB instalada en el navegador, dejando que prosiga la sesión de navegación, o bloqueando la pestaña con una aviso que diga: "¡Avisa a Papá". Recordad que se trata de un servicio que intenta ayudar a sentirse más seguros a los más jóvenes, y es como si su "papaete" estuviera navegando junto a ellos.

Peticiones y respuestas

El formato de intercambio es bastante sencillo. Desde el Agente 2FWB se envía a la App 2FWB este fichero con los datos más relevantes. El nombre del dominio, un id de la petición y la pestaña en la que está visualizando dicho contenido. Después se  introducen los datos del certificado digital recibidos en la petición HTTPs que se utilizarán para verificar con el original del sitio.

Figura 22: Formato de envío de datos que va desde el Agente 2FWB a la App 2FWB

Además, se entregan las cabeceras HTTP que han venido en la respuesta entregada por el servidor web ante la petición del navegador, junto con la lista de scripts. Además incorpora información tomada del sistema por el propio Agente 2FWB como el TimeStamp o las respuestas DNS obtenidas.

En la lógica del Servicio 2FWB, que en nuestra arquitectura está en una plataforma Cloud pero que también podría recaer directamente en la App 2FWB, evalúa los diferentes controles para verificar los diferentes posibles ataques.

Evalúa la hora del sistema, el valor SHA256 del certificado que se recibe por el Agente 2FWB en la máquina con la que se debería obtener (revisando los posibles certificados digitales y las políticas HSTS para ver si existe algún Certificate Pinning marcado por el servicio).

Evalúa la dirección IPv4/IPv6 a la que se ha conectado, la lista de cabeceras HTTP recibidas, la lista de scripts, y hace una verificación extra del nombre de dominio contra servicios de inteligencia varios  - como NotMining -para saber la calidad de ese dominio.

Figura 23: Respuesta a recibida a la petición de 2FWB con id:123

Y con todas las comprobaciones hechas, al Agente 2FWB le llega la respuesta vía App 2FWB con un formato similar a este. Donde si alguna de las validaciones anteriores falla (campo con valor a "False" ), se considerará que la conexión es peligrosa y el campo "Operation" devuelto en la respuesta, tomará el valor "Deny" . En caso contrario, el valor será "Allow" .

Probando ataques con Bettercap

Para probar el funcionamiento completo del sistema hemos preparado varios ataques utilizando caplets de Bettercap para tener la visión de cuál es la experiencia. En estos cinco vídeos vamos a poder ver cómo se detectan los ataques  que hemos incluido en esta prueba de concepto. Desde una máquina con Kali Linux vamos a lanzar todos los ataques, y veremos la experiencia en la App 2FWB y en la navegación del navegador de Internet protegido por 2FWB.


Figura 24: Detección de ataque de ARP Spoofing con 2FWB


Figura 25: Detección de ataque de DNS Spoofing


Figura 26: Detección de ataque de Certificado Falso


Figura 27: Detección de ataque a HSTS


Figura 28: Detección de ataque de Cryptojacking

Control Parental con 2FWB

Una vez que tenemos la App 2FWB en el terminal del papá, donde se pueden ver las alertas que se generan en tiempo real con los posibles ataques, parecía bastante fácil implementar un sistema de Control Parental en tiempo real, para que el adulto que se encarga de vigilar la seguridad de la navegación de los menores pudiera bloquear o permitir determinados dominios.


Figura 28: Control Parental con 2FWB

En este caso, como se puede ver, hemos puesto la alerta de otro color - azul - para que no se asuste nadie cuando aparezca y se tenga claro que ha sido el adulto el que ha puesto este control momentáneamente, tal y como se puede ver en el vídeo de la Figura 28.

Como se puede ver, la posibilidad de tener un 2FWB permite tomar muchas decisiones en función de lo que se está recibiendo por el navegador de Internet conectado a la red WiFi o Ethernet, y de lo que se recibe por el Second Channel que utilizar el servicio de 2FWB. Pero aún podíamos darle una vuelta de tuerca más, que os contaré en la última parte de esta serie.

Saludos Malignos!

*****************************************************************************************
- 2FWB: Second Factor Web Browsing [Parte 1 de 4] "Second Channels"
- 2FWB: Second Factor Web Browsing [Parte 2 de 4] "Network Attacks"
- 2FWB: Second Factor Web Browsing [Parte 3 de 4] "2FWB Mobile App"
- 2FWB: Second Factor Web Browsing [Parte 4 de 4] "Modo Centinela"
*****************************************************************************************

Entrada destacada

Hacking IA: Jailbreak, Prompt Injection, Hallucinations & Unalignment. Nuestro nuevo libro en 0xWord

Pocas veces me ha hecho tanta ilusión que saliera un nuevo libro en 0xWord como con este libro de " Hacking IA: Jailbreak, Prompt Inje...

Entradas populares