11 Aug 2023

WordPress Plugin Security Review: Meta Box

For our 42nd security review of a WordPress plugin based on the voting of our customers, we reviewed the plugin Meta Box.

If you are not yet a customer of the service, once you sign up for the service as a paying customer, you can start suggesting and voting on plugins to get security reviews. For those already using the service that haven’t already suggested and voted for plugins to receive a review, you can start doing that here. You can use our tool for doing limited automated security checks of plugins to see if plugins you are using have possible issues that would make them good candidates to get a review. You can also order a review of a plugin separately from our service.

The review was done on version 5.7.3 of Meta Box. We checked for the following issues during it as part of our standard review:

  • Insecure file upload handling (this is the cause of the most exploited type of vulnerability, arbitrary file upload)
  • Deserialization of untrusted data
  • Security issues with functions accessible through WordPress’ AJAX functionality (those have and continued to be a common source of disclosed vulnerabilities)
  • Security issues with functions accessible through WordPress’ REST API (those have started to be a source of disclosed vulnerabilities)
  • Persistent cross-site scripting (XSS) vulnerabilities in the frontend portions of the plugin and in the admin portions accessible to users with the Author role or below
  • Cross-site request forgery (CSRF) vulnerabilities in the admin portion of the plugin
  • SQL injection vulnerabilities (the code that handles requests to the database)
  • Reflected cross-site scripting (XSS) vulnerabilities
  • Security issues with functions accessible through any of the plugin’s shortcodes
  • Security issues with functions accessible through any of the plugin’s blocks
  • Security issues with functions accessible through the admin_action action
  • Security issues with functions accessible through the admin_init action
  • Security issues with functions accessible through the admin_post action
  • Security issues with import/export functionality
  • Security issues with usage of the is_admin() function
  • Security issues with usage of the add_option(), delete_option(), and update_option() functions
  • Security issues with usage of the update_user_meta() and wp_update_user () functions
  • Security with usage of determine_current_user filters
  • Security issues with usage of the reset_password() and wp_set_password() functions
  • Security issues with usage of the extract() function
  • Lack of IP address validation
  • Proper usage of sanitize_callback when using register_setting() to register settings.
  • CSV injection
  • Host header injection vulnerabilities
  • Lack of protection against unintended direct access of PHP files
  • Insecure and unwarranted requests to third-party websites
  • Any additional possible issues identified by our Plugin Security Checker

Results

Reviewing the security of the plugin is somewhat complicated by the fact that the plugin doesn’t work on its own, but is used in conjunction with custom functionality of each implementation. We tried to assess things while keeping that in mind.

We didn’t find any vulnerabilities, but we did find places where security could be improved, which are detailed below.

We notified of developer of the issues we found on July 13. They got back to us on July 15, stating they were working on things. Then on July 16, they provided us with a copy of the changes made to resolve the issues. Yesterday, they released version 5.7.5, which addresses the issues (the changelog incorrectly credits a competing provider).

Information Disclosure

The one issue that seemed reasonably serious is that the function ajax_get_users(), in the file /inc/fields/user.php, didn’t restrict what user fields are returned. For example, the session_tokens for users are returned as part of that by default. That was addressed by restricting what was returned by the WordPress function get_users(), called by the plugin’s function, by specifying the fields to be returned:

99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
$args          = wp_parse_args( $field['query_args'], [
	'orderby' => $display_field,
	'order'   => 'asc',
	'fields'  => [
		'ID',
		'user_login',
		'user_pass',
		'user_nicename',
		'user_email',
		'user_url',
		'user_registered',
		'user_status',
		'display_name',
	],
] );
99
$users   = get_users( $args );

Capabilities Check Missing

The AJAX accessible function dismiss() in /src/Updater/Notification.php lacked a capabilities check to limit access to the intended users. There was a nonce check, which would normally do the equivalent of that, but as the documentation for that states, it shouldn’t be relied on for that. A capabilities check was added:

59
60
61
62
public function dismiss() {
	if ( ! current_user_can( 'manage_options' ) ) {
		wp_send_json_error();
	}

What that function does makes the security impact of that lack of protection negligible.

There are several other AJAX accessible functions that lack a capabilities check, all of which are intended or could be intended to be accessed by anyone logged in.

Missing Nonce Check

The function ajax_get_embed() in the file /inc/fields/oembed.php seemed like it should include a nonce check, as other similar AJAX accessible functions in the plugin have that. That nonce check was added to the function:

39
40
public static function ajax_get_embed() {
	check_ajax_referer( 'oembed_get' );

Lack of Protection Against Direct Access to PHP Files

The plugin’s .php files that didn’t appear to be intended to be directly accessed don’t contain protection against direct access. We didn’t see anything that could be exploited in the files without the restriction in place, but restricting access to them would ensure that there isn’t any issue with that. Code was added to do that:

2
defined( 'ABSPATH' ) || die;

Leave a Reply

Your email address will not be published.