Security Bughunt

2017 - August - Amsterdam

2017 Target - IoT



Han Sahin - Securify, March 2017

nBill Lite WordPress Plugin unauthenticated PHP Object injection vulnerability


/advisory/SFY20160601/nbill-logo.png

Abstract

A PHP Object injection vulnerability was found in nBill Lite, which can be used by an unauthenticated user to instantiate arbitrary PHP Objects. Using this vulnerability it is possible to execute arbitrary PHP code.

Contact

For feedback or questions about this advisory mail us at sumofpwn at securify.nl

The Summer of Pwnage

This issue has been found during the Summer of Pwnage hacker event, running from July 1-29. A community summer event in which a large group of security bughunters (worldwide) collaborate in a month of security research on Open Source Software (WordPress this time). For fun. The event is hosted by Securify in Amsterdam.

OVE ID

OVE-20160712-0009

Tested versions

This issue was successfully tested on the nBill Lite WordPress Plugin version 3.2.2.

Fix

There is currently no fix available.

Introduction

nBill Lite is a free version of nBill (the online billing system), which includes features for creating ad-hoc invoices that can be paid for online. It allows you to create client records for the people you want to bill, or import them from a CSV file or from your WordPress user records. You don't have to create a client record though, nBill Lite includes support for billing someone on a one-off basis even if they are not a registered client.

A PHP Object injection vulnerability was found in nBill Lite, which can be used by an unauthenticated user to instantiate arbitrary PHP Objects.

Details

This issue exists due to an unsafe call to unserialize() in the nbill_do_login() method. The input is taken directly from the POST body as can be seen in the following code fragment:

nbill/components/com_nbill/site.nbill.php:

function nbill_do_login()
{
   if (nbf_common::get_param($_POST, 'NBILL_login_submit_generic')) {
      $full_screen = nbf_common::nb_strpos(nbf_common::get_requested_page(true), html_entity_decode(nbf_cms::$interop->site_popup_page_prefix, ENT_COMPAT | 0, nbf_cms::$interop->char_encoding)) !== false || nbf_common::nb_strpos(nbf_common::get_requested_page(true), nbf_cms::$interop->process_url(html_entity_decode(nbf_cms::$interop->site_popup_page_prefix, ENT_COMPAT | 0, nbf_cms::$interop->char_encoding))) !== false;
if ($full_screen) {
$redirect_url = nbf_cms::$interop->live_site . "/" . nbf_cms::$interop->site_popup_page_prefix;
} else {
$redirect_url = nbf_cms::$interop->live_site . "/" . nbf_cms::$interop->site_page_prefix;
}
$request_values = unserialize(base64_decode(nbf_common::get_param($_POST, 'nb_request_values', null, true, false, true)));
if ($request_values) {
       foreach ($request_values as $request_key=>$request_value) {
          if ($request_key != "option" && $request_key != "nbverifier") {
             $redirect_url .= "&" . $request_key . "=" . urlencode($request_value);
          }
       }
}
nbf_cms::$interop->login(nbf_common::get_param($_POST,'NBILL_LOGIN_username_generic'), nbf_common::get_param($_POST,'NBILL_LOGIN_password_generic'), false, $redirect_url);
if (!nbf_cms::$interop->user->id) {
$redirect_url .= "&failure_message=" . NBILL_LOGIN_FAILED;
nbf_common::redirect($redirect_url);
}
      exit;
   }
}

It has been confirmed that this issue can be used to execute arbitrary PHP code.