2 puntos por GN⁺ 2024-02-27 | 1 comentarios | Compartir por WhatsApp
  • Tracebit resume una técnica para estimar el AWS Account ID de buckets S3 públicos y privados, y recupera 123456789101 en el bucket de ejemplo bucket-alpha
  • La pista clave es la condición s3:ResourceAccount en la política de un Interface VPC Endpoint para S3, y si la solicitud queda registrada en los logs propios de CloudTrail
  • En buckets privados, aunque la respuesta final siga siendo AccessDenied, solo las solicitudes que pasan la política del VPC Endpoint aparecen en CloudTrail, por lo que se puede determinar si coinciden con un patrón numérico
  • Debido a la propagación de políticas y al retraso de CloudTrail, una exploración simple puede tardar hasta aproximadamente 40 * 12 minutos = 8 horas, pero con pruebas paralelas de 120 statements de política usando aws:userid y RoleSessionName se reduce a menos de 10 minutos
  • Esta técnica es posible porque StringLike permite coincidencia parcial en s3:ResourceAccount, y parte de la actividad también puede quedar en el CloudTrail del propietario del bucket

Una extensión a partir de la técnica para buckets públicos

  • En 2021, Ben Bridts publicó cómo encontrar el AWS Account ID de un bucket S3 público
  • El método de Tracebit reutiliza varios elementos de esa idea, pero se enfoca en encontrar el Account ID de buckets S3 incluyendo también buckets privados
  • En la ejecución de ejemplo, para bucket-alpha se recopilan los nombres de sesión que pasaron en CloudTrail y finalmente se recupera 123456789101

Por qué funciona el método existente para buckets públicos

  • El método de Ben Bridts funciona porque se combinan tres condiciones
    • Se puede aplicar una política IAM a la solicitud
    • Se puede inferir si la política permitió o bloqueó la solicitud
    • Se puede aplicar coincidencia con comodines a la clave de condición s3:ResourceAccount
  • En un bucket público, si la política bloquea la solicitud se obtiene AccessDenied, y si la política la permite la solicitud tiene éxito, por lo que es fácil distinguir si pasó la política
  • Al acotar s3:ResourceAccount dígito por dígito, el espacio total de búsqueda se reduce de billones a unos cientos

En buckets privados, se mira CloudTrail en lugar de la respuesta

  • En un bucket privado, sin importar qué política se aplique, la respuesta final será AccessDenied debido a la política del bucket de destino
  • El método de Tracebit no se basa en el resultado de la respuesta, sino en si la solicitud aparece en los logs de CloudTrail propios
    • Si la solicitud aparece en CloudTrail, la política del VPC Endpoint la permitió y luego fue rechazada por la política del bucket
    • Si la solicitud no está en CloudTrail, fue bloqueada por la política del VPC Endpoint
  • Al crear un Interface VPC Endpoint para S3, se puede aplicar una política de VPC Endpoint a las solicitudes, y esa política se evalúa junto con otras políticas, como la política del bucket y la política IAM del principal solicitante
  • En una política de VPC Endpoint también se pueden usar comodines StringLike y claves de condición de recurso, por lo que es posible usar el mismo enfoque de exploración

Procedimiento básico: desde verificar la región hasta consultar eventos

  • Primero hay que encontrar la región del bucket objetivo
    • Al enviar curl al endpoint HTTP del bucket, aunque la solicitud esté prohibida, se devuelve el encabezado x-amz-bucket-region
    • En el ejemplo, se confirma us-east-1 en los encabezados de respuesta de bucket-alpha.s3.amazonaws.com
  • Se despliega una VPC y un VPC Endpoint para S3 en la misma región que el bucket objetivo
    • El VPC Endpoint debe ser de tipo Interface, que permite aplicar políticas
    • Como ese VPC Endpoint afecta las solicitudes S3 de la VPC, conviene crear una VPC dedicada para este propósito
  • Se ejecuta una instancia EC2 dentro de la VPC para enviar solicitudes S3, y se confirma que esa instancia use el VPC Endpoint para S3
  • Se modifica la política del VPC Endpoint para probar si s3:ResourceAccount empieza con cierto número
    • Por ejemplo, para verificar si el Account ID empieza con 0, se configura la condición "0*" en s3:ResourceAccount
  • Desde la instancia EC2 se envía una solicitud de management al bucket objetivo, como GetBucketAcl
    • Usar solicitudes de management reduce la necesidad de configuraciones adicionales en CloudTrail
    • Como se espera, el resultado de la solicitud es AccessDenied

