Web Flaws and Vulnerabilities

iThemes Security < 7.9.1 – Hide Backend ByPass

Blog Web Flaws and Vulnerabilities iThemes Security < 7.9.1 – Hide Backend ByPass

iThemes Security is a know security plugin in the WordPress community since years. One week ago we discovered a security issue in their “Hide Backend” module, leaking the hidden login page.

This ByPass Vulnerability has been patched in 7.9.1, update it if you’re using it.

ITS (iThemes Security) < 7.9.1 suffers of a GET/POST/REQUEST bug that could leak the wp-login page from WordPress. The purpose of the module is broken.

This vulnerability won’t open a door to your website, not more than the native login page will do. So, that’s not a big deal, but still, when you activate a module that says “Hide Backend”, you can expect this module to… hide the backend.

Report Timings:

  • 05 April 21 : Report the vulnerability
  • 06 April 21 : Vulnerability confirmed with attached patch
  • 07 April 21: Patch not working, received another patch
  • 08 April 21 : Patch valid and confirmed.
  • 14 April 21 : Versions updated
  • 20 April 21 : Bounty Rewarded

Vulnerability Explained

The Postman request

  • The HTTP request method is POST
  • The URL is pointing on wp-login.php
  • The URL parameter is “action=postpass(so it’s a GET one)
  • The BODY parameter is “action=login(so it’s a POST one)

The plugin will read the GET and will let pass since it’s allowed (see below), but WordPress will handle the POST one and will display the login form.

ITS 7.9.0 code

These are my comments, I’m just using the useful lines to explain.

/* https://plugins.svn.wordpress.org/better-wp-security/tags/7.9.0/core/modules/hide-backend/class-itsec-hide-backend.php */

// Line#24 On ITS init, handle the page request
add_action( 'itsec_initialized', array( $this, 'handle_specific_page_requests' ), 1000 );

// Line#95 Handle the requested path
$this->handle_request_path( $path );

// Line#107-109 Since we are requesting 'wp-login.php' page, we trigger this condition
} elseif ( in_array( $request_path, array( 'wp-login', 'wp-login.php' ) ) ) {

// Line#137 If $_GET['action'] is equal to 'postpass', do nothing.
private function handle_canonical_login_page() {
$action = isset( $_GET['action'] ) ? $_GET['action'] : '';

if ( 'postpass' === $action ) {

As you may now better understand, the action=postpass is the bypass. This is why you shouldn’t use 2 different methods to read values.

WordPress does this:

// /wp-login.php#367
$action = isset( $_REQUEST['action'] ) ? $_REQUEST['action'] : 'login';

So if $_REQUEST is read, you should read it too.

Now, let’s remember what $_REQUEST is. It’s a global array that contains both $_GET and $_POST values. The default order of merging if set by the server configuration and is 90% of the time GP, meaning “GET + POST”. But you could find a server that is on PG.


The first patch was to replace $_GET['action'] by $_REQUEST['action'] which seems good, but not really if the server configuration is set to PG, the flaw is still there, WordPress will load the login page again.

Did you know that WordPress will force a GP configuration? Now you know, and it’s done with wp_magic_quotes() , cool isn’t it? But it won’t help the patch because ITS is reading the values before the usage on this function, done before setup_theme, so ITS had to rewrite the patch just to change the hook and set it to setup_theme.

It’s now fixed in 7.9.1, update now.

But there is still one thing to know…

This module has been developed to prevent bots and scripts from entering or brute-forcing the WordPress login page. It hasn’t been designed to be not found by humans, so you can still find a way, as a human, to get the secret token of a login page protected by ITS using… Google.

When you know the secret slug name of the login page, you are redirected on the real WordPress login page with a new parameter acting as a secret token named itsec-hb-token. Since the parameter is a GET one, Google can index it, this is why you will find those token on search engines.

Let’s say I’m human (this is real, I mean…) and I want to target example.com. I’ll search for “site:example.com inurl:itsec-hb-token” and I may find something with the token in. Just click on it, if the token is still valid and TS activated, you’ll get the itsec-hb-token cookie. Now you can visit wp-login.php, you’re allowed.

This will not be fixed by ITS because it means a total revamp of the design of the module, and like I said, the module is designed to prevent bots and scripts.