01 ago 2025·6 min de lectura

Auditoría de exposición de buckets de almacenamiento: evita archivos públicos y el listado

Lista de verificación para auditoría de exposición de buckets: detecta ACL públicas, valores predeterminados riesgosos y reglas de subida inseguras para mantener privados los archivos de usuarios.

Auditoría de exposición de buckets de almacenamiento: evita archivos públicos y el listado

Cómo se ve la exposición de un bucket de almacenamiento en la vida real

Un bucket de almacenamiento es una gran carpeta en la nube donde una app guarda archivos: fotos de perfil, facturas, notas de audio, informes exportados y todo lo que suben los usuarios. Los equipos usan buckets porque son baratos, rápidos y fáciles de conectar a una app.

La exposición normalmente no ocurre porque alguien “hackee” el bucket. Ocurre porque una configuración se deja abierta durante un prototipo, una demo o un lanzamiento apresurado. Un checkbox puede hacer que todo el bucket sea público. O alguien asume “privado por defecto” cuando el valor predeterminado es permisivo.

La exposición suele manifestarse de dos formas:

  • Público: cualquiera puede obtener un archivo, y a veces listar todo el bucket como si fuera un directorio.
  • No listado pero adivinable: los archivos no están indexados, pero el patrón de URL es predecible, así que la gente puede adivinar nombres como uploads/user_123/id.jpg o probar nombres comunes.

La segunda es más sigilosa. Un fundador puede probar una subida “privada”, ver que no aparece en la app y asumir que está segura. Pero si el enlace puede adivinarse (o compartirse casualmente), sigue siendo efectivamente público.

El prototipado es donde esto suele empezar. Herramientas que generan apps rápidamente pueden usar reglas simples como “permitir lectura para todos” para que nada falle en una demo. Luego el prototipo crece y llega a producción, y el bucket conserva las configuraciones de la demo.

Una auditoría de exposición de buckets busca estos puntos de fallo del mundo real antes de que se conviertan en una brecha: banderas de acceso público, defaults permisivos y reglas de subida que facilitan que archivos privados sean fáciles de obtener o listar.

Haz un inventario de buckets y lo que contienen

Empieza por el paso poco glamuroso: anota cada bucket y para qué se usa. Muchas filtraciones ocurren en los buckets “extra” que nadie recuerda, como exportaciones, backups o proyectos antiguos de staging.

Relaciona los buckets con funciones reales de la app. Si tu app permite subir avatares, adjuntar facturas, enviar imágenes en chat o exportar informes CSV, cada una de esas funciones está escribiendo archivos en algún lugar. No te fíes de suposiciones: revisa tu código y la consola del proveedor para capturar el panorama completo.

En lugar de organizar por nombre de equipo, organiza por tipo de archivo:

  • Subidas de usuarios (fotos, documentos, audio)
  • Archivos generados (PDFs, miniaturas)
  • Exportaciones e informes
  • Backups y snapshots
  • Artefactos internos (logs, outputs de build)

Para cada categoría, registra tres cosas: dónde viven los archivos (bucket más ruta/prefijo), cómo llegan ahí (qué servicio o endpoint los escribe) y cuánto deberían conservarse.

Luego decide quién debería poder leer cada tipo de archivo. “Cualquiera en internet” debe ser raro. Muchos equipos etiquetan algo como “público” cuando solo necesita ser legible por usuarios autenticados, o por un cliente y tu equipo de soporte.

Una comprobación rápida para cada bucket o prefijo:

  • ¿Este contenido está realmente destinado a ser público para siempre?
  • Si es privado, ¿quién exactamente puede leerlo?
  • ¿Qué pasa si alguien adivina un nombre de archivo?
  • ¿Deben expirar los enlaces?

Lista rápida: 5 comprobaciones que puedes hacer hoy

Puedes aprender mucho en 15 minutos probando qué podría hacer un extraño sin acceso. Ejecuta estas cinco comprobaciones y registra aprobado/fallado para cada bucket:

  • Abre la URL real de un archivo en una ventana de navegador privada. Si carga sin iniciar sesión, trátalo como público.
  • Comprueba si es posible listar objetos. Si puedes navegar objetos (o recibir una respuesta tipo índice), estás cerca de una fuga completa.
  • Recorre el flujo de subida de principio a fin. Si las subidas funcionan sin autenticación, o el servidor no valida restricciones básicas, asume que es posible el abuso.
  • Observa los patrones de URL. Si las claves incluyen nombres de usuario, timestamps, números de pedido o IDs simples, la gente puede adivinar URLs y cosechar archivos.
  • Busca “desperdicios” sensibles como archivos .env, volcados de bases de datos, backups, logs exportados o carpetas temporales.

