Blog / CVE explicados

CVE-2026-21589: la lectura de archivos de Atlassian que se esconde tras ::

CVE-2026-21589 es una lectura de archivos sin autenticación en ocho productos Data Center de Atlassian. Este es el error de orden que la provoca, y cómo comprobar su propio código.

Estudios de doctorado en Seguridad de la Información completadosDefensa universitaria superada · Defensa final de la tesis pendiente

Una biblioteca, ocho productos y una sola solicitud hasta sus archivos de configuración

Sin iniciar sesión. Y aun así devolvió la respuesta. En una instancia conectada a Atlassian Crowd, eso es un 200 OK que trae una contraseña, a partir de una solicitud sin ninguna autenticación. El 5 de octubre de 2026, Atlassian publicó una corrección fuera de ciclo para CVE-2026-21589, una lectura arbitraria de archivos sin autenticación con una puntuación CVSS 4.0 de 9,3. [1] Un único fallo alcanza ocho productos Data Center y Server: Jira Software, Jira Service Management, Confluence, Bitbucket, Bamboo, Crowd, Crucible y Fisheye. No fallan todos por casualidad. Comparten una biblioteca, atlassian-plugins-webresource, y el error está dentro de ella. El aviso indica la versión corregida de cada producto; la biblioteca en sí se corrige en la 6.0.8. [1][2]

Atlassian es cuidadosa con los límites. Un atacante puede leer «archivos concretos dentro del directorio raíz de la aplicación web», y solo si ya conoce la ruta exacta, sin listado de directorios. [1] Suena limitado. No lo es, y explicar por qué no lo es constituye el objetivo de este artículo. No he reproducido este fallo en una instancia real; lo que sigue se basa en el aviso de Atlassian y en el análisis de la causa raíz de watchTowr, consultados el 8 de octubre de 2026. [1][2]

// atlassian-plugins-webresource, before 6.0.8
escapeSlashes(String string)   { return string.replaceAll("/", "::"); }
unescapeSlashes(String string) { return string.replaceAll("::", "/"); }

// How a web-resource name is handled on the way in:
resourceName                       // attacker-controlled
  -> check for ".." / "/" traversal   // sees "..::", no slash -> looks safe
  -> unescapeSlashes(resourceName)    // "..::"  becomes  "../"
  -> load file relative to web root   // traversal now active

El servidor creía que :: era seguro. El atacante controlaba en qué se convertía

Este es el diseño en el que confiaron los desarrolladores. Las URL de los web-resources llevan una clave de recurso y un nombre de recurso. Una barra dentro de ese nombre confundiría al enrutador, así que la biblioteca la escapa: cada «/» se convierte en «::» a la entrada, y cada «::» vuelve a ser «/» más adelante. [2] Una codificación así es razonable. El error no está en la codificación. El error está en el orden.

El código comprueba primero si la cadena entrante contiene un recorrido de directorios, mientras las barras siguen escritas como «::». Para esa comprobación, una secuencia como «..::» no contiene ninguna barra, así que parece un nombre de archivo corriente y pasa. Solo después la biblioteca deshace el escape de la cadena, y «..::» se convierte en «../». [2] El componente que juzgó segura la solicitud y el que recorrió el sistema de archivos estaban mirando dos cadenas distintas. El atacante es dueño del hueco que hay entre ambas.

Por qué una lectura de archivos es en realidad la toma de su capa de identidad

Recorrámoslo paso a paso. El nombre escapado, con aspecto de recorrido de directorios, supera la validación, se decodifica de nuevo en segmentos «../» reales y se entrega al cargador que lee del classpath y de la raíz de la aplicación web. [2] watchTowr informa de que la lectura se queda dentro del contexto de Tomcat, así que no se puede salir hasta /etc/passwd. Para un atacante, ese límite apenas importa, porque los archivos que merece la pena leer ya están dentro.

El que importa es WEB-INF/classes/crowd.properties. En los productos conectados a Atlassian Crowd, ese archivo contiene el nombre de la aplicación y la contraseña de aplicación que se usa para hablar con el servidor de identidad. [2] Un fallo de «leer un archivo» sin autenticación entrega ahora una credencial del sistema que gestiona sus usuarios. watchTowr describe exactamente ese paso: se lee el archivo, se toma la contraseña de aplicación de Crowd y ya no se están leyendo archivos, sino hablando con la capa de identidad como una aplicación de confianza. [2]

