Coordinated Disclosure Timeline
- 2021-07-12: Report sent to maintainers
- 2021-10-12: Maintainers contacted about the expiration of the disclosure window
- 2021-11-22: Public GitHub issue created requesting a security contact
- 2021-11-22: GitHub advisory created to privately discuss the issue
- 2021-12-08: Fix is released
A user of the system can provide an email address containing a specifically crafted string that will trigger a ReDoS vulnerability when checking out an order.
The Rails app has an email validator class (core/lib/spree/core/validators/email.rb#L15) that matches a given email against the following regex:
EMAIL_REGEXP = /\A([^@\.]|[^@\.]([^@\s]*)[^@\.])@([^@\s]+\.)+[^@\s]+\z/
This is vulnerable to a ReDoS attack, since the
([^@\s]+\.)+ part can match a substring like
a.a. in more than one way. So, with many repetitions of
a., we can make the regex engine set up exponentially many paths through the NFA, and then a trailing
@ will force it to backtrack to try all of them.
irb(main):018:0> EMAIL_REGEXP.match "email@example.com.@" processing time: 54.293660s => nil
Denial of Service
Proof of concept
To demonstrate an exploit, run a sample Solidus Rails app in Docker:
$ docker run --rm -it -p 3000:3000 solidusio/solidus-demo:latest
Then, in a browser:
- Go to http://localhost:3000/signup to create an account.
- Enter email address
firstname.lastname@example.org(this field does not appear to be validated using the vulnerable regex), and password
foobar, and click the Create button. You should be logged in and viewing a sample store.
- Click on an item and add it to your cart.
- On the shopping cart page, click the Checkout button.
- In your browser’s dev tools, inspect the email
inputfield, and change the
text, to disable your browser’s client-side validation (or use a browser like Links that doesn’t do client-side validation).
- Then paste
email@example.com.@into that email field.
- Fill in the required address fields with a fake address.
- Press the Save & Continue button. This will trigger the email validation and catastrophic backtracking.
After a long wait, the page will finish loading and show an error that the email is invalid. In the terminal you’ll see a message like
Completed 200 OK in 42398ms showing that we made the server process spin the CPU for 42 seconds.
If we use a longer attack string, we can make it take even longer. I got tired of waiting before seeing if it would ever time out.
This issue was discovered by @nickrolfe (Nick Rolfe) from the GitHub CodeQL team.
You can contact the GHSL team at
firstname.lastname@example.org, please include
GHSL-2021-099 in any communication regarding this issue.