Cómo encontrar el ID de cuenta de AWS de un bucket S3
(tracebit.com)- Tracebit resume una técnica para estimar el AWS Account ID de buckets S3 públicos y privados, y recupera
123456789101en el bucket de ejemplobucket-alpha - La pista clave es la condición
s3:ResourceAccounten 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 usandoaws:useridyRoleSessionNamese reduce a menos de 10 minutos - Esta técnica es posible porque
StringLikepermite coincidencia parcial ens3: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-alphase recopilan los nombres de sesión que pasaron en CloudTrail y finalmente se recupera123456789101
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:ResourceAccountdí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
StringLikey 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
curlal endpoint HTTP del bucket, aunque la solicitud esté prohibida, se devuelve el encabezadox-amz-bucket-region - En el ejemplo, se confirma
us-east-1en los encabezados de respuesta debucket-alpha.s3.amazonaws.com
- Al enviar
- 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:ResourceAccountempieza con cierto número- Por ejemplo, para verificar si el Account ID empieza con
0, se configura la condición"0*"ens3:ResourceAccount
- Por ejemplo, para verificar si el Account ID empieza con
- 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 con0
- Ej.: si se ve un evento con la condición
- 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*"]
- Por ejemplo, se divide el rango incluyendo varios patrones en la condición
- 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
- Incluso usando búsqueda binaria, puede tomar alrededor de
- En un ejemplo ejecutado durante varias horas, se encontró exitosamente
123456789101como Account ID debucket-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:ResourceAccounty una condiciónaws:userid
- La condición
aws:useridse usa para hacer match con el valorRoleSessionName, que se puede especificar libremente en una llamada STSAssumeRole- Al asumir un rol con un
RoleSessionNameespecífico, se puede hacer pasar selectivamente el statement de política correspondiente a una prueba concreta de posición y dígito
- Al asumir un rol con un
- 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
- Ej.:
- 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
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.
StringLikesobre 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
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.
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.
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.
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.
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
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
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
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
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
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
Si no es secreta, ni sensible, ni confidencial, ¿por qué hay que compartirla con cuidado?
Los usuarios pueden verlo de otra manera