Pentesting de aplicaciones Adobe Experience Manager (AEM)
Tabla de contenidos

Introducción a AEM
Adobe Experience Manager (AEM) es un sistema de gestión de contenidos empresarial desarrollado por Adobe, ampliamente utilizado para la creación y administración de sitios web y formularios digitales. Se trata de una de las plataformas CMS más extendidas en entornos corporativos y es utilizada por numerosas organizaciones de gran tamaño y relevancia. El elevado nivel de adopción de AEM implica que cualquier fallo de seguridad identificado en la plataforma puede tener un impacto significativo, dado que podría afectar potencialmente a un gran número de entornos corporativos.
No obstante, AEM destaca por su alto nivel de personalización, lo que provoca que no existan dos despliegues idénticos, dificultando la explotación genérica y masiva de vulnerabilidades en todos los escenarios. Habitualmente, AEM se despliega junto con Adobe Dispatcher, un proxy inverso proporcionado por Adobe que actúa como una capa adicional de protección. Este componente se encarga de filtrar y bloquear peticiones maliciosas antes de que alcancen la instancia de AEM, si bien también se han identificado vulnerabilidades asociadas a este componente.
Desde el punto de vista tecnológico, AEM está construido sobre Java y se ejecuta sobre un contenedor OSGi (Open Services Gateway Initiative), utilizando habitualmente Apache Felix como framework de referencia. Esta arquitectura permite la gestión de componentes y servicios, facilitando la personalización de la plataforma, aunque también introduce una complejidad adicional que debe tenerse en cuenta desde el punto de vista de la seguridad y la configuración del entorno.
Author vs Publish
AEM cuenta con dos instancias diferentes, es importante diferenciar entre ellas ya que una mala configuración puede afectar gravemente a la seguridad de la aplicación.
En primer lugar, tenemos la instancia Author, aquí es donde los redactores y administradores subirán imágenes o archivos, crearán nuevos artículos en el blog y podrán realizar más acciones administrativas. Esto incluye acceso a consolas y editores.
Después tenemos la instancia Publish, esta es la instancia que verán los visitantes del sitio web. En esta instancia, las consolas administrativas, paneles de autenticación y endpoints importantes estarán bloqueados su acceso por seguridad.
Por eso es importante asegurarse antes de publicar una web con AEM, si la instancia que tenemos configurada en producción es Publish.
¿Qué es Dispatcher?
Dispatcher es un módulo desarrollado por Adobe que se instala habitualmente en un servidor web como Apache o Nginx, aunque es mucho más frecuente encontrarlo en el primero.
Su función es situarse delante de AEM Publish como una capa intermedia que decide qué peticiones pueden pasar, cuáles pueden servirse desde caché y cuáles deben reenviarse al backend.
En otras palabras, Dispatcher es la primera pieza que recibe el tráfico web antes de que AEM procese la solicitud. Actúa como proxy inverso, como mecanismo de caché y también como una capa básica de filtrado.
Esto es importante porque reduce la exposición directa de AEM en ciertos endpoints internos, rutas administrativas o recursos sensibles pueden bloquearse antes de que la petición llegue a Publish.
Además, mejora el rendimiento del entorno al servir contenido previamente cacheado, lo que reduce la carga del servidor y acelera los tiempos de respuesta.
Cabe recalcar que Dispatcher no sirve como sustituto de un WAF como Cloudflare, solo se limita a bloquear determinadas peticiones, pero no detecta payloads maliciosos, inyecciones SQL, etc…
A continuación, veremos algunos ejemplos de configuraciones incorrectas en Dispatcher que pueden ser aprovechadas por atacantes, esto también te resultará útil tanto si estás auditando una web con este gestor de contenido como si estás desarrollando una aplicación web.
Un error muy grave sería permitir (allow) los endpoints /libs y/o /content ya que aquí se encuentran archivos JSON con información, consolas internas e incluso el panel de login.
/filter {
/0001 { /type "allow" /url "/libs/" }
/0002 { /type "allow" /url "/content/" }
}
Otro error sería confiar en regex débiles mal configurados, esto supondría tirar por tierra todas las configuraciones anteriores ya que podrían hacer un bypass de estas, como observamos en el ejemplo, el acceso al endpoint /libs está bloqueado (deny), mientras que /content está permitido (allow).
/filter {
/0001 { /type "deny" /url "/libs/" }
/0002 { /type "allow" /url "/content/" }
}
Sería posible realizar un bypass de varias maneras para acceder al panel de login que se encuentra en /libs empleando un path traversal, con el cual engañaremos al Dispatcher para hacerle creer que estamos accediendo a /content.
/content/../libs/granite/core/content/login.html
/content/%2e%2e/libs/granite/core/content/login.html
/content/.;/libs/granite/core/content/login.html
/content/foo/../../libs/granite/core/content/login.html
Estructura de la aplicación
Supongamos que en nuestra empresa tenemos varias páginas web, todas ellas con AEM instalado, por poner un ejemplo cyber.example.com y empleo.example.com podrían ser dos páginas independientes de la misma empresa, pero el contenido que podemos encontrar en un dominio y otro será el mismo, ya que comparten carpetas como /content.
Introducción a los directorios de AEM
Como cualquier otro gestor de contenidos, AEM organiza gran parte de su información en distintos directorios cuya exposición puede resultar muy útil durante una auditoría de seguridad.
En los siguientes apartados se revisarán algunos de los directorios más importantes, qué tipo de archivos pueden encontrarse en ellos para enumerar información del sitio web y qué riesgos o ataques pueden existir si alguno de estos recursos es accesible desde el exterior.
Directorio /content – Contenido publicado y estructura
Como vimos anteriormente, en un mismo servidor se pueden tener múltiples instancias de AEM, es importante saber que la raíz comienza igual para ambos dominios, aquí es donde reside el contenido del sitio web.
/content
Dentro del directorio /content, existen dos carpetas más, una para cada una de nuestras webs.
/content/empleo-example
/content/cyber-example
Cada una de ellas almacena los archivos relativos a su página web, pero lo interesante es que es posible acceder a /content/empleo-example desde cyber.example.com.
https://cyber.example.com/content/empleo-example
Cada uno de estos directorios almacena varios ficheros con la estructura del nodo, estos no deberían de estar visibles ya que el Dispatcher los debe de bloquear si está correctamente configurado.
/.json -> Estructura del directorio
/.infinity.json -> Estructura completa del nodo
Estos ficheros se repiten por cada uno de los directorios y subdirectorios.
Por último, en el directorio /content también se encuentra la carpeta /content/dam, la palabra DAM viene de las siglas de Digital Asset Manager, se podría decir que es como la carpeta /wp-content de WordPress en la que se almacenan documentos PDF, imágenes, vídeos y más archivos.
/content/dam/cyber-example/logo.jpg
/content/dam/empleo-example/logo.jpg
Directorio /etc – Configuraciones
Este directorio ha sido sustituido en las últimas versiones por /conf y /apps. Sin embargo, un directorio que aún continúa existiendo y es muy importante es /etc.clientlibs . Aquí se almacenan las librerías del cliente compiladas, principalmente archivos JavaScript y CSS.
/etc.clientlibs/clientlibs/jquery.min.3tc533t63d33ft67cd4a0f76g67i0439.js
Directorio /bin – Servlets y endpoints
Bajo este directorio se almacenan los servlets personalizados desarrollados específicamente para la aplicación. Estos componentes suelen implementar lógica propia para la gestión de peticiones de registro, procesamiento de formularios y otras funcionalidades que no se encuentran disponibles de forma nativa en AEM.
QueryBuilder – Búsquedas internas
También AEM almacena sus propios endpoints en el directorio /bin, como /bin/querybuilder.json que permite realizar consultas a todos los nodos y obtener un JSON como respuesta. Esta herramienta está pensada para desarrolladores o autores, pero si estuviera abierta públicamente un atacante podría extraer información del contenido, como usuarios, grupos, acceso a documentos privados, ataques DDoS…
Enumeración de usuarios:
GET /bin/querybuilder.json?path=/home/users&type=rep:User&p.limit=50
Enumeración de grupos:
GET /bin/querybuilder.json?path=/home/groups&type=rep:Group&p.limit=50
Denegación de servicio:
Esta consulta provoca una denegación de servicio en el servidor debido a que se solicita que muestre todo el contenido que cuelga de la carpeta /content sin aplicar ninguna paginación.
GET /bin/querybuilder.json?path=/content&p.limit=-1
Directorio /system/console – Consola OSGi
Este directorio expone la consola web de administración de Apache Felix, el framework OSGi sobre el que se apoya AEM para la gestión de configuraciones y servicios internos.
El acceso a este endpoint requiere credenciales administrativas y nunca debería estar expuesto públicamente. Una exposición indebida de /system/console supone una vulnerabilidad crítica, ya que permite a un atacante autenticado instalar o modificar bundles OSGi, alterar configuraciones sensibles y, en consecuencia, derivar en ejecución remota de código (RCE) con los privilegios del proceso de AEM.
Por este motivo, su acceso debe estar estrictamente limitado a entornos internos, protegido por ACLs, Dispatcher y controles de red, y monitorizado para detectar accesos no autorizados.
Directorio /crx/de – CRXDE Lite
Interfaz CRXDE Lite para desarrolladores, utilizada para editar el repositorio desde el navegador. En un entorno de producción debe de bloquearse su acceso desde el exterior.
Además, su exposición puede facilitar la enumeración de nodos JCR (Java Content Repository), la lectura de configuraciones sensibles y el descubrimiento de rutas internas como, por ejemplo, componentes y scripts.
Java Content Repository (JRC): Es el repositorio donde AEM almacena de forma estructurada contenidos, configuraciones y metadatos.
Si un atacante consigue credenciales válidas, esta consola puede convertirse en un punto de entrada para modificar contenido, permisos o configuraciones directamente en el repositorio.
Por ello, lo habitual es restringirla por IP/VPN, protegerla con autenticación fuerte y/o bloquearla desde Dispatcher/WAF para que no sea accesible públicamente.
Directorio /crx/packmgr – Package Manager
Esta herramienta es utilizada para importar y exportar paquetes en formato ZIP con contenido JCR. Desde esta interfaz gráfica permite a usuarios autenticados subir nuevos paquetes y desplegar código, lo que puede ser muy peligroso si este panel está expuesto de forma pública a cualquier usuario.
Enumeración y descubrimiento de endpoints y recursos
Como ocurre con la mayoría de los gestores de contenido, AEM dispone de un panel de autenticación destinado a usuarios administrativos y editores. Por motivos de seguridad, este tipo de interfaces no debería ser accesible desde el exterior y su acceso debería limitarse a redes internas o a usuarios específicamente autorizados.
Sin embargo, al igual que sucede en otros CMS como WordPress, en algunos despliegues de AEM el panel de login permanece expuesto públicamente debido a configuraciones incorrectas. Por este motivo, resulta necesario comprobar si las rutas de autenticación están accesibles desde Internet:
/libs/granite/core/content/login
/libs/granite/core/content/login.html?resource=%2F
/libs/granite/core/content/login.html/j_security_check
Si el panel de autenticación es accesible desde cualquier red y para cualquier usuario, esta situación debe ser comunicada al administrador del sitio, ya que facilita ataques de fuerza bruta y enumeración de usuarios, además de ampliar la superficie de exposición del sistema. Aunque la existencia del login no es una vulnerabilidad por sí misma, su exposición incrementa el riesgo de la plataforma y debería corregirse mediante Dispatcher.
Diccionario de rutas y archivos para AEM
La enumeración de rutas y archivos juega un papel fundamental en una auditoría a una web con AEM instalado. Este diccionario que se encuentra en GitHub contiene unas 500 líneas con múltiples endpoints importantes y además varios bypass para tratar de acceder a archivos JSON y paneles de administración.
Para realizar la enumeración podríamos utilizar herramientas como WFUZZ, Gobuster, Dirsearch o cualquiera de las muchas que existen. En la imagen se puede observar cómo WFUZZ ha encontrado varios endpoints, aunque algunos de ellos con un status code 403 (FORBIDDEN). Después, aunque otros tengan un status code 200, no significa que sean accesibles; en algunos casos hay falsos positivos, por lo que habría que asegurarse de forma manual visitando la web.

Desde este repositorio puedes descargar el diccionario para realizar la enumeración de directorios anterior.
Conclusión
AEM es una plataforma empresarial muy completa, con una arquitectura que combina gestión de contenido, componentes reutilizables y múltiples capas como Author/Publish, JCR, OSGi y Dispatcher. Esto, pese a tener una alta curva de aprendizaje, permite a las empresas construir una aplicación muy personalizable donde se integran módulos con desarrollos a medida.
Sin embargo, esta alta personalización también incrementa la superficie de ataque y hace que sea más probable configurar de forma insegura algún endpoint y que quede expuesto sin autenticación. En AEM, pequeñas configuraciones pueden tener un gran impacto como vimos anteriormente. De ahí que los servicios de pentesting sean claves a la hora de asegurarse y repasar todas las configuraciones para evitar enumeración de información o incluso ejecución de comandos.
Finalmente, espero que este artículo haya servido como guía a la hora de auditar una web en entornos AEM y si en tu caso estás desarrollando una aplicación basada en este gestor de contenidos, conviene tener en cuenta las situaciones descritas para evitar reproducir los errores mencionados anteriormente.
Referencias