Advisory

Unserialisation vulnerability in Redirection could allow admin to execute arbitrary code in some circumstances

Overview

It is possible for a user with the administrator privilege to submit a string that contains an encoded object which executes arbitrary code of their choosing.

The value can be passed in with an AJAX request to admin-ajax.php using the red_ajax_set_redirect action that is passed to the ajax_set_redirect method in this code:

    public function ajax_set_redirect( $params ) {
      $params = $this->get_params( $params );
      ....
    $result = $redirect->update( $params );
    }

    private function get_params( $params ) {
      if ( empty( $params ) ) {
        $params = $_POST;
      }
      return $params;
    }

The update method then passes the attack string to this code:

    class Red_Item {
      public function update( $details ) {
        $data = $sanitizer->get( $details );
        $this->load_from_data( (object) $data );
      }

      private function load_from_data( stdClass $values ) {
        foreach ( $values as $key => $value ) {
        $this->$key = $value; }
      }

The sanitizer does not sanitize the action_data value. Many calls to this class then use its to_json method, which is as follows:

    public function get_action_data() {
      return $this->action_data ? $this->action_data : '';
    }

    public function to_json() {
      maybe_unserialize( $this->get_action_data() ),
    }

The sum effect is therefore that unsanitized user input is being passed to maybe_unserialize().

Proof of concept

Achieving arbitrary code execution depends on which classes are available (that is, which plugins and themes are installed and active). It may not be possible in all situations. As such, this PoC will merely attempt to show that an arbitrary string can be passed to the maybe_unserialize() function.

Visit /wp-admin/tools.php?page=redirection.php

Create a new redirect with “/boo”, “https://www.dxw.com/”, and “Redirections”.

We’ll assume this redirect was given ID of 1 in the wp_redirection_items table. If that isn’t true, change the “id” value in the provided JavaScript.

Then, without leaving the page, open your browser’s console and execute this JavaScript:

    jQuery.ajax(ajaxurl,{
      method: 'POST',
      data: {
      'action': 'red_set_redirect',
      '_wpnonce': window.Redirectioni10n.WP_API_nonce,
      'id': '1',
      'match_type': 'url',
      'action_code': '1',
      'action_type': 'url',
      'url': 'https://www.dxw.com/',
      'group_id': '1',
      'action_data': 'O:8:"stdClass":1:{s:5:"hello";s:5:"world";}',
      },
    }).done(console.log)

Then, by inspecting the JavaScript object printed by console.log, or by looking at the Network logs, you’ll notice that we have a {“hello”: “world”} JavaScript object showing that our arbitrary string was passed to unserialize() and therefore, if the correct classes were available, we would be able to turn this into arbitrary code execution.

Mitigation/further actions

Upgrade to version 2.8 or later.

Advisory timeline

  1. 2017-10-02: Discovered
  2. 2017-10-03: Reported via website contact form
  3. 2017-10-04: Response received. Author has asked for PoC: “The value for action_data is sanitised when it is passed through Red_Item_Sanitize”
  4. 2017-10-09: Developed a PoC
  5. 2017-10-10: Working PoC provided to author.
  6. 2017-10-18: Author reported fixed in 2.8
  7. 2018-06-06: Advisory published
  8. 2018-06-12: CVE requested
  9. 2018-06-23: CVE assigned

CVSS

Base score 7.2
Attack vector Network
Attack complexity Low
Privileges required High
User interaction None
Scope Unchanged
Confidentiality High
Integrity High
Availability High

Metadata

  • Severity
    High (base score 7.2)
  • Discovered by
    Glyn Wintle
  • Severity
    High
  • Advisory ID
    dxw-2017-3338
  • CVE
    CVE-2018-1000509
  • Component/package
    Redirection
  • Version
    2.7.1
  • Published
    2018-06-06