One of the most complex yet effective methods of gaining unauthorized access to corporate network resources is an attack using forged certificates. Attackers create such certificates to fool the Key Distribution Center (KDC) into granting access to the target company’s network. An example of such an attack is the Shadow Credentials technique, which lets an attacker sign in under a user account by modifying the victim’s msDS-KeyCredentialLink attribute and adding an authorization certificate to it. Such attacks are difficult to detect because, instead of stealing credentials, the cybercriminals use legitimate Active Directory (AD) mechanisms and configuration flaws.
Nevertheless, it is possible (and necessary) to counter attacks that use forged certificates. Having analyzed the practical experience of our MDR service, I identified several signs of such attacks inside the network and developed a Proof-of-Concept utility capable of finding artifacts in AD, as well as a number of detection logic rules that can be added to SIEM. But first a few words about the quirks of certificate-based Kerberos authentication.
In modern corporate networks based on Active Directory, resource management is performed by the Kerberos protocol. Users can access any service (object) inside the network only if they can provide this object with a ticket issued by the KDC (Msg E in the figure below). The KDC component that issues service tickets is called the Ticket Granting Server (TGS). Moreover, the user receives a TGS ticket from the KDC only if they have a Ticket Granting Ticket (TGT) (Msg B in the figure below). Essentially, a TGT is proof of successful user authentication, usually by password.
Kerberos authentication scheme. Source: https://en.wikipedia.org/wiki/Kerberos_(protocol)
However, there is a way to get a TGT without knowing the password — using a certificate. For this to work, the KDC must trust the provided certificate, and the certificate must relate to the subject requested in the TGT. This part of Kerberos, called Public Key Cryptography for Initial Authentication (PKINIT), makes it quite easy to set up authentication if there is a (Certificate Authority) in the corporate network that issues certificates for domain users. But there is an alternative way.
For example, to take advantage of Microsoft Hello for Business features, such as PIN-based authorization or face recognition, the device from which you’re signing in must have its own certificate in AD so that the KDC can issue a TGT based on this certificate. However, not all networks with Active Directory have a Certificate Authority. This is the reason for inventing the msDS-KeyCredentialLink attribute, where the certificate can be written. The KDC will trust this certificate and issue a TGT. That’s a really good solution that extends the capabilities of Microsoft Active Directory.
However, based on the above logic, the subject that writes the msDS-KeyCredentialLink attribute to some object will also be able to get a ticket for this object. Therein lies the problem.
Let’s illustrate one of the possible attack scenarios:
Let’s focus not on how to get the KDC to trust a particular certificate, including stolen or forged ones, but on what happens when the TGT is issued. This triggers Event 4768 on the domain controller: A Kerberos authentication ticket (TGT) was requested. This event may contain artifacts from the certificate used for authentication, with three fields: CertIssuerName, CertSerialNumber and CertThumbprint. These fields are what we’ll look at.
For simplicity and convenience, we’ll handle all events in the Kibana interface of the ELK cluster. By default, Logstash actually knows how to convert the bit fields of Event 4768 into an array of values specific to a ticket in the list. This also makes the search much faster and smoother. I recommend using the handy set of Docker configurations to get your ELK lab up and running quickly. Plus the official WinLogBeat setup guide.
On the test bench we created several TGT request events based on a forged certificate that we generated using Whisker. Here’s what these events look like in the test environment:
Within the framework of the MDR service, we observe several hundred thousand certificate-based ticket request events a week. On their basis, we can use this fairly broad sample to identify some patterns:
CertIssuerName.raw:/S\-1\-(5\-21|12\-1)\-([0-9]{8,10}\-){3}[0-9]{4,10}\/[a-f0-9]{8}\-([a-f0-9]{4}\-){3}[a-f0-9]{12}\/login\.windows\.net\/[a-f0-9]{8}\-([a-f0-9]{4}\-){3}[a-f0-9]{12}.*/
CertIssuerName.raw:CN=* AND CertSerialNumber.raw:01
CertSerialNumber.raw:/[a-f0-9]{32}/ AND CertThumbprint.raw:/[a-f0-9]{40}/
CertSerialNumber.raw:/[a-f0-9]{38}/ AND CertThumbprint.raw:/[a-f0-9]{40}/
Using real data, let’s see what queries we can filter out. For this, we can build the following aggregation using the regular expressions described above:
Aggregation of certificate-based ticket request events in the Kaspersky MDR service
Take a look at the “Rest” line, which contains the remaining unfiltered events (13 of them), shown in detail. Pay attention to the CertIssuerName field; see the details below.
Expanded list of unfiltered certificate-based ticket request events
As I mentioned, in our example the certificate was generated in the Whisker utility itself with default parameters. See here for a description of the procedure for generating a self-signed certificate.
As we can see, Whisker tries to pass of its certificates as Windows Hello for Business certificates (in the case of programmatic generation, a key pair). However, the original certificates (when a Windows PC independently generated a certificate to use this functionality) contain an error: the Distinguished Name (DA) notation in the CertIssuerName field uses the format “CN=…”. The attackers’ toolkit is free of this error, which is suspicious. The second and third lines can be compared with the data from the test bench, but in the MDR product system (also see below).
We can add a Painless script directly to Kibana that finds all 4768 events resulting from case-insensitive matches between CertIssuerName and TargetAccountName.
{ "query": { "bool": { "filter": { "script": { "script": { "lang": "painless", "source": "doc['CertIssuerName.raw'].value.equals(doc['TargetAccountName.raw'].value.toLowerCase())" } } } } } } |
There are ten such events, all of which relate to the use of the Whisker utility.
Now let’s consider the winlog.event_data.TicketOptionsDescription field in events from the test bench over an arbitrary time interval during which both forged and legitimate TGT requests occur.
What’s striking is the absence of the name-canonicalize flag, which plays an important role in the Kerberos infrastructure. The thing is that a service or account can have multiple primary names. For example, if a host is known by multiple names, services based on it may have multiple Service Principal Names (SPNs). To relieve the client of having to request a ticket for each name, the KDC can provide it with mapping information during the credential retrieval process. This functionality is requested when the name-canonicalize flag is enabled. If the “canonicalize” option is set, the KDC can modify the names and SPNs of both the client and the server in the response and the TGT. But in our case this flag is missing, which, as mentioned, is suspicious. Let’s find all tickets without this flag but requested using PKINIT (certificate-based). We create a request based on Kaspersky MDR product data.
The result, as we see, is Whisker + Rubeus activity (for the last 30 days) on our bench (AD-Gam host) and the work of my colleague (the others) in testing a group of vulnerabilities in the AD CS settings, which we combined under the general name ADCS ESC or Certified Pre-Owned. In addition, there is one false positive filtered by certificate name and one incident sent to the client. That’s not a bad conversion.
Let’s look at the example of Rubeus to see why the name-canonicalize flag is not set in ticket requests.
It turns out that Rubeus does not set this flag on purpose. Likewise with Impacket, the de facto standard toolkit for security analysts who work with Kerberos (and not only). This explains why our search for flagless tickets also turned up the work of my colleague, who tested ESC techniques (using a toolkit based on Impacket). Such utilities are plentiful due to the simplicity of the code and the popularity of the language.
We can compare two attributes: one set legitimately during Hello for Business configuration, the other set by Whisker. There is a difference between them. When comparing these attributes, I in fact wrote a tool that lets you find artifacts from an illegitimate attribute setting, for example, as a result of using Whisker.
You can download and use this utility yourself in the development environment; when debugging, try to find and compare the key differences in the “good” and “bad” attributes.
Things to pay attention to:
The above-described attacks are relatively effective, but they can be detected when a forged certificate is used. Knowledge of the infrastructure (ideally including a list of all active keys) and monitoring will assist the security expert in this. Also of great help is the ability to spot common patterns and artifacts of attacks using forged certificates, and my utility will simplify the search process.