Basic attacks on communication protocols – replay and reflection attacks
tl;dr: will review the basic concepts of replay and reflection attacks.
Those with familiarity of blockchain forks will have no doubt heard of “replay attacks”. This is where one transaction sent on a chain can be resent on the forked chain. However, from a definition perspective I am debating whether it is replay attack or a reflection attack. I think that they look like reflection attacks as much as replay attacks. In a series of two articles I will present an explanation of what the two attack types are, my reasoning for saying it feels like a reflection attack, and my fears about the proposed fixes.
In this article I will recap the basic concepts of network security as it pertains to replay and reflection attacks. This is the same thing you will be taught on a university course about network security. It isn’t particularly difficult to understand but those of a less technical background may find it a bit dull. I won't be able to cover all details here but hopefully enough to give a basic understanding.
In the next article I will outline my thinking about how those attacks specifically affect current and future blockchains (including my fears for multi-chain environments, e.g. Polkadot; FYI, it does have some sort of protection).
Network Security: Replay Attacks
The idea of preventing replay attacks is to ensure a notion of freshness: that the message you’ve just received hasn’t been seen before.
There are a couple of ways that you could think about doing this:
Just use a simple index value which increases with each message. These are known as sequence numbers and feature in TCP. It sounds like a reasonable fix but has a well-known attack which means it is an ineffective protection mechanism.
Include a single-use random value (a nonce) in each message and disregard any duplicates. Random values can’t be guessed, and if they are unique, then you have good reason to believe the message is “genuine” (caveat: you don’t know the identity of the sender just from a nonce). Fresh is a better word than genuine, but I’m trying to make this article digestible by newbies too.
Example of a TCP exchange showing sequence numbers
Sequence numbers
A simple but ultimately ineffective way to prevent replay is to number every message with a sequence of numbers and discard any that you’ve seen before. If you receive 10 messages and they are all numbered 1-10 then you can discard any duplicates which come in with the same number.
This is a necessary part of many networking protocols (e.g. TCP); however, it is ineffective as a security mechanism. In the simplest case there is a race condition to see who can send a message the quickest and hence appear as the original message: e.g. the first message to arrive labelled with a “3” would appear to be the correct message for that number, but being first to arrive doesn’t necessarily mean it isn’t malicious. Hence, there is a race to arrive first and be accepted.
Making the starting point of the sequence unpredictable (e.g. a large random number) helps but it doesn’t provide cryptographic-strength protection (i.e. can’t be faked). If you want to read about a good example of predicting sequence numbers then read about the Kevin Mitnick (scroll down to step 1).
Nonces: single-use random values
The inclusion of a random value (a value which has no predictable sequence) essentially guarantees that a message has not been seen before (provided it is only used once). This is provided that the value is kept secret while in transit (i.e. encrypted).
Cryptographic Nonce @ Wikipedia
If I send you a message which is encrypted with a random value inside it and you agree only to accept that message and to disregard any message in the future which somehow have the same random value then replaying old messages is impossible (read: computational infeasible).
However, I could send my original message to another person and use the same nonce. They won’t have seen the nonce before so my message will appear as valid. This isn’t good practice but it is certainly possible.
From this you should see a resemblance to the current blockchain replay attacks: yes the transactions are signed, but the transaction can be replayed on a different network and one of the participants may be none-the-wiser. More on that in the next article!
In the real world, protocols use nonces which are sufficiently large such that repeated use is improbable within a given timeframe. The more bits the value has the less likely it is to repeat (caveat: provided we also have a sufficient source of randomness).
Example of a challenge-response protocol with exchange of nonce values. Discussion below.
Challenge-Response protocols
Ideally, in an exchange of messages you would want to be sure that you know who the other participant is and likewise for them. Ideally, both participants would mutually authenticate each other although that doesn’t always happen in practice.
In a challenge-response protocol you send an encrypted random value to the other participant and they reply with that same value but re-encrypted with a different key. Provided both participants have knowledge of the keys used then it is clear that both participants have access to the same secret key and hence gain confidence that the other participant should be who they say they are.
Moreover, you’d know that the exchange of messages is fresh. I’ve skipped a lot of details here but hopefully the point is clear. :-) My proposition for fixing the supposed replay attacks on blockchain forks would be to implement something similar (more details in the next article).
Network Security: Reflection Attacks
Simple challenge-response mechanisms are not invulnerable though and may be attacked via a reflection attack.
The following is a simple example of a reflection attack. I’ve taken some of the explanation from a reply on stack exchange (with some modifications). I will run through the non-malicious example first: i.e. a protocol run in the absence of an attacker.
Non-malicious challenge-response example
Example exchange of messages where Alice and Bob are communicating. Alice sends a nonce (random value to Bob) and Bob replies with an encrypted value containing the nonce (we assume Bob and Alice have a shared key):
- Alice -> Bob: nonce <-- challenge
- Bob -> Alice: E(K, nonce) <-- response (the nonce is encrypted with key K)
Great. So the received value must have come from Bob, right? The nonce is decrypted and checks out so it would appear that everything is fine. Alice agrees that the encrypted nonce is the one she sent. If Bob sent the message again then Alice should ignore it (in theory).
Current blockchain protocols don’t use challenge response which is part of the reason I fear that so-called replay attacks can exist. Albeit the replay requires a valid transaction to first occur on the original chain before it is replayed on the new chain.
Example of a simple challenge-response protocol
Malicious challenge-response example
However, let’s pretend that there is a rogue person (Mallory) who is for lack of a better explanation between the other two participants. The attack explained here is known as a man-in-the-middle attack which is part of the reason we say Mallory is between Alice and Bob.
Alice is trying to send out a nonce to Bob, but it is unknowingly intercepted by Mallory. He then sends this to Bob while pretending to be Alice. I appreciate this may sound unlikely and that a human could easily see the difference but you have to remember that when two automated systems are communicating with each other they can other see what they are programmed to see. A simple protocol will fail because it is simple; it doesn’t have all the other information that a human might see (why else would a similar attack on a forked blockchain be possible? :-) ).
Bob replies to Mallory with the correct encrypted value which Mallory essentially ‘replays’, or ‘reflects’, to Alice. Mallory is now able to spoof being Bob. Also note that Mallory does not need to decrypt the message in this protocol, he only has to pass it along to Alice.
Here is the protocol step by step:
- Alice -> Mallory: nonce
- Mallory -> Bob: nonce <-- reflection attack
- Bob -> Mallory : E(K, nonce) <-- Mallory receives the correct response to Alice's challenge
- Mallory -> Alice: E(K, nonce) <-- and then authenticates himself to Alice
There are a number of variations of such attacks so any you see on the web may differ but the principles are essentially the same.
Reflection attack prevention: ID values
From the above protocol example it is clear that encryption and nonce values alone are not quite enough to prevent replay attacks. At university we learnt about the Needham-Schroeder authentication protocol which suffers from the man-in-middle attack described above (a reflection attack). It also uses encrypted nonce values but it is slightly more sophisticated than I described above.
The fix for the attack is include an ID value (such as a name, "Bob") inside the encrypted message. Once Bob’s message is decrypted by Alice she would know to only use a key she shares with Bob to encrypt later messages. A more thorough explanation could take quite a bit of time; however, the idea of using an ID value to defeat a particular type of attack is what made me think that recent replay attacks were really more like reflection attacks. The two are related, but thinking on the problem gave me a lot of food for thought.
The fixed protocol with participant IDs
Up Next
In my next piece I'm going to apply my understanding of the above attacks specifically to the blockchain setting.
Hope that was informative and helpful for learning about protocol security. This knowledge definitely has applicable uses in blockchain protocols.