wp2shell: more than a month later. Confirm 6.8.6, 6.9.5, 7.0.2. Patched is not clean.

Read the advisory

Emergency WordPress admin recovery with a one-time URL hook

Authorized emergency recovery when you have file access but no admin login: a temporary one-time URL hook, then remove the code immediately. Plus how to spot Indoxploit-style and odd-asset backdoors.

Topics Malware & cleanup Backups & recovery Login & access

Lars Koudal

Lars Koudal

Updated Published

If you own the site (or are hired to recover it) and every administrator login is gone, but you still have FTP, SFTP, or file manager access, you can temporarily create a new admin with a secret URL, log in, then delete the code.

Do not leave this in place “for later.” Do not install it on client sites as a hidden permanent entry. Attackers look for exactly this pattern. A forgotten recovery hook is a backdoor.

Prefer the simpler flow when you can: create an admin via functions.php and remove it after one login. Use the URL hook below only when you want the account created on an explicit visit.

When a recovery hook is appropriate (and when it is not)

Use it only when all of these are true:

  • You are authorized to recover the site (owner, or hired with written permission)
  • Every known admin login is gone or locked out
  • You have file access (FTP, SFTP, SSH, or host file manager)
  • You will remove the code immediately after one successful login

Do not use it when:

  • You want a permanent “just in case” entry on production or client sites
  • You lack authorization (that is unauthorized access, not recovery)
  • You still have a working admin account (reset the password instead)
  • The site is compromised and you plan to stop after logging in (regain access is step one of cleanup, not the finish line)

Typical recovery cases: a previous developer vanished with the only admin credentials, or malware deleted or locked every administrator account. If the lockout came from a hack, continue with hacked site steps after you get in.

Rules of engagement

  1. Only use this on sites you are authorized to recover.
  2. Choose secret query names that are not the examples in this post.
  3. Create the account once, log in, then delete the code.
  4. If the site was hacked, treat recovery as the start of cleanup, not the end.

Temporary URL hook (remove after use)

  1. Back up the active theme’s functions.php.
  2. Append this block at the end (child theme preferred so parent updates do not surprise you):
<?php
/**
 * TEMPORARY authorized recovery hook. Delete after you log in once.
 * Visit: https://example.com/?sn_recover=your-long-secret
 */
function sn_emergency_url_admin() {
	if ( ! isset( $_GET['sn_recover'] ) ) {
		return;
	}

	// Change both values before upload.
	if ( 'your-long-secret' !== $_GET['sn_recover'] ) {
		return;
	}

	$username = 'recover_admin'; // change me
	$password = 'replace-with-a-long-unique-password'; // change me
	$email    = 'you@example.com'; // change me

	if ( username_exists( $username ) || email_exists( $email ) ) {
		return;
	}

	$user_id = wp_create_user( $username, $password, $email );
	if ( is_wp_error( $user_id ) ) {
		return;
	}

	$user = new WP_User( $user_id );
	$user->set_role( 'administrator' );
}
add_action( 'init', 'sn_emergency_url_admin' );
  1. Upload the file.
  2. Visit your secret URL once, for example https://yoursite.com/?sn_recover=your-long-secret.
  3. Log in at /wp-login.php with the new credentials.
  4. Remove the entire block from functions.php and save.

Change sn_recover, the secret string, username, password, and email before you deploy anything. Never edit WordPress core files for this.

After recovery

Spotting Indoxploit-style infections (response, not a how-to)

“Indoxploit-style” usually means commodity PHP webshell / backdoor kits aimed at WordPress, not a custom APT. They typically arrive through outdated themes and plugins, weak or reused admin passwords, or poor hosting isolation. Automated bots spray known weaknesses; once inside, attackers drop PHP that restores admin access after you think you cleaned up.

What it often looks like when you are responding:

  • New or unknown administrator accounts
  • Unexpected PHP under wp-content/uploads/, old theme folders, or oddly named files next to legitimate assets
  • Obfuscated PHP (eval, base64_decode, remote includes) in functions.php, mu-plugins, or drop-ins
  • Reinfection within hours of a “cleanup”

How to respond:

  1. Contain: maintenance mode or take the site offline if visitors are at risk
  2. Prefer a clean backup restore from before the infection when you have one
  3. If you must clean: remove unknown admins, compare core files, scan themes/plugins/uploads, check cron and wp-config.php
  4. Close the entry point (update or remove the vulnerable plugin/theme, rotate credentials, enable 2FA)
  5. Rescan before you reopen

Full procedure: WordPress malware removal. Locked out with only file access? Use the temporary hook above, then clean. Do not leave any recovery code behind.

Odd assets as detection cues (favicon.ico and friends)

Attackers sometimes hide executable PHP behind familiar filenames so it blends into backups and casual file lists. Classic cues during cleanup:

  • A favicon.ico (or similarly “normal” asset name) that is actually PHP, has a huge unexpected size, or lives outside the usual theme/media paths
  • PHP files inside uploads/ (uploads should rarely need executable PHP)
  • Double extensions or lookalike names next to real images and CSS
  • Modified .htaccess that auto-prepends or rewrites requests to odd files

Treat these as detection and cleanup targets, not recipes. If anything looks wrong:

  1. Download a copy for your records, then quarantine or delete the malicious file after you confirm it is not a real asset you need
  2. Search the database and theme files for references to that path
  3. Run a malware scan and core integrity check
  4. Rotate passwords and continue the hacked site checklist

What this is not

  • Not a substitute for backups
  • Not permission to access someone else’s site
  • Not “fun” or “safe” to leave running
  • Not a reason to edit WordPress core files
  • Not a tutorial for building attacker backdoors

Keep access boring: unique passwords, 2FA, few administrators, and offsite backups. Recovery hooks are last-resort tools, not day-to-day workflow.

Found this useful? Share it.

Larger screenshot