Coordinated Disclosure Timeline
- 2024-03-07: Sent vulnerability report to Zammad.
- 2024-03-08: Report was acknowledged by maintainer.
- 2024-04-17: Advisory for this vulnerability (ZAA-2024-03) was published and Zammad 6.3 was released.
- 2024-04-26: CVE-2024-33667 was assigned to this vulnerability.
Summary
A denial of service (DoS) vulnerability was found in the helpdesk software Zammad. An authenticated attacker could have prevented the web application from handling any requests.
Project
Zammad
Tested Version
Details
Remote DoS via arbitrary method call (GHSL-2024-029
)
An authenticated user can perform a remote Denial of Service attack against Zammad. Zammad exposes endpoints to export the calendar of a helpdesk worker in the iCal format:
# @path [GET] /calendar_subscriptions/:object
# @path [GET] /calendar_subscriptions/:object/:method
[..]
def object
calendar_subscriptions = CalendarSubscriptions.new(current_user)
ical = calendar_subscriptions.generic(params[:object], params[:method])
Here the method
parameter is defined as part of the URL. This method flows into a method named generic
on the class CalendarSubscriptions
, which itself calls generic_call
passing the method name on:
def generic_call(object_name, method_name = 'all')
method_name ||= 'all'
events_data = []
if @preferences[ object_name ].present?
sub_class_name = object_name.to_s.capitalize
object = "CalendarSubscriptions::#{sub_class_name}".constantize
instance = object.new(@user, @preferences[ object_name ], @time_zone)
method = instance.method(method_name)
events_data += method.call
end
events_data
end
The method generic_call
then uses the method_name
to create a method object, which is then called using call
. (The object name is prefixed and not freely definable.)
Ruby’s method
objects can reference any available method on an object including methods defined on parent classes such as Object
and BasicObject
. The Kernel
module is included by the class Object
, so its methods are available in every Ruby object. When call
is called on a method
object the referenced method is executed.
Most public information about this type of vulnerability mentions the Kernel methods exit
and exit!
as destructive examples to pass to the send method. However, while this might throw an exception or even stop the container (Which seems to be the case when exit!
is sent to Zammad). We found out that the Kernel method sleep
might be a better candidate to stop a Rails application from answering requests. Calling sleep
without a duration parameter will make the current request thread sleep forever.
So, if a Rails application is started with a maximum of 5 threads (RAILS_MAX_THREADS=5
) in combination with 2 Puma workers (WEB_CONCURRENCY=2
) it will take 10 (2*5) requests to stop the Rails application from responding to any requests.
This vulnerability was discovered with the help of CodeQL’s Code injection query.
Proof of concept
The following request sets the params[:method]
to sleep
.
curl 'http://127.0.0.1:8080/ical/tickets/sleep' \
-H 'User-Agent: Mozilla/5.0' \
-b $'_zammad_session_[..]=[..]'
Hint: replace the _zammad_session_
cookie with a valid (authenticated) value.
Alternatively, an attacker could direct a Zammad helpdesk worker to a website under their control, which would call this endpoint (e.g. by loading it in an img
tag). Since a GET request is enough to trigger this vulnerability the authenticated cookie should be sent automatically by the browser.
Impact
This issue may lead to Denial of Service (DoS). (It might also lead to information disclosure if a method could be called that returns information that can be rendered by the calendar renderer)
CVE
- CVE-2024-33667
Credit
This issue was discovered and reported by GHSL team member @p- (Peter Stöckli).
Contact
You can contact the GHSL team at securitylab@github.com
, please include a reference to GHSL-2024-029
in any communication regarding this issue.