Pentesting de Aplicaciones Liferay
Tabla de contenidos
Liferay es una plataforma lanzada a principios del año 2000 que proporciona un Sistema de Gestión de Contenidos (Content Management System o CMS en inglés) y que, actualmente, ofrece servicios a miles de sitios web de grandes empresas y entidades gubernamentales. Como profesionales de la seguridad ofensiva, es muy común encontrar instancias de Liferay en la infraestructura de una organización.
Sin embargo, dada la poca documentación disponible en Internet y la poca investigación en materia de seguridad realizada sobre la plataforma, puede resultar un verdadero reto encontrar ejemplos de vulnerabilidades conocidas o configuraciones erróneas en Liferay.
Este hecho destaca además si lo comparamos con otros CMS como WordPress o Drupal, cuya seguridad ha sido objeto de investigación en numerosas ocasiones. Como respuesta a esto, en este blog pretendemos ofrecer una guía para realizar ejercicios de pentesting de aplicaciones Liferay, que sea fácil de entender y verdaderamente útil.
Liferay ofrece dos productos principales: Liferay Portal CE y Liferay DXP. La principal diferencia entre ellos es que el primero es gratuito y ofrece menos funcionalidades que el segundo, que únicamente se encuentra disponible para asociados de pago mediante una tasa de subscripción.
Ambos productos están basados en la tecnología de Liferay de código abierto, pero aún así el más común es Liferay DXP. Desde este punto, nos estaremos refiriendo a Liferay DXP cuando hablemos de Liferay.
Descubrimiento de recursos ocultos
Liferay es una plataforma muy potente, que ofrece numerosas funcionalidades que permiten construir aplicaciones con gran complejidad. Sin embargo, debido a la inconsistencia de su documentación y su dificultad de comprensión, los desarrolladores a menudo pasan por alto muchas de estas funcionalidades.
Esto hace que aparezcan fallos en la configuración que pueden permitir a atacantes evitar ciertas restricciones y obtener acceso a recursos que puedan suponer un riesgo para la aplicación.
Portlet
Las aplicaciones de Liferay están compuestas por portlets, que se pueden entender como pequeñas aplicaciones web, escritas en Java normalmente, que ofrecen una funcionalidad concreta dentro de la aplicación. Existen un gran número de portlets desarrollados por Liferay que se encuentran por defecto en cualquier instalación de la plataforma.
Además, los desarrolladores pueden crear sus propios portlets para expandir las funcionalidades del portal.
Los portlets se pueden acceder mediante la siguiente ruta y parámetros:
/?p_p_id=<portlet_ID>&p_p_lifecycle=0&p_p_state=<window_state>& p_p_mode=<mode>
Donde:
- portlet_ID: Identificador del portlet que se va a ejecutar. Puede ser un identificador numérico, que es un numero incremental para cada portlet, o un fully qualified ID, que es una cadena de caracteres.
- window_state: Cantidad de espacio que ocupa el portlet en la página. Los valores disponibles son los siguientes:
- normal.
- maximized.
- minimized.
- mode: La función concreta del portlet. Los valores disponibles son los siguientes:
- view.
- edit.
- help.
A modo de ejemplo, la ruta para acceder al portlet de login podría ser la siguiente:
/?p_p_id=com_liferay_login_web_portlet_LoginPortlet&p_p_lifecycle=0&p_p_state=maximized&p_p_mode=view
En cuanto al parámetro mode, el único valor posible para usuarios no administradores en portlets por defecto es view. Sin embargo, vale la pena intentar modificarlo en portlets desarrollados por terceros.
Para descubrir portlets en una aplicación de Liferay, un atacante puede iterar sobre los identificadores numéricos (por ejemplo, en el rango de 0 a 500) y sobre la lista de fully qualified IDs de portlets por defecto.
A continuación, se muestran algunos de los portlets por defecto más interesantes:
Asset Publisher | com_liferay_asset_publisher_web_portlet_AssetPublisherPortlet |
Documents and Media | com_liferay_document_library_web_portlet_DLPortlet |
Navigation Menu | com_liferay_site_navigation_menu_web_portlet_SiteNavigationMenuPortlet |
Site Map | com_liferay_site_navigation_site_map_web_portlet_SiteNavigationSiteMapPortlet |
Web Content Display | com_liferay_journal_content_web_portlet_JournalContentPortlet |
Search Bar | com_liferay_portal_search_web_search_bar_portlet_SearchBarPortlet |
Search | com_liferay_portal_search_web_portlet_SearchPortlet |
En caso de estar autenticados, también es una buena opción realizar este mismo ataque de fuerza bruta sobre la ruta del propio Panel de Control. Por ejemplo, si la ruta del Panel de Control de la aplicación es /group/control_panel/manage, un atacante podría iterar sobre el siguiente recurso:
/group/control_panel/manage?p_p_id=&p_p_lifecycle=0&p_p_state=maximized& p_p_mode=view
El Panel de Control de Liferay es tratado más adelante en este artículo.
Página de login
Cuando se configura un CMS, es muy común ocultar la página de login por defecto o restringir su acceso con el objetivo de que los atacantes no puedan ejecutar ataques de fuerza bruta o tratar de iniciar sesión con credenciales filtradas. En Liferay, esto se suele hacer restringiendo el acceso a las siguientes rutas:
/login
/c/portal/login
Sin embargo, dado que la página de login de Liferay está desarrollado como un portlet, también es posible acceder a ella utilizando su ruta de portlet correspondiente:
/?p_p_id=58&p_p_lifecycle=0&p_p_state=maximized&p_p_mode=view
/
p_p_id=58&p_p_lifecycle=0&p_p_state=maximized&p_p_mode=view&saveLastPath=false&_58_struts_action=%2Flogin%2Flogin
/?p_p_id=com_liferay_login_web_portlet_LoginPortlet&p_p_lifecycle=0&p_p_state=maximized&p_p_mode=view
/
p_p_id=com_liferay_login_web_portlet_LoginPortlet&p_p_lifecycle=0&p_p_state=maximized&p_p_mode=view&saveLastPath=false&_58_struts_action=%2Flogin%2Flogin
Página de registro
La capacidad de registrar nuevas cuentas y obtener acceso autenticado en un CMS puede ser muy poderosa para un atacante, ya que permite realizar ataques de defacement y ampliar la superficie de ataque, lo cual incrementa en gran medida la probabilidad de que un atacante identifique nuevas vulnerabilidades. En este caso, Liferay permite deshabilitar el registro de nuevas cuentas.
Sin embargo, los desarrolladores pueden haber pasado por alto esta configuración y simplemente haber restringido el acceso al recurso de registro. Aún así, como la página de registro es una extensión del portlet que proporciona la funcionalidad de login, se puede acceder también añadiendo un parámetro a la URL del portlet de login:
/?p_p_id=58&p_p_lifecycle=0&p_p_state=maximized&p_p_mode=view&_com_liferay_login_web_portlet_LoginPortlet_mvcRenderCommandName=%2Flogin%2Fcreate_account
/?p_p_id=58&p_p_lifecycle=0&p_p_state=maximized&p_p_mode=view&saveLastPath=false&_58_struts_action=%2Flogin%2Flogin&_com_liferay_login_web_portlet_LoginPortlet_mvcRenderCommandName=%2Flogin%2Fcreate_account
/?p_p_id=com_liferay_login_web_portlet_LoginPortlet&p_p_lifecycle=0&p_p_state=maximized&p_p_mode=view&_com_liferay_login_web_portlet_LoginPortlet_mvcRenderCommandName=%2Flogin%2Fcreate_account
/?p_p_id=com_liferay_login_web_portlet_LoginPortlet&p_p_lifecycle=0&p_p_state=maximized&p_p_mode=view&saveLastPath=false&_58_struts_action=%2Flogin%2Flogin&_com_liferay_login_web_portlet_LoginPortlet_mvcRenderCommandName=%2Flogin%2Fcreate_account
Es importante tener en cuenta que, al deshabilitar el registro de nuevas cuentas, algunas instancias de Liferay pueden seguir permitiendo el acceso a la página de registro mediante estas rutas. Sin embargo, al intentar crear una cuenta nueva, el proceso de registro no se completará, por lo que siempre debe verificarse antes de reportarlo como una vulnerabilidad.
APIs
Liferay ofrece diferentes APIs con las que interactuar con la aplicación. Esto puede suponer una muy buena oportunidad para un atacante a la hora de descubrir funcionalidades que pueden no estar disponibles desde la propia interfaz de la página, en caso de que los desarrolladores no las hayan restringido correctamente. Estas APIs son las siguientes:
- JSON Web Services, que ofrece una interfaz gráfica para poder interactuar con cada endpoint:
/api/jsonws
- GraphQL, que permite ejecutar introspection queries para obtener el esquema completo de la base de datos:
/o/graphql
Además, los usuarios autenticados pueden interactuar con ambas APIs mediante una interfaz gráfica en la siguiente ruta:
/o/api
Gestor de licencias
Los administradores de una instancia de Liferay pueden obtener información sobre el estado de la licencia y del servidor dentro del Panel de Control. Igualmente, en algunas ocasiones esta información se encuentra accesible en la siguiente ruta:
/c/portal/license
Perfiles públicos de usuarios
Cada usuario existente dentro de la aplicación tiene un perfil público para cualquier usuario sin necesidad de autenticación. Esto se puede utilizar para enumerar usuarios de la aplicación:
/web/<user
/web/<user>/home
Además, las aplicaciones de Liferay presentan por defecto un usuario guest cuyo perfil público suele corresponder con la página principal del portal, que puede contener algunos recursos que los desarrolladores hayan tratado de ocultar, como un botón de login o una barra de búsqueda:
/web/guest
/web/guest/home
Los perfiles de usuario serán tratados más Adelante en la sección de Funcionalidades peligrosas.
Configuración de usuario
Los usuarios autenticados pueden editar sus datos en la página de configuración por defecto de Liferay. Sin embargo, algunos desarrolladores eligen restringir el acceso a este recurso e implementar su propia página de configuración de usuario, a veces incluso restringiendo la edición de algunos parámetros como el nombre de usuario, el correo electrónico, la foto de perfil, etc.
Por ejemplo, esto puede pasar en infraestructuras donde la aplicación de Liferay se esté utilizando como Intranet de una empresa y cada usuario tenga un nombre y un correo por defecto. En estos casos, puede ser posible acceder igualmente a la página de configuración de usuario de Liferay y editar estos parámetros en las siguientes rutas:
/user/<user>
/user/<user>/manage
/user/<user>/manage
p_p_id=com_liferay_my_account_web_portlet_MyAccountPortlet&p_p_lifecycle=0&p_p_state=maximized&p_p_mode=view
/group/control_panel/manage?p_p_id=com_liferay_my_account_web_portlet_MyAccountPo
Panel de control
Los usuarios autenticados pueden editar sitios web, wikis, blogs, comentarios y cualquier elemento al que tengan acceso mediante el panel de control, dependiendo de sus roles y permisos. Es muy importante comprobar todos los apartados del panel de control, ya que los desarrolladores suelen pasar por alto algunos permisos y los usuarios suelen poder editar más elementos de los que deberían.
Para evitar que los usuarios puedan editar elementos, algunos desarrolladores restringen el acceso al panel de control bloqueando algunas URLs. Sin embargo, existen numerosas formas de acceder a él, por lo que es sencillo evadir estas restricciones:
/group/control_panel/manage
/group/guest/control_panel/manage
/group/guest/~/control_panel/manage
/group/<user>/control_panel/manage
/group/<user>/~/control_panel/manage
/user/<user>/control_panel/manage
/user/<user>/~/control_panel/manage
Si ninguna de estas rutas permite acceder al panel de control, en ocasiones añadir los parámetros correspondientes a un portlet al que se tenga acceso puede hacer que se muestre dicho portlet junto al panel de control. Por ejemplo, si el portal de login es accesible a través de las siguientes rutas:
/?p_p_id=com_liferay_login_web_portlet_LoginPortlet&p_p_lifecycle=0&p_p_state=maximized&p_p_mode=view
Las siguientes rutas pueden permitir acceso al panel de control:
/group/control_panel/manage?p_p_id=com_liferay_login_web_portlet_LoginPortlet&p_p_lifecycle=0&p_p_state=maximized&p_p_mode=view
/group/guest/control_panel/manage?p_p_id=com_liferay_login_web_portlet_LoginPortlet&p_p_lifecycle=0&p_p_state=maximized&p_p_mode=view
/group/guest/~/control_panel/manage?p_p_id=com_liferay_login_web_portlet_LoginPortlet&p_p_lifecycle=0&p_p_state=maximized&p_p_mode=view
/group/<user>/control_panel/manage?p_p_id=com_liferay_login_web_portlet_LoginPortlet&p_p_lifecycle=0&p_p_state=maximized&p_p_mode=view
/group/<user>/~/control_panel/manage?p_p_id=com_liferay_login_web_portlet_LoginPortlet&p_p_lifecycle=0&p_p_state=maximized&p_p_mode=view
/user/<user>/control_panel/manage?p_p_id=com_liferay_login_web_portlet_LoginPortlet&p_p_lifecycle=0&p_p_state=maximized&p_p_mode=view
/user/<user>/~/control_panel/manage?p_p_id=com_liferay_login_web_portlet_LoginPortlet&p_p_lifecycle=0&p_p_state=maximized&p_p_mode=view
En algunos casos, el panel de control puede incluso utilizarse para obtener información de otros usuarios como sus roles, sus permisos o incluso datos personales:
/user/<other_user>/control_panel/manage
/user/<other_user>/~/control_panel/manage
Funcionalidades peligrosas
Las aplicaciones de Liferay ofrecen algunas funcionalidades cuyo estado actualmente no es del todo seguro y pueden producir ciertas vulnerabilidades. Liferay no pretende parchear estas funcionalidades ya que los desarrolladores consideran que funcionan de la forma esperada. Sin embargo, como veremos a continuación, suponen un riesgo real para la seguridad de la aplicación.
Open redirect
Por defecto, Liferay permite redirigir a un dominio arbitrario utilizando las siguientes rutas:
/html/common/referer_jsp.jsp?referer=<url>
/html/common/referer_js.jsp?referer=<url>
/html/common/forward_jsp.jsp?FORWARD_URL=<url>
/html/common/forward_js.jsp?FORWARD_URL=<url>
Esto permite a atacantes utilizar una aplicación legítima de Liferay para redirigir usuarios a un dominio arbitrario, pudiendo ejecutar otros ataques como phishing o usándolo como parte de una cadena más compleja de vulnerabilidades.
Además, en versiones anteriores de Liferay, algunas de estas rutas presentan también una vulnerabilidad de tipo XSS reflejado, en la que un atacante puede ejecutar código JavaScript en el navegador del usuario que acceda al link malicioso:
/html/common/referer_js.jsp?referer=javascript:alert("XSS")
/html/common/forward_js.jsp?FORWARD_URL=javascript:alert("XSS")
Sin embargo, como esta vulnerabilidad fue solucionada de forma discreta por los desarrolladores de Liferay, no tiene un CVE asociado y no está claro qué versiones son vulnerables.
JavaScript en los perfiles de usuario
Anteriormente en este artículo, se han mencionado los perfiles de usuario, que se comportan como páginas públicas que cada usuario puede editar para mostrar un contenido. Estas páginas permiten añadir código JavaScript y son accesibles por cualquier usuario, incluso aquellos sin autenticar, pudiéndose aprovechar esta funcionalidad para explotar una vulnerabilidad de tipo XSS almacenado muy poderosa.
Ejecución de código en el panel de control de administrador
Como en cualquier otro CMS, los administradores tienen acceso a funcionalidades mucho más críticas que cualquier otro usuario. En el caso de Liferay, existe una opción para activar una consola de Gogo, que permite gestionar módulos de la aplicación.
Sin embargo, esta consola también puede utilizarse para ejecutar algunos comandos en el sistema operativo, como recorrer los directorios del servidor o acceder a archivos. Una vez que está activada, la consola se encuentra disponible en la siguiente ruta:
/group/control_panel/manage?p_p_id=com_liferay_gogo_shell_web_internal_portlet_GogoShellPortlet&p_p_lifecycle=0&p_p_state=maximized&p_p_mode=view&_com_liferay_gogo_shell_web_internal_portlet_GogoShellPortlet_javax.portlet.action=executeCommand
Como se ha mencionado, esta consola únicamente permite ejecutar algunos comandos:
Además, el panel de control de administración también ofrece la Consola de Scripts, que es un intérprete de Groovy. Se puede acceder a ella en la siguiente ruta:
/group/control_panel/manage?p_p_id=com_liferay_server_admin_web_portlet_ServerAdminPortlet&p_p_lifecycle=0&p_p_state=maximized&p_p_mode=view&_com_liferay_server_admin_web_portlet_ServerAdminPortlet_mvcRenderCommandName=%2Fserver_admin%2Fview&_com_liferay_server_admin_web_portlet_ServerAdminPortlet_tabs1=script
En este caso, la consola de scripts sí que permite ejecutar comandos del sistema operativo sin ninguna restricción, usando el siguiente fragmento de código:
def sout = new StringBuilder(), serr = new StringBuilder()
def proc = "<command>".execute()
proc.consumeProcessOutput(sout, serr)
proc.waitForOrKill(1000)
println "$sout"
Vulnerabilidades conocidas
Como cualquier otro software, Liferay ha tenido numerosas vulnerabilidades en el pasado y probablemente tenga más en el futuro. Ofrecen un índice para la mayoría de las vulnerabilidades conocidas con el fin de poder hacer un seguimiento adecuado. Como profesionales de la seguridad ofensiva, pueden ser muy útiles para conseguir explotar aplicaciones desactualizadas.
Sin embargo, existe una vulnerabilidad de Liferay que merece la pena mencionar debido a su impacto.
Ejecución de Código mediante deserialización insegura (CVE-2020-7961)
CVE-2020-7961 es una vulnerabilidad que afecta a Liferay Portal < 7.2.1. que consiste en una deserialización insegura de datos en la API de JSON web services (/api/jsonws). Existen múltiples artículos sobre el proceso de explotación, así como numerosos exploits en Github.
Para explotar esta vulnerabilidad, no es necesaria autenticación ni ninguna configuración especial: afecta por defecto a las b.
Conclusiones
Liferay es una plataforma potente que presenta una amplia variedad de funcionalidades y una arquitectura compleja. Su flexibilidad y modularidad permiten a los desarrolladores crear configuraciones muy específicas que se adapten lo máximo posible a sus necesidades.
Sin embargo, esta gran capacidad de personalización también hace más probable la introducción de nuevas vulnerabilidades, que pueden llegar a suponer un gran riesgo para las organizaciones que utilizan Liferay.
Este artículo busca servir de guía para realizar pruebas de seguridad y pentesting en entornos de Liferay, proporcionando técnicas que permitan identificar vulnerabilidades y fallos de configuración comunes, con el fin de minimizar el riesgo asociado a un posible ataque.