Ese es el movimiento que omitieron los titulares. «Lee archivos concretos» y «entrega a un atacante sus secretos de identidad» son el mismo error, separados solo por saber qué archivo pedir. La condición previa del aviso, que hay que conocer la ruta exacta, es real, pero crowd.properties no está en una ubicación secreta. Es donde ese archivo está siempre. [1][2]

# WEB-INF/classes/crowd.properties  (illustrative keys, not real values)
application.name       = my-confluence
application.password   = <shared secret to the Crowd identity server>
crowd.server.url       = https://id.example.internal/crowd/services/
crowd.base.url         = https://id.example.internal/crowd/

El parche invierte el orden de dos pasos. Asegúrese de que es eso lo que ha desplegado

La corrección de atlassian-plugins-webresource 6.0.8 cierra el hueco haciendo que la comprobación y el sistema de archivos vean la misma cadena: el nombre se decodifica a su forma real antes de la comprobación de recorrido de directorios, no después. [2] Merece la pena retener el principio por su nombre: primero canonicalizar, después validar. Una comprobación de seguridad solo tiene sentido si inspecciona exactamente el valor que llega al punto peligroso. El flujo siguiente muestra ese orden corregido como ayuda para la revisión, no como copia del diff de Atlassian.

Para un responsable de producto, la trampa es fiarse del número de versión en lugar del artefacto. Varios de estos productos publican más de una rama corregida, y una imagen de reversión, un servidor de preproducción o un Crucible olvidado pueden seguir cargando la biblioteca 6.0.7 mientras sus notas dicen «parcheado». [1] Compruebe el jar que realmente se carga, en la instancia que realmente es accesible. Una copia parcheada en el portátil de un desarrollador no demuestra nada sobre el servidor expuesto a internet.

// The fix, as a principle (not Atlassian's exact diff):
// decode to the real value FIRST, then validate THAT value.
resourceName
  -> unescapeSlashes(resourceName)    // "..::"  becomes  "../"  up front
  -> check the decoded value for ".." traversal   // now the check sees it
  -> reject, or load file relative to web root

Cómo encontraría este patrón en un código que no es de Atlassian

Este error no trata realmente de Atlassian. Es una clase de errores, y esa clase es «validar y después transformar». Siempre que un código decodifica, deshace un escape, normaliza o canonicaliza un valor después de haber comprobado si es peligroso, tiene el mismo agujero, ya sea el destino una lectura de archivos, una SSRF o una cadena SQL. Cuando reviso código, lo primero que busco con grep es un paso de decodificación situado después de un paso de validación sobre la misma variable.

El patrón siguiente es mi punto de partida. Saca a la luz las llamadas de decodificación y los destinos; el trabajo de verdad es manual. Para cada resultado me hago una sola pregunta: ¿la cadena que examinó la comprobación de «..» es, byte a byte, la que llega al sistema de archivos? Si hay una transformación entre medias, la comprobación está inspeccionando un valor que ya no existe cuando importa. Esa pregunta encuentra este error más rápido que cualquier firma de un escáner, porque el escáner compara nombres y yo comparo el orden.

# Smell to hunt: a decode/normalise step that runs AFTER the path check,
# on the same variable. Start broad, then read each hit by hand.
rg -ni "replaceAll|URLDecoder|decode|unescape|normalize|canonical" \
   --glob '!**/test/**'

# The one question that confirms the bug:
#   is the string that reaches the file sink byte-for-byte the string
#   the ".." check inspected? If a transform sits between them, it is vulnerable.

¿Es este su incendio? Para algunos de ustedes, sí, hoy mismo

Seamos honestos con la escala. Esto afecta solo a las instalaciones propias de Data Center y Server. Atlassian afirma que las instancias en la nube se parchearon y que no hay pruebas de explotación en ellas. [1] Si trabaja íntegramente en Atlassian Cloud, este no es su incidente. Si aloja usted mismo cualquiera de los ocho productos y lo expone a internet, lo es, y el reloj ya está corriendo.

