Vulnerability Details: Authenticated SQL Injection in MailPoet 2
The changelog for the latest version of the WordPress plugin MailPoet 2 is:
Fixed security issues, thank you to Mike for reporting these issues.
Some of the changes made in that version look to involve SQL statements and we confirmed that there was at least an authenticated SQL injection vulnerability fixed.
In the beginning of the function countSubscribers in the file /models/user.php this line was added to restrict the values contained in the array variable $list_ids to integers:
80 | $list_ids = array_map('intval', $list_ids); |
That variable is included in an SQL statement:
90 | $where[] = 'C.list_id IN ('.implode(',',$list_ids).')'; |
The value of that variable is passed in to the function:
78 | function countSubscribers(Array $list_ids = array(), $confirmed_subscribers = true) |
That function is in called by the function can_subscribers_count_shortcode, where the value of the variable comes from user input, in the form of a shortcode attribute:
268 269 270 271 272 273 274 275 276 277 278 279 | function scan_subscribers_count_shortcode($attributes) { $user = WYSIJA::get('user','model'); $list_ids = !empty($attributes['list_id']) ? explode(',', $attributes['list_id']) : array(); // if double optin is on we count only the confirmed subscribers, otherwise we count both confirmed and unconfirmed $confirmed_subscribers = false; $model_config = WYSIJA::get('config', 'model'); if ($model_config->getValue('confirm_dbleoptin')){ $confirmed_subscribers = true; } return $user->countSubscribers($list_ids, $confirmed_subscribers); |
That function is in turn accessed through the shortcode “wysija_subscribers_count”:
14 | add_shortcode('wysija_subscribers_count', array($this,'scan_subscribers_count_shortcode')); |
As the proof of concept below, before that change, SQL injection was possible to anyone able to add a shortcode to a post or page.
Proof of Concept
Adding the following proof of concept to a post or page will cause varying amounts of time for tit to fully load depending on how long you specify MySQL sleep function to run.
Replace “[sleep time]” with how many seconds you want sleep to occur for.
[wysija_subscribers_count list_id="1 )AND SLEEP([sleep time]"]