¿Estás visitando desde Perú?
Ingresá a Linware Perú ⯈
Continuar en Linware Perú ⯈
×
¿Qué estás buscando?
BUSCAR!
BLOG
Implementando una verificación CSRF en una extensión de Zimbra
Publicada el 18/05/2022

En este artículo aprenderá cómo implementar una verificación CSRF en una extensión de Zimbra. El proyecto Java y el código fuente se pueden encontrar en https://github.com/Zimbra/zm-extension-guide .

En muchos casos, la política de recursos de origen cruzado en el navegador web y la configuración del atributo SameSite=Strict en la cookie de autenticación proporcionarán suficiente seguridad para su extensión. Sin embargo, en algunos casos, es posible que desee implementar una verificación CSRF adicional en su extensión. Por ejemplo, es posible que desee permitir la publicación de formularios HTTP solo desde un dominio específico en su organización (y no permitir subdominios).

Aquí hay una implementación de ejemplo:

 /**n  * Processes HTTP OPTIONS requests.n  *n  * Here is an example CSRF implementation, you may not need it for your application, also be aware of the following setting:n  * zmlocalconfig -e zimbra_same_site_cookie="Strict"n  *n  * In this demonstration case the CSRF check is implemented on the HTTP Options request, in reality you would probably implement it on HTTP Post and Get.n  *n  * You will also need to set zimbraCsrfAllowedRefererHosts if you want to implement a referer check:n  * zmprov mcf +zimbraCsrfAllowedRefererHosts "zimbra.example.com"n  *n  * Example request to test this CSRF implementation:n  * curl 'https://zimbra.example.com/service/extension/mytest' -X OPTIONS -H 'X-Zimbra-Csrf-Token: 0_3278....030b' -H 'Referer: https://zimbra.example.com/modern/email/Inbox/conversation/266' -H 'Cookie: ZM_AUTH_TOKEN=0_78fe8e....a313b;'n  *n  * @param req  request messagen  * @param resp response messagen  * @throws java.io.IOExceptionn  * @throws javax.servlet.ServletExceptionn  */nn @Overriden public void doOptions(HttpServletRequest req, HttpServletResponse resp) throws IOException, ServletException {n     //all authentication is done by AuthUtil.getAuthTokenFromHttpReq, returns null if unauthorizedn     final AuthToken authToken = AuthUtil.getAuthTokenFromHttpReq(req, resp, false, true);n     if (authToken == null) {n         resp.getOutputStream().print("No or invalid Auth token received.");n         return;n     }n     String csrfToken = req.getHeader(Constants.CSRF_TOKEN);n     if (!StringUtil.isNullOrEmpty(csrfToken)) {n         resp.getOutputStream().print("No CSRF token received.");n         return;n     }nn     //check for valid CSRF tokenn     if (!CsrfUtil.isValidCsrfToken(csrfToken, authToken)) {n         resp.getOutputStream().print("CSRF check FAILED.");n         return;n     }nn     //do a CSRF referrer checkn     String[] allowedRefHosts = null;n     Provisioning prov = Provisioning.getInstance();n     try {n         allowedRefHosts = prov.getConfig().getCsrfAllowedRefererHosts();n     } catch (Exception e) {n         resp.getOutputStream().print("getCsrfAllowedRefererHosts failed.");n         return;n     }nn     if (isValidCsrfReferrer(req, allowedRefHosts)) {n         resp.getOutputStream().print("All CSRF checks passed.");n         //Add your code heren     } else {n         resp.getOutputStream().print("CSRF referrer checks FAIL.");n     }n }nnn public static boolean isValidCsrfReferrer(final HttpServletRequest req, final String[] allowedRefHost) {n     List allowedRefHostList = Arrays.asList(allowedRefHost);n     String referrer = req.getHeader(HttpHeaders.REFERER);n     String refHost = null;nn     URL refURL = null;n     try {n         refURL = new URL(referrer);n     } catch (Exception e) {n         return false;n     }n     refHost = refURL.getHost().toLowerCase();nn     return allowedRefHost != null && allowedRefHostList.contains(refHost);n }

Probando el CSRF

Para poder realizar la prueba, primero deberá obtener un ZM_AUTH_TOKEN válido y un token CSRF válido. La forma más fácil de obtenerlos es iniciar sesión en su servidor de prueba de Zimbra, en el navegador web, abra Developer Console (F12), vaya a la pestaña de red y cópielos/péguelos para usarlos con el curlcomando.

 

curlSolicitud de ejemplo :

curl 'https://zimbra.example.com/service/extension/mytest' \n     -X OPCIONES \n     -H 'X-Zimbra-Csrf-Token: 0_32786543c8a1da061a5294e011823dfe54e7030b' \n     -H 'Referente: https://zimbra.example.com/modern/email/Inbox/conversation/266' \n     -H 'Cookie: ZM_AUTH_TOKEN=0_78fe8ed6316247bbf0489b9443079e02462f36bf_69643d33363a373.....e302e305f47415f343137383b637372663d313a313b;'

 

Ahora puede cambiar los encabezados Referery para simular una solicitud maliciosa. También puede modificar  la cookie para probar la implementación de autenticación de su extensión.X-Zimbra-Csrf-Token
ZM_AUTH_TOKEN

Ir al Blog