This blog post is about the User Registration plugin vulnerability. If you’re a User Registration user, please update the plugin to at least version 2.3.3.
Patchstack Pro and Business users are protected from the vulnerability. You can also sign up for the Patchstack Community plan to be notified about vulnerabilities as soon as they become disclosed.
For plugin developers, we have security audit services and Threat Intelligence Feed API for hosting companies.
User Registration WordPress plugin
The plugin User Registration (versions 2.3.2.1 and below, free version), which has over 60,000 active installations is known as one of the more popular custom registration plugins in WordPress.
This plugin is considered to be a lightweight, and 100% responsive plugin that comes with a beautifully designed login form ready to use. User Registration’s drag-and-drop form builder lets us create custom registration forms of any kind for our WordPress site.
This plugin suffers from an authenticated PHP Object Injection vulnerability. The User Registration plugin vulnerability occurs when user-supplied input is not properly sanitized before being passed to the unserialize()
PHP function.
Since PHP allows object serialization, a user in this case with a minimum Subscriber role, could pass ad-hoc serialized strings to a vulnerable unserialize()
call, resulting in an arbitrary PHP object(s) injection into the application scope. The described vulnerability was fixed in version 2.3.3 and assigned CVE-2023-27459.
User Registration plugin vulnerability
User Registration plugin vulnerability in Patchstack database.
The User Registration plugin is designed to handle multiple custom registration processes on the WordPress site. Most WordPress sites that utilize this plugin would have configured the Membership
settings to be Anyone can register
. Since the default value of New User Default Role
setting is set to Subscriber
, with this configuration, anyone could have a Subscriber
role with self-registration.
The vulnerable code exists on the user_registration_form_field
function:
-------
case 'checkbox':
$field_key = isset( $args['field_key'] ) ? $args['field_key'] : '';
$default_value = isset( $args['default_value'] ) ? $args['default_value'] : ''; // Backward compatibility. Modified since 1.5.7.
$default = ! empty( $value ) ? $value : $default_value;
$select_all = isset( $args['select_all'] ) ? $args['select_all'] : '';
$options = isset( $args['options'] ) ? $args['options'] : ( $args['choices'] ? $args['choices'] : array() ); // $args['choices'] for backward compatibility. Modified since 1.5.7.
$choice_limit = isset( $args['choice_limit'] ) ? $args['choice_limit'] : '';
$choice_limit_attr = '';
if ( '' !== $choice_limit ) {
$choice_limit_attr = 'data-choice-limit="' . $choice_limit . '"';
}
if ( isset( $options ) && array_filter( $options ) ) {
if ( ! empty( $default ) ) {
$default = ( is_serialized( $default ) ) ? unserialize( $default ) : $default;
}
-------
case 'multiselect':
$options = $field .= '';
if ( is_serialized( $value ) ) {
$default_value = unserialize( $value );
} else {
$default_value = $value;
}
-------
This function handles the process when a logged-in user tries to update their profile. Looking at the function handler, each form type will be handled on a multiple switch case condition. The $value
parameter is the data of the form field submitted by the user. In this case, the user is able to trigger the PHP Object Injection through a checkbox
and multiselect
fields.
For example, one of the user registration form templates is Student Registration, which has a checkbox
field type on the Hobbies field. When updating the profile on the My Account
page of the User Registration profile, the user only needs to supply a raw PHP object into one of the checkbox
es or multiselect
fields on the HTTP request like the example below:
.......
------WebKitFormBoundaryl6vqRujEtLBjFt5p
Content-Disposition: form-data; name="user_registration_check_box_<RANDOM_NUMBER>"
<RAW SERIALIZE PHP OBJECT>
------WebKitFormBoundaryl6vqRujEtLBjFt5p
.......
At the time this article was posted, we were not able to discover a significant POP chain in the vulnerable plugin. If a POP chain is present via an additional plugin or theme installed on the WordPress site, it could allow the attacker to delete arbitrary files, retrieve sensitive data, or execute code, depending on the available POP chain.
The patch in User Registration
Since this issue is mainly because the code tries to unserialize data directly from the user input, the patch could be a simple add of allowed_classes
set to false on the unserialize function, though a patch using json_encode and json_decode would be more ideal. The patch can be found below:
Conclusion
The Unserialize
process in PHP is one of the more sensitive processes that could lead to a security issue. In general, we do not recommend using this method to process data that could be partially or fully controlled by user input.
We recommend using JSON instead of serialization to process more complex data structures. If the unserialize process is still needed on the application, we recommend at least configuring the allowed_classes
option set to false
.
User Registration plugin vulnerability disclosure timeline
02-03-2022 – We found the vulnerability and reached out to the plugin vendor.
16-03–2022 – User Registration plugin version 2.3.3 was published to patch the reported issues.
21-03-2023 – Added the vulnerabilities to the Patchstack vulnerability database.
24-03-2023 – Published the article.
Help us make the internet a safer place
Making the WordPress ecosystem more secure is a team effort, and we believe that plugin developers and security researchers should work together.
- If you’re a plugin developer, join our mVDP program that makes it easier to report, manage and address vulnerabilities in your software.
- If you’re a security researcher, join Patchstack Alliance to report vulnerabilities & earn rewards.