Cómo determinar patrones numéricos con CloudTrail

  • Después de la solicitud, se consulta en CloudTrail si aparece el evento GetBucketAcl
  • Si aparece el evento, significa que la política del VPC Endpoint permitió la solicitud, por lo que el Account ID coincide con el patrón probado
    • Ej.: si se ve un evento con la condición "0*", el Account ID empieza con 0
  • Si no aparece el evento, significa que la política del VPC Endpoint bloqueó la solicitud, por lo que no coincide con ese patrón
  • Como puede tomar varios minutos que el evento aparezca en CloudTrail, se recomienda esperar 10 minutos antes de concluir que no hay evento
  • Los cambios en la política del VPC Endpoint también tardan en propagarse y aplicarse por completo; esperar 5 minutos después de modificar la política funciona bien

Aunque se automatizó, el método básico es lento

  • Tracebit escribió un script para automatizar este proceso y poder encontrar de forma confiable el Account ID de un bucket
  • En lugar de verificar simplemente todos los números dígito por dígito, reduce la cantidad de pruebas con un método cercano a una búsqueda binaria en cada posición
    • Por ejemplo, se divide el rango incluyendo varios patrones en la condición s3:ResourceAccount, como ["0*", "1*", "2*", "3*", "4*"]
  • Aun así, los tiempos de espera por aplicación de políticas y verificación en CloudTrail siguen siendo el cuello de botella
    • Incluso usando búsqueda binaria, puede tomar alrededor de 40 * 12 minutos = 8 horas
  • En un ejemplo ejecutado durante varias horas, se encontró exitosamente 123456789101 como Account ID de bucket-alpha

Reducción a menos de 10 minutos con 120 statements de política

  • El método más rápido consiste en incluir de antemano en la política del VPC Endpoint todas las combinaciones posibles de posición y dígito
  • La política contiene un total de 120 statements
    • Se prueban los 10 dígitos posibles para cada posición del AWS Account ID
    • Cada statement usa en conjunto un patrón de posición específico de s3:ResourceAccount y una condición aws:userid
  • La condición aws:userid se usa para hacer match con el valor RoleSessionName, que se puede especificar libremente en una llamada STS AssumeRole
    • Al asumir un rol con un RoleSessionName específico, se puede hacer pasar selectivamente el statement de política correspondiente a una prueba concreta de posición y dígito
  • Esta política apenas entra dentro del límite máximo de caracteres de una política de VPC Endpoint
  • Como se prueban en paralelo las 120 posibilidades, se reduce la necesidad de modificar la política cada vez o esperar individualmente los resultados de CloudTrail
  • Con este método, el tiempo de exploración del Account ID se reduce a menos de 10 minutos

Alcance de la exposición y posibles aplicaciones

  • Parte de la actividad puede verse en los logs de CloudTrail del propietario del bucket objetivo
  • Tracebit consultó al equipo de AWS Security antes de publicarlo
  • Ya ha habido mucho debate sobre si un AWS Account ID es información sensible, y en el evento de CloudTrail de ejemplo el Account ID de un tercero aparece oculto como HIDDEN_DUE_TO_SECURITY_REASONS
  • La misma técnica podría aplicarse a otras claves de condición de recurso relacionadas con buckets
    • Ej.: aws:ResourceOrgID
    • Ej.: aws:ResourceOrgPaths
    • Ej.: aws:ResourceTag
  • También podría aplicarse a otros servicios distintos de S3 donde esta técnica sea viable
  • Si se crean VPC y VPC Endpoints interconectados por peering en todas las regiones, podría ser posible construir una configuración que funcione sin importar la región del bucket objetivo
  • Esta técnica es posible porque se puede usar coincidencia parcial con StringLike para la condición s3:ResourceAccount
  • Podría ser útil que los eventos rechazados por políticas de VPC Endpoint también se registraran en CloudTrail

