espressif / esp-idf

Espressif IoT Development Framework. Official development framework for Espressif SoCs.
Apache License 2.0
13.46k stars 7.25k forks source link

ESP-NOW does not prevent replay attacks (IDFGH-8037) #9544

Closed ceribus closed 1 month ago

ceribus commented 2 years ago

Environment

Problem Description

The ESP-NOW protocol does not prevent message replay with encrypted messages.

Expected Behavior

Replayed messages should be ignored.

Steps to reproduce

Use two devices to reproduce the replay attack using the firmware and script from https://github.com/ceribu/esp-now-replay This was only tested on ESP32 and ESP32-C3 using IDF v4.4.1 and v4.4.2.

ceribus commented 2 years ago

While testing some other stuff on ESP-NOW i discovered that you can't replay frames when the retry bit is set. So the replay protection does seem to work but only on retransmitted frames?

zhangyanjiaoesp commented 2 years ago

While testing some other stuff on ESP-NOW i discovered that you can't replay frames when the retry bit is set. So the replay protection does seem to work but only on retransmitted frames?

Yes, you are right.

Alvin1Zhang commented 1 year ago

Thanks for reporting, will close due to short of feedback, feel free to reopen with more updates.

ceribus commented 1 year ago

@Alvin1Zhang What kind of feedback are you expecting? As far as I can tell, this issue hasn't been fixed yet. Please reopen.

zhangyanjiaoesp commented 1 year ago

@ceribus Since we have explained in the last comment what kind of replay attacks are currently supported to prevent, and the issue hasn't been updated for a long time, we closed it. If your request is to support all replay attacks for ESPNOW, we'll reopen the issue and then we'll consider to add this feature as soon as possible.

ceribus commented 1 year ago

@zhangyanjiaoesp @Alvin1Zhang Let me explain the issue in a little more detail.

First, it should be noted that random numbers alone are not suitable for protection against replay attacks, since the receivers would have to permanently remember all previously received random numbers. Furthermore, there is a small chance that a collision could occur if a sender generates the same number multiple times.

Currently, ESP-NOW uses only a single buffer for the last received random number of any of its peers, which can lead to the following problem.

  1. Peer A sends a message to Peer C, which is also received by an attacker.
  2. Peer C stores the Random Number received from Peer A.
  3. Peer B sends a message to Peer C.
  4. Peer C overwrites the buffer with the Random Number received from Peer B.
  5. The Attacker replays the previously captured frame from Peer A.
  6. Peer C compares the Random Number of the received frame against the last one it received, which is from Peer B. Since the numbers do not match, the replayed frame is passed to the application.

However, the random number is currently only compared if the retransmission bit in the frame header is set, which is not the case in an attack. Thus, the implemented mechanism can at best prevent repeating retransmissions by the sender, but not a replay attack.

Also, this mechanism is not described any further in the documentation. The only sentence in the documentation about random bytes contains spelling errors which could cause confusion between relay and replay attacks.

Please add a sufficient protection against replay attacks for encrypted ESP-NOW communication. Also, it would be helpful to have a note in the documentation indicating the vulnerability to replay attacks until the problem is fixed.

zhangyanjiaoesp commented 1 year ago

@ceribus Thanks for your explanation. We will fix the problem scenario you described and update the docs.

zhangyanjiaoesp commented 1 year ago

@ceribus I have changed the espnow code based on the IDF v4.4.2 (commit 1b16ef6cfc2479a08136782f9dc57effefa86f66), please use the attched wifi lib to test if it can solve your problem, thanks.

replace the wifi lib in the idf/components/esp_wifi/lib folder. wifi_lib_0629.zip wifi firmware version: c1a7486

AmirHmZz commented 1 year ago

@zhangyanjiaoesp can you please explain how did you try to fix that? I mean techninal details...

ceribus commented 1 year ago

Thank you very much for the fix! I am currently quite busy and will have a closer look at the changes some time next week.

zhangyanjiaoesp commented 7 months ago

Thank you very much for the fix! I am currently quite busy and will have a closer look at the changes some time next week.

@ceribus Have you tested the fix?

ceribus commented 6 months ago

Hi @zhangyanjiaoesp! I accidentally posted the answer to another issue first :smile: I'm sorry for the delay.. It seems you implemented a buffer of recently received random values for every peer, right? To my unterstanding, this will not effectively prevent replay attacks, as an attacker can overwrite the buffer with previously sent frames (from outside the range of the buffer) and then replay a selected frame.

zhangyanjiaoesp commented 6 months ago

@ceribus Yes, you are right. Since ESP-NOW is not connected, the security is not as perfect as wifi connection, we implement the buffer to save random values in order to ensure as much security as possible, but it can't cover all situations, maybe we need to find a better solution.

ceribus commented 6 months ago

@zhangyanjiaoesp This is very difficult with a connectionless protocol, when messages can be sent and received at any time without any previous handshake. You could include a warning about the susceptibility to replay attacks to the documentation. Perhaps the handshake from the ESP-NOW Component (https://github.com/espressif/esp-now) could be used by default for encrypted communication with ESP-NOW protocol. This would make it much easier, as you can simply use sequence numbers to prevent replay attacks after the handshake.

zhangyanjiaoesp commented 6 months ago

@ceribus

You could include a warning about the susceptibility to replay attacks to the documentation.

yes, we will update the documentation.

Perhaps the handshake from the ESP-NOW Component (https://github.com/espressif/esp-now) could be used by default for encrypted communication with ESP-NOW protocol. This would make it much easier, as you can simply use sequence numbers to prevent replay attacks after the handshake.

Do you mean the handshake in the security example ?

Sherry616 commented 1 month ago

Thanks for reporting, will close due to short of feedback, feel free to reopen with more updates. Thanks for using our Espressif product!