Using Certificates For More Than Encryption
Encryption is everywhere. Whether communicating with users across the internet, making requests between internal microservices, or simply handling data at rest, encrypting all data and communications is becoming the standard in securing programs and services. And, as encryption becomes more common, the creation and distribution of certificates is becoming more common as well. Certificates, and by extension certificate authorities, are the cornerstone of modern encryption practices. They are used to provide the mathematical basis for performing encryption and decryption. Certificates typically come in two flavours, public and private, each containing a key. The key contained in a public certificate can be used to encrypt data and the key in a private certificate is used to decrypt data encrypted using the public certificate. However, in modern infrastructure certificates can be used for a lot more than just encryption and decryption. Address validation, user authentication and other functionality can also be provided by certificates, resulting in better security using a mechanism that most organizations will already have the skeleton of in place.
Use Certificates to Detect Malicious Websites
Most people familiar with SSL encryption will already be familiar with the most common type of certificate authentication, address authentication. This is the type of authentication performed by your web browser when it connects to a site and receives a public certificate to be used for encrypting communications. Whenever a service attempts to establish an SSL connection, it should perform address authentication. Authentication is performed by checking to see if the website’s address matches the Common Name on the certificate provided by the server. If the Common Name and address match, then the certificate is accepted for use in the encrypted connection.
While address authentication is pretty simplistic, it also provides a powerful mechanism for preventing spoofing. If you attempt to connect to google.com, and a malicious actor redirects you to google.bad.com, they are forced to provide a certificate. If the certificate states that it is from google.bad.com, then your web browser will prevent the connection, noting that you are connecting to google.com and the addresses don’t match. If they provide the certificate normally used by google.com, then your web browser will be happy, but since the spoofer doesn’t control the private certificate for google.com, they can’t decrypt the communications.
What happens if the spoofer creates a certificate with google.com, as it’s a common name? This would then defeat the validation mechanism, and since the spoofer created the certificate, they would be able to decrypt communications encrypted with it. Fortunately, this is quite hard to do effectively. While anyone can create a certificate with any common name, web browsers will only trust certificates created by trustworthy entities called Certification Authorities.
A Certification Authority performs due diligence to ensure that when a certificate is issued with a Common Name, it is only issued to the owner of the address that the Common Name is associated with. Similarly, if a certificate is stolen or erroneously issued, the Certificate Authority is responsible for revoking the certificate. Certificate Authorities tag certificates created by themselves with additional cryptographic information, which can be used to verify that the certificate was created by the authority. They do this by including their public signing certificate in the issued certificate, known as creating a certificate chain. These certificate chains may contain only a single signing authority’s information, or they may include many signing certificates. In this way, a certificate authority can imbue another organization with the ability to sign certificates on its behalf. The lower-level authority signs certificates including both it’s signature and the higher-level authorities signature, signaling that the entire chain of certificates is trustworthy.
Use Certificates to Prevent Internal Service Spoofing
This system works well for online services and results in fairly strong anti-spoofing prevention for users and their web browsers, but things get more complicated when we begin to talk about service-to-service communications. In these communications, internal services make requests of one another, and certificates must be provided in a fashion similar to web requests. Challenges begin to arise when there are many instances of a service. When there are many instances of a service and when services can be spun up and down, it may not be practical to issue certificates using a Common Name containing a web address. Instead, the Common Name is typically the IP address of the server endpoint, and as services are spun up and shut down, an internal certificate authority issues services certificates. These internal certificates are typically not useful for validation by users outside the network since the certification authority is unlikely to be trusted by outside users, but they are useful for internally verifying service endpoints aren’t getting spoofed and for encrypting communications.
Use Certificates to Prevent Request Spoofing
When we control both the Certification Authority and all the services, we can use certificates for a lot more than just address authentication. The simplest improvement we can make to our security is to provide client certificates as well as server certificates. While a server certificate is useful for verifying that a service is connecting to the expected endpoint, it does nothing to prevent bad actors from within the network connecting to the server endpoint. Arguably this sort of client request spoofing is much easier to execute and can be much more dangerous. Server spoofing allows an attacker to control what a client sees but client spoofing allows a malicious attacker to request data or make changes to stored data.
Client certificates work by having a client provide an encryption certificate during the connection phase, typically after verifying the server’s certificate. This client certificate contains the Common Name of the client, typically the address to the client is connecting to the server. The server can then verify that the client has provided a certificate proving that it is who it claims to be. Because certificates are distributed by a central certificate authority, the server can verify the certificate is valid by testing to see if it was provided by the certificate authority. Using this simple scheme, we can greatly increase bad actors’ difficulty in making requests within the network. Without the proper client certificate distributed by the certificate authority, bad actors will simply be unable to make requests.
Do More Than Just Prevent Spoofing
With both client and server certificate validation, it is almost impossible to attack microservices via spoofing. However, there is another type of attack originating from inside the network that certificate validation can not prevent. Malicious services, making unauthorized or just badly formed requests, can make valid requests from the other services’ point of view because they have valid client certificates. These types of attacks are much more difficult to prevent and, unfortunately, are becoming much more prevalent. As the number of internal services, internal users, and third-party integrations grows the likelihood of attacks originating not only from within the network but from within internally validated services grows as well.
The standard approach to stopping these types of attacks is using credentials. For example, a user using an authorized service to make a database request would typically need credentials to prove that they are allowed to access the database. However, managing credentials among services is quite a complex problem. Credentials require an application-level mechanism that services need to be aware of, different services are liable to have different mechanisms for validating credentials, and as microservices are spun up and spun down, we need a secure way of informing them of what credentials they should be using.
Fortunately, modern infrastructure can use certificates to handle this authentication issue rather than forcing us to manage credentials for all our services. This can be done by having a service’s credentials included in it’s client certificate. When a service makes a request, these credentials can be checked to see if the request is allowed. These credentials are typically just a service name. No password is required since the certificate itself is the password. Since the certificates are issued by the Certificate Authority, and since we trust the Certificate Authority to validate that the service is who it claims to be for us when we receive a certificate with a claimed service name, we can safely assume that the named service is the one making the request.
To determine which services are allowed to connect with each other, we provide an access control list. This list details which services are allowed to make requests and what types of requests they are allowed to make. When a request is made, the server can quickly consult this list to determine if the request should be processed or not. Access control lists also conveniently centralize the access control for any single service. This means we do not have to maintain separate authentication lists on each application instance or rely on varying authentication mechanisms implemented by different services. This single authentication mechanism can be used to handle all the authentication between services.
Building Certificate Authentication Systems
While building this type of authentication system might sound complicated, in practice, modern infrastructure deployment tools have made it relatively easy. The standard implementation has each service expose a proxy service rather than it’s own endpoints. These proxy services then perform all the encryption and authentication. When a request comes in, the proxy handles validating that the request comes from a trusted client and that the client is authorized to make the specific request. The proxy service then terminates unauthenticated requests or forwards them to the service it is proxying, as well as forwarding responses back from the proxied service to the requesting service.
As is shown in the diagram, the key to this type of authentication is the deployment of an authenticating proxy service for each service. In modern microservice deployments, this authenticating proxy service, or a set of services providing this functionality, can be deployed as a sidecar to the main service. These sidecar services are deployed in a shared container with the main service. We do not have to worry about communications between these sidecar services and their main service since the communications are contained within the container, where they can not be rerouted or observed. The advantage of this setup with a proxy service is that the main service does not need to know anything about the authentication scheme. We can then manage our authentication scheme via a completely separate mechanism. No library integration between our main services and our encryption and authentication system is needed.
Creating an Authentication Tech Stack
There are several tech stacks available for implementing certificate-based authorization. One common one, OPA – Envoy – SPIRE, works by providing a different service for each piece of the authentication process. Envoy provides encryption and proxy services, validating incoming client certificates and forwarding them to OPA for authentication. OPA handles the actual authentication process, checking the certificate’s information against an access control list to determine if the request should be allowed or not. A central bundle server is used to manage access control lists in OPA so that each instance does not need it’s own list, simplifying spinning up new instances. Finally, SPIRE sits above OPA and Envoy, providing certificates as the certificate authority. When a new instance is spun up, SPIRE distributes a certificate containing the new instance’s client authentication and encryption information.
As we can see, certificates can be used for a lot more than just providing basic encryption. Certificates can significantly increase the difficulty of spoofing both server endpoints and client requests by providing information for validating connections. In addition, authorization information can be contained within certificates. This reduces the need for per-service authentication schemes and makes service authentication much simpler. As encryption becomes more common between internal services organizations, they need to consider what types of authentication they need and choose a scheme and certificate authority that fits their needs. As services move toward the cloud, certificates and certification authorities can provide a lot more functionality than simple encryption. The best part, with many tech stacks, this type of functionality can be provided automatically, ensuring good security practices in cloud architectures.
Next, see my previous blog post, Zero-Trust Authentication: What It Is and Why It Matters, or contact us for more.
References
Read more about OPA Authorization with Envoy and X.509 SVIDs, SPIFFE.