Una comprobación realista: si tu app guarda fotos de perfil como /uploads/jane-1700000000.png, incluso un bucket no listable puede filtrarse por adivinanzas.

Revisa configuraciones de acceso público y ACLs

Comienza a nivel de bucket. Un único interruptor “público” puede anular la lógica de la app y hacer que cualquier objeto sea accesible por quien adivine una URL.

Los controles de acceso público suelen existir en más de un lugar: una configuración de bucket (bloquear acceso público), una política de bucket (quién puede leer o listar) y ACLs de objetos (permisos por archivo). Si cualquier capa permite lecturas anónimas, los archivos privados pueden filtrarse.

Qué verificar primero:

  • Confirma que el bucket bloquea el acceso público en la configuración.
  • Confirma que el listado está bloqueado. El listado público suele ser peor que lecturas públicas porque expone todo.
  • Escanea en busca de patrones de ACL como public-read en subidas de usuarios.
  • Registra quién es el propietario del bucket (cuenta/proyecto/rol de servicio) y quién puede cambiar configuraciones.

Las ACLs merecen atención extra porque pueden aplicarse por objeto. Un camino de subida con bugs puede crear silenciosamente archivos públicos aunque la política del bucket parezca correcta.

Si encuentras acceso público, trátalo como urgente. Asegura las lecturas y el listado primero. Luego corrige defaults y reglas de subida para que el problema no vuelva.

Revisa permisos por defecto y políticas heredadas

Muchas filtraciones ocurren porque el bucket no está “público” en apariencia, pero los archivos nuevos heredan permisos que los hacen legibles. La ganancia más rápida es confirmar qué pasa por defecto cuando tu app sube un objeto nuevo.

Comprueba los valores predeterminados a nivel de bucket para nuevas subidas. Algunas configuraciones aplican una ACL por defecto o un permiso enlatado que hace que los objetos sean legibles por cualquiera con la URL.

Después revisa políticas que se aplican por encima del bucket. Una política de bucket puede anular ajustes por archivo, y una regla a nivel de cuenta puede anular el bucket. Reglas amplias como lectura para “todos los usuarios” (o cualquier principal global equivalente) son una fuente común de exposiciones sorpresa.

Comprueba qué hace tu app durante la subida

Muchas apps establecen permisos automáticamente durante la subida, a menudo copiando un tutorial. Busca en tu código términos como public-read, acl, make public o mecanismos que recurran de URLs firmadas a URLs públicas cuando algo falla.

Para validar el comportamiento real, sube un archivo de prueba y verifica:

  • ¿Se puede leer sin iniciar sesión?
  • ¿Aparece en algún endpoint de listado?
  • ¿Afecta cambiar los defaults del bucket a objetos ya existentes?

Atiende la deriva entre dev, staging y producción

Los equipos a veces aseguran producción pero dejan dev o staging muy abiertos, y luego apuntan por error el frontend o la app móvil al bucket equivocado. Un fallo común es un bucket de staging “temporal” con lectura global y una build release que aún usa la configuración de staging.

Audita tus reglas de subida para que los archivos privados sigan privados

Asegura toda la app
FixMyMess fortalece apps generadas por IA contra fugas como secretos expuestos y autenticación débil.

La mayoría de fugas de almacenamiento empiezan en el momento de la subida. Si tu app permite subir un archivo, necesitas reglas claras sobre quién puede subir, dónde se guarda y quién podrá leerlo después.

Requiere autenticación antes de cualquier subida, o usa subidas firmadas que expiren rápido. Una subida firmada debe permitir un solo objeto, en una sola ubicación, por poco tiempo y solo para el usuario autenticado que la solicitó.

