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:
- 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 as7995
and7996
. - Insecure internal services exposed via GFIAgent – The
GFIAgent
service exposes multiple HTTP services across ports7994
to7997
. 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.
- 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
and7996
do not require authentication for interaction. Specifically, port7996
only requires an Appliance ID (UUID), which can be retrieved without authentication via the endpoint on port7995
. Unlike other internal services, theGFIAgent
server on port7996
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 port7996
Because of this, the more reliable and common path to reach the unauthenticated interface on port7996
is through the default-enabled non-transparent proxy on port3128
.
Server Proxy Permit Access to GFIAgent
Server Proxy Permit Access to GFIAgent | |
---|---|
Vulnerable Asset | service: winroute | port: 3128 |
CWE | CWE-441: Unintended Proxy or Intermediary (‘Confused Deputy’) |
Precondition | Reaching the non-transparent proxy server on the TCP port where it is exposed. |
Short Description | The proxy server allows the forwarding of HTTP requests to internal or non-exposed services of KerioControl, bypassing firewall rules and enabling authentication bypass |
Impact | Access 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 Asset | service: GFIAgent | port: 7995, 7996 |
CWE | CWE-306: Missing Authentication for Critical Function |
Precondition | Access to ports 7995 or 7996 (directly or via proxy) |
Short Description | The 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/* ). |
Impact | Authentication 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
- Retrieving of appliance Id:
curl http://localhost:7995/appliances --proxy http://192.168.234.128:3128/
- 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 port3128
.
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 Asset | service: winroute |
CWE | CWE-345: Insufficient Verification of Data Authenticity |
Precondition | The ability to upload the system image to perform a system upgrade, with access to the administrative web portal. |
Short Description | The 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. |
Impact | Allows 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
- Decompress
kerio-control-upgrade-9.4.5-8526-linux.img
filegzip -d kerio-control-upgrade-9.4.5-8526-linux.img --suffix=.img
- Extract content of TAR archive
tar -xvf kerio-control-upgrade-9.4.5-8526-linux
- Modify the content of
upgrade.sh
script for example. - Remove the original
upgrade.sh
scripttar --delete -f kerio-control-upgrade-9.4.5-8526-linux upgrade.sh
- Add the modified
upgrade.sh
script to tar archivetar -rf kerio-control-upgrade-9.4.5-8526-linux upgrade.sh
- 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
- Upload and start upgrade of modified img file
- Confirm on the KerioControl appliance the correct execution of added code.
Exploit
- 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 tohttp://localhost:8084/admin/
. - 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
- https://ssd-disclosure.com/ssd-advisory-kerio-control-authentication-bypass-and-rce - [SSD Secure Disclosure Advisory]
- https://cwe.mitre.org/data/definitions/306.html – [CWE-306]
- https://cwe.mitre.org/data/definitions/345.html – [CWE-345]
- https://cwe.mitre.org/data/definitions/441.html – [CWE-441]
- https://gfi.ai/products-and-solutions/network-security-solutions/keriocontrol – [Kerio Control Product Page]
- https://gfi.ai/it/appmanager – [GFI AppManager]
- http://download.kerio.com/archive/ – [Kerio Control Update Image Archive]
- https://cdn.kerio.com/dwn/control/control-9.4.5-8526/kerio-control-upgrade-9.4.5-8526-linux.img – [Original 9.4.5 Image File]