WordPress Plugin - All in One SEO Pack - Stored XSS
Vulnerability Overview
The all-in-one-seo-pack plugin before 3.2.7 for WordPress (aka All in One SEO Pack) is susceptible to Stored XSS due to improper encoding of the SEO-specific description for posts provided by the plugin via unsafe placeholder replacement.
- Identifier : SBA-ADV-20190913-04
- Type of Vulnerability : Cross-site Scripting
- Software/Product Name : All in One SEO Pack
- Vendor : Semper Plugins
- Affected Versions : <= 3.2.6
- Fixed in Version : 3.2.7
- CVE ID : CVE-2019-16520
- CVSSv3 Vector : AV:N/AC:L/PR:L/UI:R/S:U/C:H/I:H/A:N
- CVSSv3 Base Score : 7.3 (High)
Vendor Description
THE ORIGINAL WORDPRESS SEO PLUGIN, DOWNLOADED OVER 50,000,000 TIMES SINCE 2007. Use All in One SEO Pack to optimize your WordPress site for SEO. It’s easy and works out of the box for beginners, and has advanced features and an API for developers.
Active Installations: 2+ million
Source: https://wordpress.org/plugins/all-in-one-seo-pack/
Impact
By exploiting the documented vulnerability, an authenticated attacker with the ability to create posts can execute JavaScript code in a victim's browser. This can be misused, e.g for phishing attacks by displaying a fake login form and sending the victim's credentials to the attacker. Furthermore malicious actions can be performed in the context of an authenticated user. The impact depends on the level of access of the attacked user. In case of an admin this can lead to the execution of PHP code and the compromise of the server.
Vulnerability Description
The plugin adds several fields to the page where a post can be created or edited.
This allows setting a custom title and description for each post.
The information provided there, will be inserted in corresponding meta-tags on the page
of the post. The values of the fields are escaped before they are inserted into the
HTML of the page.
However, in the description field, there is the possibility to insert placeholders that
get replaced with certain values before output. A placeholders can be also
set for the previously mentioned title field. The relevant code can be found in
aioseop_class.php lines 4546-4548:
if ( false !== strpos( $description, '%post_title%', 0 ) ) {
$description = str_replace( '%post_title%', $this->get_aioseop_title( $post, false ), $description );
}When an attacker sets a payload in the title field and provides a placeholder for the
value of the title field in the description field, the raw value of the title field will get inserted
in the description. The description is not sanitized or encoded afterwards.
This allows the attacker to break out of the meta-tag attribute and insert arbitrary
HTML and JavaScript.
Proof of Concept
When a post is created or edited the following values can be set to show the vulnerability:
- Title:
test_aiosp_title&<>"';><script src='data:text/javascript,alert(1)'></script>a - Description:
test_aiosp_desc&<>"'; pt:%post_title% wp_title:%wp_title% bd:%blog_description% sd:%site_description% bt: %blog_title% st: %site_title% desc:%description%
When the post is saved and accessed later the JavaScript alert-popup will be shown. The resulting HTML page will contain the following code (shortened for readability):
[...]
<title>test_aiosp_title&<>"';<script src='data:text/javascript,alert(1)'></script> | XXXXXXX</title>
<!-- All in One SEO Pack 3.2.5 by Michael Torbert of Semper Fi Web Design[197,235] -->
<meta name="description" content="test_aiosp_desc&"'; pt:test_aiosp_title&<>"';<script src='data:text/javascript,alert(1)'></script> wp_title:test_aiosp bd: sd: bt: XXXXXXX st: XXXXXXX desc:%description%" />
[...]Recommended Countermeasures
We recommend to properly escape the output by applying the encoding functions provided by WordPress,
like the esc_*- or wp_kses_*-functions after all placeholders were substituted.
Timeline
2019-09-09Identified the vulnerability2019-09-10Contacted vendor2019-09-10Response by vendor about disclosure contact2019-09-10Vulnerability disclosed to vendor2019-09-10Vulnerability verified by vendor2019-09-10Vulnerability fixed by vendor, public disclosure coordinated2019-09-20CVE assigned2019-10-16Public disclosure
References
- https://wordpress.org/plugins/broken-link-checker/
- https://wordpress.org/plugins/broken-link-checker/#developers
- https://semperplugins.com/all-in-one-seo-pack-changelog/
- awesomemotive/all-in-one-seo-pack#2888
Credits
- Tobias Fink (SBA Research)