La validación importa incluso cuando el almacenamiento es privado. Subidas inseguras aún pueden crear problemas de seguridad y de costes. Mantén las reglas simples:

  • Acepta solo los tipos que realmente necesitas (verifica el contenido, no solo la extensión).
  • Establece un límite de tamaño rígido.
  • Usa rutas por usuario y IDs aleatorios (no nombres de usuario ni marcas de tiempo).
  • Bloquea sobrescrituras salvo que “reemplazar este archivo” sea una función intencional.

Un ejemplo simple: uploads/jane/profile.jpg es fácil de adivinar. uploads/user_123/9f3a2c... es mucho más difícil de adivinar y más fácil de controlar con políticas.

Deja de adivinar, listar y filtrar metadatos

Un bucket puede ser “privado” y aun así filtrar datos si la gente puede adivinar claves, listar objetos o aprender demasiado por metadatos.

Deshabilita el listado donde el proveedor lo permita. El listado convierte una adivinanza afortunada en un directorio completo de archivos de usuarios.

Luego arregla nombres predecibles. Si los archivos se llaman como users/[email protected]/avatar.png o invoices/1042.pdf, externos pueden forzar patrones y confirmar qué usuarios existen. Usa IDs aleatorios e inadivinables para las claves de objetos y evita identificadores de usuario en las rutas.

Los metadatos también pueden filtrar. Los nombres originales muchas veces contienen nombres reales, nombres de proyectos o IDs de clientes. Algunos sistemas también guardan metadatos personalizados como user_id o account_tier, lo que se vuelve un problema si un objeto se hace público por accidente.

Si quieres reducir el riesgo de descubrimiento, céntrate en tres movimientos: bloquear el listado, usar claves inadivinables y minimizar metadatos.

Logs y alertas que realmente detectan exposición

Rescata una app creada por IA
¿Heredaste una app de Lovable, Bolt, v0, Cursor o Replit? La dejamos lista para producción.

Muchas filtraciones de buckets se encuentran tarde, después de que archivos hayan sido descargados durante días. El logging convierte una auditoría puntual en protección continua.

Activa logs para lecturas, escrituras y borrados, no solo errores. Las lecturas importan más, porque un bucket público puede ser raspado sin que nada falle.

Una entrada de log útil responde cuatro preguntas:

  • Quién accedió (usuario, cuenta de servicio o anónimo)
  • Qué pasó (lectura, subida, borrado)
  • Qué objeto fue tocado (ruta/clave completa)
  • Cuándo pasó (timestamp)

Para alertas, céntrate en patrones que normalmente señalan problemas: accesos anónimos y volumen inusual. Una sola lectura anónima puede ser una prueba de configuración. Un estallido de lecturas anónimas suele ser un raspador.

Mantén las alertas pequeñas y accionables. Por ejemplo: lecturas anónimas en un bucket privado, picos repentinos de descargas o muchos “not found” (señal de adivinanza de claves).

También decide la retención según cuánto tiempo podría pasar antes de que se note un incidente. Si solo guardas siete días, puede que no puedas demostrar qué se accedió.

Soluciones que reducen el riesgo y se mantienen simples

La forma más fácil de estar seguro es elegir un modelo y mantenerlo: un bucket es para activos públicos (logos, imágenes de marketing) o para archivos privados de usuarios (facturas, fotos de perfil, exportaciones). Mezclar ambos es donde suele ocurrir el “ups, es público”.

Empieza privado por defecto. Bloquea el acceso público a nivel de bucket y luego abre solo lo que realmente deba ser público. Si algo debe ser público, hazlo obviamente público por diseño (bucket separado, nombres claros), no por accidente.

Para descargas privadas, evita URLs públicas permanentes. Sirve archivos a través de tu app tras el login y las comprobaciones de permiso, o usa URLs firmadas que expiran rápido. Ejemplo: un usuario pide un PDF exportado, tu app verifica la propiedad y luego emite un enlace que funciona durante cinco minutos.

Anota las reglas finales (quién puede subir, quién puede leer, qué es público). La mayoría de incidentes repetidos ocurren cuando alguien “arregla en la consola” pero la app sigue subiendo con el comportamiento antiguo.

Escenario de ejemplo: una app startup con subidas de usuarios expuestas

Una pequeña startup lanza rápido. Los usuarios pueden subir fotos de perfil y la app las guarda en un bucket en la nube. Todo parece bien hasta que un usuario publica una captura donde se ve la foto de otra persona abierta en un navegador.

