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
Summary
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.
Product
solidus
Tested Version
v2.10.5
Issue details
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 "a@a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.@"
processing time: 54.293660s
=> nil
Impact
Denial of Service
Resources
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
a@example.com
(this field does not appear to be validated using the vulnerable regex), and passwordfoobar
, 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
input
field, and change thetype
attribute totext
, to disable your browser’s client-side validation (or use a browser like Links that doesn’t do client-side validation). - Then paste
a@a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.@
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.
Credit
This issue was discovered by @nickrolfe (Nick Rolfe) from the GitHub CodeQL team.
Contact
You can contact the GHSL team at securitylab@github.com
, please include GHSL-2021-099
in any communication regarding this issue.