1 comentarios

 
GN⁺ 2024-02-27
Opiniones en Hacker News
  • Es realmente extraño que se pueda aplicar coincidencia con comodines a la clave de condición s3:ResourceAccount.
    No parece haber una razón válida para permitir o denegar permisos según una coincidencia parcial del ID de cuenta.

    • Parece que es porque la ejecución de políticas de AWS tiene varios operadores y operandos, y en este caso la estructura usa StringLike sobre la cadena del ID de cuenta.
      Es interesante ver cómo en el área de DevOps ahora se están descubriendo ataques de canal lateral. Los canales laterales de ejecución especulativa en CPU, como Meltdown y Spectre, también causaron gran impacto cuando se descubrieron; antes de eso ya existían campos como el análisis de consumo, la detección de distorsión magnética y la criptografía de tiempo constante.
      https://en.m.wikipedia.org/wiki/Side-channel_attack
      https://en.m.wikipedia.org/wiki/Power_analysis
    • A mí también me sorprendió esa parte. Este campo parecería no deber permitir nada salvo coincidencia exacta, y no se me ocurre un caso de uso para aplicar pattern matching a un ID de cuenta.
    • Probablemente venga de una tendencia a generalizar.
      En un proyecto paralelo reciente hice una función para escribir consultas en un formato inspirado en OWL, y hay una biblioteca de operadores relacionales para cosas como extraer el host de una URL, consultas por prefijo, consultas like, consultas con expresiones regulares, etc.
      Como era un proyecto paralelo de otro proyecto paralelo mío, lo hice de la forma fácil y dejé que los operadores estuvieran siempre disponibles, incluso cuando no tenía sentido. No sé ni me importa qué pasa si haces una consulta con regex sobre un número. Puede que dentro de AWS exista algo parecido, pero si es un sistema con muchos usuarios y sensible desde el punto de vista de seguridad, el estándar debería ser distinto.
    • Es parecido a hacer match contra un bitfield de IDs de grupo en sistemas Unix.
      Alguien podría tener esta idea y pensar que es inteligente, pero implementarla en un sistema que no controlas al 100% parece una tontería.
  • Normalmente no andarías publicando tu ID de cuenta, pero hay que asumir que alguna parte se filtrará tarde o temprano.
    Cada vez más proveedores de terceros y plataformas SaaS se están moviendo hacia integraciones que prefieren la delegación de roles en lugar de usuarios IAM y access keys, y así debe ser. Eso significa que, como mínimo, el ID de la cuenta usada como punto de integración queda en conocimiento de otra parte, que a su vez tiene dependencias, vulnerabilidades, etc.

    • Esto me da curiosidad. ¿Qué puede hacer un atacante con un ID de cuenta de AWS? ¿En qué se diferencia de saber la dirección de correo de alguien?
  • Un ID de cuenta de AWS es parecido a una dirección IP. Puede ser sensible, pero para trabajar alguien tiene que conocerlo.
    Por ejemplo, hace uno o dos años tuvimos que integrarnos con un tercero por procedimientos antilavado de dinero. Como normalmente es más seguro que un puerto SFTP público, propusimos configurar PrivateLink con esa organización, pero la otra empresa se negó por motivos de seguridad: tenían que ocultar su ID de cuenta. Y eso a pesar de que era necesario en el ARN del rol del endpoint PV para permisos mutuos.
    Al final agregamos a la lista de permitidos el rango de IP públicas que ellos usan para el puerto inbound 22.
    La lección es que puedes ofuscar IDs y sentirte inteligente, pero es difícil operar un negocio si la contraparte no sabe la dirección a la que debe volver.

    • AWS PrivateLink tiene otra característica que en general lo vuelve poco deseable para este tipo de integraciones: la comunicación es bidireccional y las subredes IP no deben solaparse.
      Nosotros, como proveedor, normalmente integramos mediante VPC Endpoint Service. En este enfoque la comunicación es unidireccional y nuestro servicio se expone como un endpoint de load balancer dentro de la VPC del cliente.
  • Para quienes tengan interés, dejé el código aquí: https://github.com/tracebit-com/find-s3-account

  • Es un hallazgo interesante, sin duda, pero por el título pensé que habría un método más directo.
    Me gustaría que en AWS, desde una cuenta administradora, pudiera preguntarse fácilmente dentro de la organización “dónde está el recurso X” y saber rápido en qué cuenta está un bucket S3 específico. Lo mismo aplica a otros recursos, pero en S3 el problema es especialmente grande.
    Sinceramente, esto suele pasar sobre todo con buckets legacy anteriores a mejores prácticas, o con cosas que existían antes de definir todos los buckets como código. Aun así, cuando tienes muchas cuentas de AWS, encontrar recursos en cuentas y regiones desconocidas puede volverse tedioso.

    • Si configuras un agregador de AWS Config para la organización, puedes consultar con Athena SQL el inventario de recursos de todas las cuentas de la organización.
      Entonces encontrar qué cuenta posee un recurso es posible más o menos con select accountId where arn = "x".
  • Otros recursos de AWS públicos con namespace global también revelan el ID de cuenta de AWS.
    https://blog.plerion.com/conditional-love-for-aws-metadata-e...

  • Algo relacionado: Cloudflare account_id y zone_id son seguros de exponer públicamente
    https://github.com/cloudflare/cloudflare-docs/issues/474
    https://community.cloudflare.com/t/api-zone-id/355566

    The Zone ID and Account ID are not sensitive. Sensitive data like account API Key, Secrets etc. can all be revoked, rotated or changed. See the comment 36 below on the Wrangler repo: as per our security team, it’s completely Fine to have your zone_id and account_id public, the Global API key and associated email address should be kept secret.

    • El ID de cuenta de AWS también es seguro de exponer públicamente
      Sin embargo, una de las cosas que se puede hacer con eso es detectar correlaciones. Si operas varios sitios S3 desde la misma cuenta de AWS, la gente puede ver que están alojados en la misma cuenta. Que eso importe o no depende de tu modelo de amenazas
    • Para la cuenta de CF, uso la función + de Gmail para crear una dirección de correo totalmente única que no sea fácil de adivinar
      No es perfecto, pero agrega una capa más de abstracción
  • Relacionado con esto, aunque el ID de clave de AWS no sea la parte de la clave secreta, contiene dentro el ID de cuenta desplazado un bit
    https://medium.com/@TalBeerySec/a-short-note-on-aws-key-id-f...
    Ese ID de clave se incluye en las URL prefirmadas de S3, así que es muy probable que ya estuvieras exponiendo el ID de cuenta

    • En este hilo parece que bastante gente asume que el ID de clave de AWS forma parte de la seguridad por oscuridad o de la defensa en profundidad
      Probablemente me van a dar votos negativos, pero si aun así lo leen, esto es un ejemplo de por qué la seguridad por oscuridad no es una buena defensa. Uno va a pasar algo por alto, y un atacante persistente no lo hará
      La seguridad que no depende de la oscuridad aplica independientemente de si yo entendí algo o no, salvo que el atacante contrate, por ejemplo, a un genio capaz de romper AES-256 así nomás: https://www.youtube.com/watch?v=KEkrWRHCDQU
  • ¿Por qué podría importar esto? Como ejemplo claro, dado un bucket de producción, ahora se vuelve posible encontrar buckets de desarrollo de la misma organización. Personalmente, no es el comportamiento que esperaba

    • Eso solo aplica si usas la misma cuenta para producción y desarrollo. Es otra razón para no usar la misma cuenta
    • Para hacer eso basta con tener el nombre del bucket
      Para impedir estos intentos de enumeración, habría que poner en el nombre del bucket un prefijo o sufijo generado aleatoriamente. Además, como medida adicional y no como reemplazo, también es buena práctica exponer los objetos del bucket con un nombre que no sea el hostname predeterminado, para que no se filtre el propio nombre del bucket
    • ¿Cómo se llega a eso? ¿No tendrías que saber primero el nombre del bucket de desarrollo?
    • Es poco probable, a menos que el bucket de desarrollo de alguna forma esté en la misma cuenta
  • While account IDs, like any identifying information, should be used and shared carefully, they are not considered secret, sensitive, or confidential information.
    https://docs.aws.amazon.com/accounts/latest/reference/manage...

    • Al menos en el mundo digital, la información parece ser una de dos: pública o privada. No hay muy buen concepto de información que requiera autorización o que esté protegida
      Por ejemplo, la dirección de mi casa es técnicamente información pública, pero jamás querría verla en un espectacular junto a la autopista, junto con fotos de mi familia, diciendo dónde vivo. La doy solo a quienes la necesitan, y en general confío y espero que se mantenga casi confidencial o con uso limitado
    • ¿Qué significa esto?
      Si no es secreta, ni sensible, ni confidencial, ¿por qué hay que compartirla con cuidado?
    • Creo que “no se considera información secreta, sensible ni confidencial” debería decir “según nuestros criterios
      Los usuarios pueden verlo de otra manera