Así es como pasa: el bucket permite lecturas públicas, o una antigua ACL public-read sigue aplicándose en la subida. La app además usa nombres previsibles como user_123/avatar.jpg. Nadie quiso hacer las fotos públicas, pero los defaults y las decisiones de nombrado lo hicieron silenciosamente.

Una vez que incluso un archivo es legible sin iniciar sesión, adivinar se vuelve fácil. Un atacante puede probar IDs comunes (1, 2, 3...) y solicitar avatar.jpg cada vez. Si el listado está activado, puede que ni siquiera necesite adivinar.

Un plan de arreglo práctico que puedes implementar en un día:

  • Bloquear acceso público y eliminar ACLs públicas en objetos existentes.
  • Usar URLs firmadas de corta duración para descargas privadas.
  • Cambiar nombres a claves inadivinables (IDs aleatorios) y evitar IDs de usuario en las rutas.
  • Aplicar reglas de subida (tipo, tamaño, ruta de destino) y rechazar sobrescrituras no intencionadas.
  • Revisar logs por picos inusuales de lecturas y rotar cualquier secreto expuesto.

Errores comunes que provocan buckets públicos accidentales

Detecta deriva en staging
Comprobamos staging vs producción para que los builds no apunten al bucket equivocado.

La mayoría de buckets públicos no son culpa de un hacker. Ocurren porque una decisión temporal se vuelve permanente, o porque nadie se hace cargo de las configuraciones después del lanzamiento.

Una trampa común es asumir que “no enlazado” significa privado. Si un bucket permite lecturas anónimas, un archivo puede abrirse por cualquiera que adivine la ruta. Si el listado está activado, un atacante ni siquiera tiene que adivinar.

Otro problema frecuente es copiar la configuración de desarrollo a producción. Los buckets de dev suelen permitir acceso amplio para que el equipo se mueva rápido. Cuando esa plantilla se reutiliza para datos reales de usuarios, terminas alojando archivos privados con reglas de demo.

Errores que se repiten:

  • Permitir que el navegador o la app cliente establezcan ACLs directamente sin comprobaciones estrictas del servidor.
  • Usar URLs públicas permanentes para archivos que deberían ser privados.
  • Confiar en el oscurantismo (nombres aleatorios) en vez de controles de acceso.
  • Dejar buckets de prueba antiguos con datos reales de clientes.
  • Mezclar archivos públicos y privados en el mismo bucket y añadir excepciones que se expanden.

Siguientes pasos: asegúralo y haz una auditoría

Decide cómo debe comportarse cada tipo de archivo que almacenas. Avatares e imágenes de marketing pueden ser públicos por diseño. Recibos, exportaciones, subidas de chat y cualquier cosa ligada a una cuenta de usuario deben ser privados por defecto, con acceso concedido solo a través de tu app.

Una vez tengas ese comportamiento objetivo, verifica las configuraciones de los buckets y luego verifica las rutas de código que suben, leen y comparten archivos. Los buckets raramente se filtran por sí solos. La mayoría de fugas ocurren porque la app asigna la ACL equivocada, genera una clave adivinable o escribe subidas en una ruta pública.

Una forma práctica de asegurar sin complicarlo:

  • Haz una tabla simple: tipo de archivo, público o privado, y quién puede acceder.
  • Audita configuraciones y políticas de buckets contra esa tabla.
  • Revisa el código de subida: ruta de destino, permisos en el momento de la subida y cualquier bandera de “hacer público”.
  • Añade una comprobación de regresión después del despliegue: intenta listar el bucket y obtener un archivo que no deberías poder ver.
  • Activa logging y alertas para cambios de política y picos de lecturas anónimas.

Si heredaste un prototipo generado por IA (por ejemplo de Lovable, Bolt, v0, Cursor o Replit), los permisos de almacenamiento y las rutas de subida suelen ser donde “funcionó en la demo” se convierte en un incidente real de privacidad. Si quieres ayuda para desenredarlo, FixMyMess (fixmymess.ai) puede ejecutar una auditoría de código gratuita para identificar buckets expuestos, comprobaciones de acceso rotas y defaults de subida riesgosos, y luego verificar las correcciones con revisión humana.

Preguntas Frecuentes

¿Cómo puedo saber rápidamente si mi bucket está expuesto?