watchTowr publicó la causa raíz y una prueba de concepto el 6 de octubre y sitúa la población expuesta «en el rango de las seis o siete cifras», con algo menos de 700 000 instancias solo de Confluence según su recuento. [2] Tome esa cifra como suya, no como mía. Lo que no está en discusión es la velocidad. The Hacker News y BleepingComputer informan de que los honeypots registraron intentos de explotación unas dos horas después de que se publicaran los detalles, por ahora sobre todo de identificación de sistemas y de barrido en busca de archivos de configuración. [3][4] Actualización del 18 de octubre: CISA ha confirmado la explotación activa, al añadir este CVE a su catálogo de vulnerabilidades explotadas conocidas el 15 de octubre con un plazo de parcheo federal que vence hoy. [5]

Así que las tres condiciones para que esta sea su emergencia son sencillas. Aloja usted mismo uno de los ocho productos. Es accesible desde internet o desde un segmento de red del que no se fía por completo. Y ha ejecutado una compilación sin parchear de la biblioteca en algún momento desde el 5 de octubre. Si se cumplen las tres, parchear es el primer paso, no todo el trabajo, porque un archivo que podía leerse puede que ya se haya leído.

Qué hacer antes de cerrar esta pestaña

La lista siguiente refleja el orden en el que trabajaría. Primero parchear, porque aquí el margen para mitigar se mide en horas, no en semanas. [3] Pero si aloja usted mismo el producto y estuvo expuesto, dé por hecho que la contraseña de aplicación de Crowd y cualquier otra cosa bajo la raíz web pueden haberse leído, y rótelas. Un parche detiene la siguiente lectura. No recupera un secreto que ya se ha filtrado.

Los registros de acceso son donde descubrirá si alguien lo intentó. Las solicitudes anteriores al parche a las rutas de web-resources que llevan «::», «%3a%3a» o «..» en el nombre del recurso son la firma que hay que buscar. Una coincidencia no demuestra que la lectura tuviera éxito, pero le indica qué instancias tratar como sospechosas y qué secretos rotar primero.

Patch and verify (in this order):
  [ ] List every self-hosted install: Jira, JSM, Confluence, Bitbucket,
      Bamboo, Crowd, Crucible, Fisheye.
  [ ] Confirm the build that is RUNNING, not the one in your notes.
  [ ] Patch each product to its fixed version from the advisory [1].
  [ ] Cannot patch yet? Apply Atlassian's WAF / RewriteValve mitigation [1].

If you were exposed and unpatched, assume read, then rotate:
  [ ] The Crowd application password in crowd.properties.
  [ ] Any other secret stored under the web application root.

Hunt the access logs for pre-patch probing:
  grep -iE "/(s|resources|sources)/[^ ]*(::|%3a%3a|\.\.)" access.log

Lo que no le dirá una actualización de versión

CVE-2026-21589 es un ejemplo claro de un error que no se ve en el número de versión. La corrección invierte el orden de dos pasos internos, y la única forma de saber que su despliegue está a salvo es mirar el artefacto que se está ejecutando y la ruta de código que llega al sistema de archivos. Esa es la distancia entre «hemos aplicado el parche» y «hemos verificado que lo que nos importa está cerrado».

Seguir una solicitud desde el perímetro, a través del framework, hasta la línea exacta que decide qué se lee es el núcleo de una revisión de seguridad del código, y el patrón «validar y después transformar» de este CVE es algo que busco en código que no tiene nada que ver con Atlassian. Si va a lanzar algo que convierte entradas externas en acceso a archivos, consultas a bases de datos o solicitudes internas, ese es el límite que comprobaría por usted. Cuénteme qué está ejecutando y definiremos el alcance.

Fuentes

¿Necesita que se compruebe esto en su propio producto?

Revisión de seguridad del código

¿Quiere aprender a encontrar vulnerabilidades como esta por su cuenta?

Curso individual de revisión de código seguro
Todos los artículos

08Contacto

¿Va a lanzar algo que trata datos de usuarios?

Envíeme un breve resumen. Respondo en un plazo de tres días con preguntas o un esbozo de propuesta, y el precio se acuerda por escrito antes de empezar.