In Brief

An unauthenticated user can exploit a vulnerability in Kerio Control’s GFIAgent service by reaching ports (such as 7995 and 7996) via the default-enabled non-transparent proxy on port 3128, effectively bypassing authentication. The update mechanism then allows uploading a modified system image, ultimately leading to root access on the appliance.

Scenario

  • Analyzed Product: Kerio Control 9.4.5 - Download
  • Vulnerable Asset: GFIAgent and Software Update Functionality
  • Prerequisites: Reaching non-transparent proxy server
  • Privileges Required: No privileges are required

SSD Advisory

In Depth

The audit revealed a critical vulnerability chain in Kerio Control that allows an unauthenticated remote attacker to escalate to full root access. This chain is enabled by the default configuration of the system and by the absence of proper authentication checks in key services. The central component involved is the GFIAgent service.

what is GFIAgent?

GFIAgent is a software component bundled by default in Kerio Control appliances starting from version 9.4.3. Its primary purpose is to enable communication with the GFI AppManager, a cloud-based centralized management platform. Through GFIAgent, administrators can remotely monitor and manage the system, manage configurations, register appliances, and deploy software updates.

Vulnerability Chain Overview

The attack flow is made possible by the combination of the following three vulnerabilities:

  1. Exposed non-transparent proxy on port 3128 – A non-transparent HTTP proxy service listens on port 3128 and is enabled by default. While not inherently exposed to the internet, it becomes reachable if an ingress firewall rule allows traffic to it. Once accessible, it allows unauthenticated forwarding of HTTP requests to arbitrary internal services and ports, including normally non-public ones such as 7995 and 7996.
  2. Insecure internal services exposed via GFIAgent – The GFIAgent service exposes multiple HTTP services across ports 7994 to 7997. In particular:
    • Port 7995 serves unauthenticated requests that disclose internal metadata, including a unique agent identifier used in further API interactions.
    • Port 7996 registers a /proxy endpoint that blindly forwards incoming requests to the internal administrative interface (*:4081/admin/*), effectively bypassing authentication and exposing admin functionality to external users.
  3. Software update functionality – The administrative web-interface, includes an endpoint for uploading software update images. However, the update process does not verify the integrity or authenticity of the uploaded files. This allows an attacker to upload a crafted update image containing arbitrary code, which is then executed as root, resulting in full remote code execution.
flowchart TD
    A[Attacker] --> B{Access to proxy server port 3128?}
    B -- Yes --> C[Send HTTP requests via proxy to internal services]
    C --> D[Query GFIAgent on port 7995 for agent metadata]
    D --> E[Access /proxy on port 7996 to reach admin interface]
    E --> F[Trigger admin functionality via unauthenticated request]
    F --> G[Upload malicious update image]
    G --> H[Remote Code Execution as root]
    B -- No, but 7995/7996 exposed --> D

Note on Direct Exposure of GFIAgent

The web servers exposed on ports 7995 and 7996 do not require authentication for interaction. Specifically, port 7996 only requires an Appliance ID (UUID), which can be retrieved without authentication via the endpoint on port 7995. Unlike other internal services, the GFIAgent server on port 7996 is bound to all interfaces by default. This means that if the firewall configuration explicitly allows inbound traffic to this port, an attacker can bypass authentication directly, without needing to exploit additional vulnerabilities. However, such firewall rules are generally not required in typical Kerio Control deployments and are rarely configured. Internet-wide scans using tools like Shodan and Censys confirm that few Kerio Control appliances expose port 7996 Because of this, the more reliable and common path to reach the unauthenticated interface on port 7996 is through the default-enabled non-transparent proxy on port 3128.

Server Proxy Permit Access to GFIAgent

Server Proxy Permit Access to GFIAgent
Vulnerable Assetservice: winroute | port: 3128
CWECWE-441: Unintended Proxy or Intermediary (‘Confused Deputy’)
PreconditionReaching the non-transparent proxy server on the TCP port where it is exposed.
Short DescriptionThe proxy server allows the forwarding of HTTP requests to internal or non-exposed services of KerioControl, bypassing firewall rules and enabling authentication bypass
ImpactAccess to internal services and possibility to perform SSRF.

Description

By default, the initial configuration of Kerio Control enables the non-transparent proxy service, which is exposed on TCP port 3128. In order to interact properly with this service, appropriate firewall rules must be configured using the “Traffic Rules” functionality

The Proxy Server allows requests to be forwarded to internal services on the appliance’s localhost and/or other network interfaces.

Therefore, it is possible to force access to internal services through the proxy server, including the GFIAgent local service. (Local services can be accessed via 127.0.0.1, localhost, or control).

Proof of Concept

cURL

curl http://localhost:7995/appliances --proxy http://192.168.234.128:3128/

HTTP Request

GET http://control:7995/appliances HTTP/1.1
Host: 192.168.234.218
Connection: close
 
 

Missing Authentication in GFIAgent (RemoteServer)

Missing Authentication in GFIAgent (RemoteServer)
Vulnerable Assetservice: GFIAgent | port: 7995, 7996
CWECWE-306: Missing Authentication for Critical Function
PreconditionAccess to ports 7995 or 7996 (directly or via proxy)
Short DescriptionThe GFIAgent service, responsible for communication with GFI AppManager to remotely control the appliance (in the cloud), lacks adequate authentication, allowing unauthenticated execution of any request that can be performed via the administrative web portal (*:4081/admin/*).
ImpactAuthentication bypass, leading to RCE

Description

Analysis of the GoLang binary for the GFIAgent service revealed that requests handled on ports 7995 and 7996 do not implement any authentication mechanism. However, the service listening on port 7996 (github.com/trilogy-group/gfi-agent/servers.RemoteServe) requires the presence of the app-id header (a UUID identifying the appliance) within the requests. It is important to note that the value of this identifier can be easily retrieved through the :7995/appliances endpoint.

In detail, inspection the github.com/trilogy-group/gfi-agent/servers.(*RemoteServer).RegisterHandlers code it is possible to note a registration of /proxy path.

The logic of /proxy handler is implemented in github.com/trilogy-group/gfi-agent/servers.(*RemoteServer).RedirectToAppServer, which, to semplify, forwards incoming requests to the *:4081/admin/ endpoint. Allowing calls to, for example: admin/api/scim/v2/Users, /admin/api/jsonrpc/ ecc…

This configuration effectively allows external users with access to ports 7995 or 7996 of the GFIAgent service to issue requests to the appliance with administrative privileges, bypassing authentication entirely.

It is important to note that many other endpoints within the GFIAgent service enable administrative actions, though they are not covered in this document. For instance, it might be possible to deregister the appliance (if already registered with AppManager) using the :7995/register-cancel endpoint. Additionally, the :7995/register endpoint could allow retrieval of the public key or, more broadly, the URL required to register the appliance with a GFI AppManager account.

Proof of Concept

  1. Retrieving of appliance Id:
    curl http://localhost:7995/appliances --proxy http://192.168.234.128:3128/
  2. Make administrative requests in unauthenticated manner:
    curl http://192.168.234.128:7996/proxy/admin/ -H 'app-id: <ApplianceId>'

TITLE

To reproduce the request as described, you need to ensure that an inbound rule is added for port 7996, exposing it on all interfaces. Alternatively, you can proxy the request through port 3128.

POST /proxy/admin/api/jsonrpc/ HTTP/1.1
Host: 192.168.234.128
Connection: Close
Content-Length: 162
app-id: <ApplianceId>
 
{"jsonrpc":"2.0","id":1,"method":"Users.get","params":{"query":{"start":0,"limit":-1,"orderBy":[{"columnName":"userName","direction":"Asc"}]},"domainId":"local"}}

Missing Validation of System Image during Upgrade

Missing Validation of System Image during Upgrade
Vulnerable Assetservice: winroute
CWECWE-345: Insufficient Verification of Data Authenticity
PreconditionThe ability to upload the system image to perform a system upgrade, with access to the administrative web portal.
Short DescriptionThe system does not adequately verify the authenticity and integrity of the uploaded image during appliance upgrades, potentially allowing the upload of a tampered or modified image.
ImpactAllows modification of the system, resulting in root-level access.

Description

The Kerio Control appliance upgrade functionality allows the upload of modified system images.

It is possible to retrieve the original upgrade image from: http://download.kerio.com/archive/ - https://cdn.kerio.com/dwn/control/control-9.4.5-8526/kerio-control-upgrade-9.4.5-8526-linux.img.

The downloaded *.img file is a compressed gzip POSIX TAR file. The TAR file contains configuration files and the upgrade script (upgrade.sh), the disk image (part2.img), and GRUB components.

Proof of Concept

  1. Decompress kerio-control-upgrade-9.4.5-8526-linux.img file
    gzip -d kerio-control-upgrade-9.4.5-8526-linux.img --suffix=.img
  2. Extract content of TAR archive
    tar -xvf kerio-control-upgrade-9.4.5-8526-linux
  3. Modify the content of upgrade.sh script for example.
  4. Remove the original upgrade.sh script
    tar --delete -f kerio-control-upgrade-9.4.5-8526-linux upgrade.sh
  5. Add the modified upgrade.shscript to tar archive
    tar -rf kerio-control-upgrade-9.4.5-8526-linux upgrade.sh
  6. Recompress the TAR archive with gzip
    gzip -c kerio-control-upgrade-9.4.5-8526-linux > kerio-control-upgrade-9.4.5-8526-linux_modfied.img
  7. Upload and start upgrade of modified img file
  8. Confirm on the KerioControl appliance the correct execution of added code.

Exploit

  1. CAP001: Start a server on the localhost at port 8084 that automatically forwards requests to the proxy, which in turn forwards them to the GFIAgent service. This allows unauthenticated access to the appliance by navigating to http://localhost:8084/admin/.
  2. CAP002: Create a modified image (the original image file must be placed in the root folder of the code). The code will handle the creation of the modified image by altering the upgrade script: upgrade.sh.`

Note

In the provided example, the upgrade script (upgrade.sh) was modified in a simple and obvious way purely for demonstration purposes and to make the change visually clear. The better approach would be to insert a small backdoor inside the disk image and invoke it during the initialization process.

References