The WordPress GiveWP plugin, which has 70,000+ active installations, fixed vulnerabilities affecting version 2.5.9 and below.
Reference
A CVE ID has been requested and we’ll update this post when it is assigned.
Unauthenticated settings change
In the “includes/gateways/stripe/includes/admin/admin-actions.php” script, the give_stripe_connect_save_options
function is loaded via the admin_init
hook:
function give_stripe_connect_save_options() { $get_vars = give_clean( $_GET ); // If we don't have values here, bounce. if ( ! isset( $get_vars['stripe_publishable_key'] ) || ! isset( $get_vars['stripe_user_id'] ) || ! isset( $get_vars['stripe_access_token'] ) || ! isset( $get_vars['stripe_access_token_test'] ) || ! isset( $get_vars['connected'] ) ) { return false; } // Update keys. give_update_option( 'give_stripe_connected', $get_vars['connected'] ); give_update_option( 'give_stripe_user_id', $get_vars['stripe_user_id'] ); give_update_option( 'live_secret_key', $get_vars['stripe_access_token'] ); give_update_option( 'test_secret_key', $get_vars['stripe_access_token_test'] ); give_update_option( 'live_publishable_key', $get_vars['stripe_publishable_key'] ); give_update_option( 'test_publishable_key', $get_vars['stripe_publishable_key_test'] ); // Delete option for user API key. give_delete_option( 'stripe_user_api_keys' ); } add_action( 'admin_init', 'give_stripe_connect_save_options' );
The function lacks a capability check and a security nonce. Because the admin_init
hook can be triggered by anyone, an unauthenticated user can tamper with the authentication credentials of the Stripe Connect payment gateway: ACCESS_TOKEN, REFRESH_TOKEN, PUBLISHABLE_KEY, ACCOUNT_ID.
Authenticated settings change
In the “includes/admin/emails/ajax-handler.php” script, the give_set_notification_status_handler
function is loaded via the wp_ajax
hook. It is used to enable or disable email notifications sent by GiveWP to the administrator:
function give_set_notification_status_handler() { $notification_id = isset( $_POST['notification_id'] ) ? give_clean( $_POST['notification_id'] ) : ''; if ( ! empty( $notification_id ) && give_update_option( "{$notification_id}_notification", give_clean( $_POST['status'] ) ) ) { wp_send_json_success(); } wp_send_json_error(); } add_action( 'wp_ajax_give_set_notification_status', 'give_set_notification_status_handler' );
The function lacks a capability check and a security nonce and thus can be accessed by an authenticated user such as a subscriber.
This vulnerability could be used in conjunction with the previous one: after tampering with the payment gateway, the attacker could disable all email notifications sent to the admin, which includes the notification sent when a new donation is received.
Additional issues
In the “includes/misc-functions.php” script, the give_get_ip
function is used to retrieve the user IP address:
function give_get_ip() { $ip = '127.0.0.1'; if ( ! empty( $_SERVER['HTTP_CLIENT_IP'] ) ) { // check ip from share internet $ip = $_SERVER['HTTP_CLIENT_IP']; } elseif ( ! empty( $_SERVER['HTTP_X_FORWARDED_FOR'] ) ) { // to check ip is pass from proxy $ip = $_SERVER['HTTP_X_FORWARDED_FOR']; } elseif ( ! empty( $_SERVER['REMOTE_ADDR'] ) ) { $ip = $_SERVER['REMOTE_ADDR']; } /** * Filter the IP * * @since 1.0 */ $ip = apply_filters( 'give_get_ip', $ip ); // Filter empty values. if ( false !== strpos( $ip, ',' ) ) { $ip = give_clean( explode( ',', $ip ) ); $ip = array_filter( $ip ); $ip = implode( ',', $ip ); } else { $ip = give_clean( $ip ); } return $ip; }
It relies on untrusted user input (HTTP_CLIENT_IP
and HTTP_X_FORWARDED_FOR
) that is sanitised in order to prevent attacks such as XSS, but isn’t properly validated: GiveWP will accept Client-IP: foo
as a valid IP address.
Timeline
The vulnerability was reported to the authors on October 18, 2019 and a new version 2.5.10 was released on October 28, 2019.
Recommendations
Update as soon as possible if you have version 2.5.9 or below installed.
If you are using our web application firewall for WordPress, NinjaFirewall WP Edition (free) and NinjaFirewall WP+ Edition (premium), you are protected against this vulnerability.
Stay informed about the latest vulnerabilities in WordPress plugins and themes: @nintechnet