Abre la URL real de un archivo en una ventana privada/incógnito. Si carga sin pedir inicio de sesión, trátalo como público.

También intenta acceder a un archivo al que no deberías tener permiso (por ejemplo, el avatar o la factura de otro usuario) usando el mismo patrón de URL. Si puedes obtenerlo, tus controles de acceso no funcionan.

¿Por qué el listado del bucket es peor que un solo archivo público?

El listado permite a alguien navegar muchos objetos, no solo descargar un archivo aislado. Convierte un error puntual en una extracción masiva de datos.

Incluso si solo una parte es listable, suele revelar nombres de archivos, prefijos y patrones que facilitan ataques dirigidos.

¿Qué significa realmente “no listado pero adivinable”?

Significa que las URLs siguen patrones predecibles como IDs de usuario, correos, marcas de tiempo o números de pedido, y que un tercero puede forzar rutas probables. Eso hace que “no listado” sea en la práctica público.

La solución es usar claves de objeto no adivinables y aplicar comprobaciones de acceso en cada lectura, no solo ocultar el enlace.

¿Cuál es la diferencia entre una política de bucket y las ACL de objetos?

Las políticas de bucket son reglas amplias que pueden permitir (o bloquear) lectura y listado sobre muchos objetos. Las ACL de objetos son permisos por archivo y pueden hacer que subidas individuales sean públicas aunque la política del bucket parezca segura.

Hay que revisar ambas, porque una ACL permisiva en una ruta de subidas puede filtrar archivos privados sin cambiar la política principal del bucket.

¿Cómo hago un inventario de buckets sin olvidar los “olvidados”?

Haz un inventario sencillo de cada bucket y qué almacena, incluyendo exportaciones olvidadas, backups y proyectos antiguos de staging. Luego asigna cada bucket o prefijo a la funcionalidad de la app que escribe ahí.

Una vez sepas qué pertenece dónde, puedes decidir qué debe ser público, qué debe ser privado y qué rutas nunca deben ser accesibles sin autenticación.

¿Cómo terminan los buckets de staging y dev filtrando datos de producción?

A veces se bloquea producción, pero dev o staging quedan abiertos y luego se despliega una build que aún apunta al bucket abierto. Otra opción es copiar una plantilla “amistosa para demos” a producción.

Revisa la configuración de la app para cada entorno y verifica que dev/staging no contengan datos reales de clientes.

¿Cuáles son las reglas de subida más seguras para archivos privados de usuarios?

Un buen predeterminado es: requerir autenticación antes de subir, y usar subidas firmadas de corta duración que permitan un solo objeto en una sola ruta para un solo usuario. Tras la subida, mantén los objetos privados y sirve descargas solo tras comprobar permisos.

Si usas subidas directas a almacenamiento, que sea el servidor—no el cliente—quien decida la ruta final y los permisos.

¿Cómo debemos nombrar los archivos para que la gente no pueda adivinar URLs?

Usa claves de objeto aleatorias y no adivinables, y evita poner identificadores de usuarios en las rutas. Por ejemplo, no uses correos, IDs secuenciales, números de factura o timestamps como la clave principal.

También vigila los nombres originales y metadatos: si algo se hace público por error, esos campos pueden filtrar más información que el propio contenido del archivo.

¿Qué logs y alertas ayudan a detectar la exposición temprano?

Activa registros (logs) de lecturas además de escrituras, porque el raspado parece lecturas exitosas “normales”. Las señales más útiles son accesos anónimos, picos repentinos de descargas y muchos 404 que indican intentos de adivinanza.

Mantén alertas pequeñas y específicas para que se actúe, y conserva logs el tiempo suficiente para investigar incidentes que pasan desapercibidos.

¿Qué debo hacer primero si descubro acceso público en un bucket?

Bloquea el acceso público de inmediato: impide el acceso público a nivel de bucket, elimina cualquier ACL pública y confirma que el listado está deshabilitado. Luego verifica que el código de subida de tu app no vuelva a crear objetos públicos.

Si heredaste un prototipo generado por IA, los valores por defecto y las rutas de subida suelen ser el origen de la exposición. FixMyMess puede ejecutar una auditoría de código gratuita para encontrar las malas configuraciones exactas y confirmar las correcciones con revisión humana.