Security is one of the most important responsibilities for owners of online applications. I once launched a WordPress site and within minutes I was getting security alerts about someone trying to attack the login page. Malicious individuals and bots are constantly on the prowl, waiting to take advantage of any security vulnerabilities present in a system. We all need to stay ahead of attackers by fixing and guarding the loopholes in our systems.
In this piece, we will go through what I believe are the top 5 steps for securing your webhooks. We'll look at strategies that help block the most common and most dangerous loopholes, where attackers look to take advantage of your webhooks.
How webhooks work
Webhook communication is achieved by sending an HTTP request from a source application to a destination application. When an event takes place in the source application, an HTTP request which might contain data relating to the event is triggered. This HTTP request is sent to the destination application's endpoint. This is the endpoint, submitted by the destination application to the source application, for webhook requests to be sent to. The endpoint is often referred to as the webhook URL.
Webhook requests can be sent using the POST or GET request methods. This depends on the webhook provider's preferences — the information on how to consume the requests is always available on the provider's documentation.
A 5-step security checklist
Security issues affect us all, and you don't have to be a security expert to begin taking steps to secure your webhooks against malicious attacks. Below are the threats and solutions you should be aware of when working with webhooks.
Now that we have this information, let's dig deeper into each of the steps you should be taking right away to ensure your webhooks are protected.
1) Encrypt all data
Webhook requests are regular HTTP requests, and HTTP is a plain-text protocol. This means that all information transmitted from source to destination during a webhook request is clearly visible and readable.
Attackers can easily intercept these messages and take advantage of any sensitive information contained in them, such as user data or authentication tokens.
You may not be able to completely prevent the visibility of the messages, but you can prevent their readability. This is done by making sure that all communication occurs over the secure HTTP protocol, HTTPS.
You can achieve this by installing an SSL Certificate on the client and providing a secure webhook URL. This provides security at the transport layer, ensuring that all data sent is encrypted and therefore cannot be read.
2) Verify the source
A webhook URL is an endpoint on the client's API. This endpoint is publicly available and because of this, it can be called from any application. As a webhooks receiver, you want to verify that requests hitting your endpoint are coming from the right source.
If there is no mechanism to verify the source, attackers can easily send malicious requests well-crafted to wreak havoc on your system. For example, payloads that can cause SQL injection can be fed into your endpoint to attack your database and either expose or delete important data.
If you're a webhook provider, you want to help your clients verify you. One of the strategies you can use is to include an authentication token in a header in the webhook request. Your client will also know this token and will check for it in the headers of any received request.
Another way to verify the source is for the client to be aware of the webhook provider's IP address. The client can then whitelist this IP address and bounce any other request coming from unknown IP addresses.
3) Verify the consumer
As a webhook provider, another security measure you want to take is to verify your consumers.
Attackers can always intercept webhook requests and route them to different destinations in order to take advantage of the data being transmitted.
One way to achieve client verification is to make use of Mutual TLS. In a regular TLS setup, only the client gets to verify/authenticate the server.
With Mutual TLS, both the client (your API endpoint) and server (the webhook provider) get to verify one another. They both present a certificate during the TLS handshake which helps to mutually prove their identities.
This way, even if the webhook request is redirected to a malicious destination, the authentication will fail as the client will not be able to receive the information contained within the request.
4) Verify the message
So you have received your webhook request and the information contained within, but how can you be sure the information you received is correct?
Attackers can intercept a request and feed it with the wrong payload before it hits your endpoint. This way, even if the message is encrypted, it contains what they (the attackers) want you to see.
This provides another loophole for attackers to transmit corrupt information into your system.
One very effective way to verify that messages are legitimate is for both the webhook provider and client to perform signature verification on the messages.
The webhook provider sends a plain message along with a signature generated using the message and the HMAC cryptography algorithm to the client. When the client receives the message, it uses the HMAC algorithm and the message received to deduce its signature.
It then compares the deduced signature with that sent by the webhook provider. If the signatures match, the message is valid. If not, the message has been tampered with and should be rejected.
Stripe uses this strategy by sending the signature in a Stripe-Signature header in its webhook requests.
5) Prevent replay attacks
Even with the message verification signatures in place, attackers can still find their way into your system using a strategy known as replay attacks. In this type of attack, a malicious agent intercepts both the message and its signature and retransmits it by itself.
This gives the attacker the ability to act as the source of the webhook request when the request is retransmitted. Think of it like identity theft, where another person can act as you because they got ahold of your social security number or credit card.
The most effective way to prevent this is to add a timestamp to the payload that is used to create the signature. The attacker cannot change the timestamp without invalidating the signature.
If the attacker tries to change the timestamp, your message verification setup will detect that the signature is incorrect.
To effectively take advantage of this strategy, ensure that your server's clock synchronizes with that of the webhook provider using the Network Time Protocol (NTP).
Stripe uses this strategy by including the timestamp in the signed payload, thus the timestamp is also verified by the signature.
There is nothing like 100% security. Even the biggest firms with the largest budgets are still researching new ways to be secure against the majority of attacks. However, keep in mind that attacks are also not cheap to launch as attackers also have to invest in infrastructure to penetrate the most secure networks in order to steal information or cause damage. That said, with certain checks in place, you are sure to be protected from most of the common yet deadly attacks that can be launched against your system.