
CVE-2022-22954 analyste
Workspace ONE Access (modèle de fourniture d'espace de travail en tant que service) propose l'authentification multifacteur, l'authentification unique (SSO) et l'accès conditionnel pour les SaaS, les applications web et mobiles. CVE-2022-22954 est une vulnérabilité d'injection de modèles côté serveur (Server-side Template Injection) présente sur les produits suivants :
Téléchargez le fichier ova de l'appliance VMware Workspace ONE Access version 21.08.0.1
Ouvrez le fichier avec VMware Workstation, la machine virtuelle doit être placée sur le réseau NAT
Dans Networking Properties, configurez le Host Name (FQDN)

Une fois l'installation terminée, accédez au chemin https://{{hostname}}:8443/ pour configurer le mot de passe du compte applicatif, le mot de passe du compte ssh et la base de données de l'application. L'application s'exécute sur https://{{hostname}}/

Connectez-vous à la machine virtuelle avec le compte sshuser, puis passez au compte root. L'application se trouve dans /opt/vmware/horizon/workspace/. Le code source de l'application se trouve dans le dossier /opt/vmware/horizon/workspacce/webapps

Vérifiez le fichier /opt/vmware/horizon/workspace/bin/setenv.sh, on constate que la variable JAVA_OPTS peut être configurée pour le débogage à distance (remote debug)

Ajoutez -agentlib:jdwp=transport=dt_socket,server=y,address=5005,suspend=n à JAVA_OPTS et redémarrez le service
`systemctl restart horizon-workspace.service`
Téléchargez le fichier hotfix HW-154129-applyWorkaround.py
Parmi les étapes, l'une d'elles consiste à supprimer le fichier templates/customError.ftl de l'application

Dans le fichier customError.ftl, il existe une fonction eval. La faille Freemarker SSTI peut être exploitée à partir d'ici si l'on peut contrôler la valeur de errorObj.


Dans la classe com.vmware.enusercatalog.ui.web.UiErrorController, on voit que la fonction handleGenericError affecte une valeur à errorObj via la variable errorMessage

Continuons à suivre les appels de fonctions et le paramètre errorMessage
Fonction handleUnauthorizedError

Fonction getErrorPage

Dans les deux fonctions sendError et sendUnhandledError, la valeur de errorMessage est extraite de la propriété javax.servlet.error.message


Dans la classe com.vmware.endusercatalog.ui.web.UiApplicationExceptionResolver, la propriété javax.servlet.error.message reçoit sa valeur dans la fonction resolverExeption

La fonction handleAnyGenericExeption est annotée @ExeptionHandler

Dans la classe com.vmware.endusercatalog.ui.UiApplication, les packages annotés @CommponentScan incluent com.vmware.endusercatalog.auth

=> Les exceptions de ce package peuvent être interceptées par la fonction handleAnyGenericExeption
Dans com.vmware.endusercatalog.ui.config, l'intercepteur AuthContextPopilationInterceptor est ajouté pour les chemins /ui, /hub-ui, /hub-ui/byob, /logout, /ui/oauth/verify


En se dirigeant vers la classe com.vmware.endusercatalog.auth.interceptor.AuthContextPopulationInterceptor, dans la fonction preHandle, l'application reçoit 2 paramètres deviceUdid et deviceType et appelle la fonction authContextBuilder

Dans la classe com.vmware.endusercatalog.auth.interceptor.AuthContext, l'exception InvalidAuthContextException est levée si la condition this.isValidRequest n'est pas satisfaite


Pour que isValidRequest soit satisfaite, les 2 paramètres this.deviceId et this.deviceType doivent être tous deux vides ou tous deux renseignés

=> ne transmettre une valeur qu'à l'un des 2 paramètres provoque une erreur ici

Envoyez la requête
GET /catalog-portal/ui/oauth/verify?deviceUdid=111
une erreur apparaît
An unexpected error occurred while processing request with requestId: {0}.
En revenant à la fonction com.vmware.endusercatalog.ui.web.WorkspaceOauth2CodeVerificationController, on constate que l'erreur ci-dessus apparaît en raison du paramètre requis error manquant
@GetMapping(
value = {"/ui/oauth/verify"},
params = {"error"}
)
@ApiOperation(
value = "authorizeError",
notes = ""
)
public void authorizeError(@ApiParam @RequestParam String error, @ApiParam @RequestParam(name = "error_description") String errorDescription, @ApiParam @RequestParam(defaultValue = "/admin/") String state) {
LOGGER.debug("Failed to obtain authorization code due to {}:{} received for {}", new Object[]{error, errorDescription, state});
throw new AuthorizationCodeFailedRetrievalException(new Object[]{error, state});
}
Renvoyez la requête
GET /catalog-portal/ui/oauth/verify?error=&deviceUdid=111abc
la valeur de deviceUdid apparaît dans la réponse

Insérez le paramètre déclenchant la faille SSTI de Freemarker

Envoyez la requête avec la valeur
deviceUdid=${"freemarker.template.utility.Execute"?new()("cat /etc/passwd")}

