Home » ajax » Page 3

Tag: ajax

Beaver Builder Lite and Pro < 1.7.1 Security Issue

Beaver Builder is a popular WordPress plugin that allows drag & drop editing of pages. I’m a big fan of this plugin it allows users to make some pretty great sites without a lot of work. Any plugin I’m going to use I have to do at least some minimal reading of the code to search for security issues. I discovered a few issues here, though what I did discover requires a valid WordPress user account (not just admin) to use them.

The wordpress.org page for the lite version claims there are 50,000+ active installs, I could not find any indication of how many users of the pro version there are.

Unauthorized AJAX Calls

The Beaver Builder plugin creates it’s own AJAX handler that is hooked into the ‘wp’ WordPress action.


This looks solid at first glance. It requires a user to be logged in and also checks that the current_user_can() edit this post. Unfortunately as seen below, FLBuilderModel::get_post_id() allows passing the ‘post_id’ via HTTP POST data (abstracted away behind the self::get_post_data() function). A user is able to pass in HTTP POST ‘post_id=0’ and the current_user_can() function call is never run.


After a nefarious user circumvents those checks they are able to call any of the 40+ actions that Beaver Builder includes. Which would allow them to create/edit pages, manage services, list all users.


  • 1/19/2016 3:30pm Sent request for contact information
  • 1/19/2016 10:54pm Response received
  • 1/20/2016 12:02am Security disclosure sent
  • 1/24/2016 Updated version released

WP-Invoice < 4.1.1 Multiple Security Vulnerabilities

The WP-Invoice plugin from Usability Dynamics, Inc. contains several security vulnerabilities. The wordpress.org stats claim there are 5,000+ active installs, so this is not a highly used plugin but anything that is related to billing/invoices always puts me on edge. If you use this plugin I encourage you to update immediately.

I only evaluated the free version of this plugin and did not look at any of their paid add-ons for vulnerabilities. I discovered three issues that were accessible to unauthenticated users and one issue that required a valid WordPress account.

Unauthorized Setting Changes

Inside class_core.php the function admin_init() gets hooked to the ‘admin_init’ WordPress action which is called when the admin files are loaded, not just when an account with administrator access is used.

Inside this function it takes user input and without verification updates the sites settings. This merges in the existing settings so by passing individual settings only those can be updated. This allows changing settings like the emailed templates, paypal email address, and various other scary parts.


Retrieving invoices of arbitrary users

I’m not sure this is the most critical of the flaws, but it does allow release of sensitive data and the invoice numbers can be used in the next vulnerability.

Here we have AJAX actions registered for logged in and not logged in users.


Upon first glance I thought this would allow only the current users invoices to be loaded.


Upon further examination if the user is logged in then their invoice will be loaded, but if the user is not logged in $_GET[‘wpi_user_id’] can be passed containing a WordPress numeric user_id.


Updating previously invoiced users meta data

Through the magic of unauthenticated AJAX the ‘wpi_gateway_process_payment’ actions can be called.


The wpi_gateway_base::process_payment() function takes user input in order to call the process_payment() function in various payment gateway handlers.


In this case the ‘wpi_paypal’, ‘wpi_interkassa’, and ‘wpi_twocheckout’ all allow this to happen. Below I’ll only show the ‘wpi_paypal’ variation. This allows various type of the users meta data to be updated and if their CRM plugin is installed any of the attributes that are used in there can be updated.


Privilege escalation of logged in users

Through the ‘wpi_update_user_option’ AJAX action, a logged in user can pass arbitrary ‘meta_key’ and ‘meta_value’ that gets updated for their account. Many of these options are accessible to the user via their profile, but typically a user should not be able to modify their ‘wp_capabilities’ or other potentially dangerous fields.



  • 1/15/2016 11:28am Initial contact email sent
  • 1/18/2016 3:14am Contact information received
  • 1/19/2016 11:58am Full disclosure email sent
  • 1/29/2016 6:23am Vendor responded saying issues were resolved in latest release


Ultimate Member Plugin 1.0.78 Critical Security Vulnerability

While sitting  and waiting for my daughter at gymnastics several weeks ago I noticed an announcement for Ultimate Member plugin, sounded interesting so I bookmarked it to check out later.

Fast forward till last week when I noticed it sitting there and decided to take a look at it. I noticed a couple security issues and contacted the developers.

There were a few minor issues that they fixed, but the major ones are critical. If you are using this plugin, Update Immediately!

Delete any file

We’ve got an un-authenticated AJAX action to delete files here.


We definitely need some authorization on the user and/or the specific file to be deleted there when the AJAX call comes in.


Well at least delete_file() is calling um_is_temp_upload() to make sure the file is a temporary file.


Uh-oh. It’s only pulling ‘/ultimatemember/temp/’ off the beginning. So it will happily take ‘../’ in the path and you can use it to delete any file that the user running php has permissions for.

Upload arbitrary files

Multiple issues all come together to make this especially evil.

ultimate-fileexecFirst off, the um-file-upload.php can be called directly and it bootstraps WordPress. I’d rather send every request through WordPress and not allow direct access to anything.


Then we call check_file_upload() and only move the file if it doesn’t return an error.


Cool, check_file_upload() at least checks for allowed extensions from an array. So if I try to upload something ending in .php it sets ‘$error = $data[‘extension_error’]; Here’s the rub, since user input is passed into check_file_upload(), get_field($field) call will return null if $field is some invalid field. So the end result is check_file_upload() is going to return null;


Now we’ve got a file uploaded and it even kicks back the full path that you need to call the file. Assuming the host will allow code execution from the uploads directory, you can now run code as the user running php.