DEV Community

Cover image for Renaming wp-login isn't the same as making wp-admin disappear
Calin V.
Calin V.

Posted on

Renaming wp-login isn't the same as making wp-admin disappear

"How do I hide wp-admin" is one of the most-searched WordPress security questions, and most answers give the same advice: install a plugin that renames your login URL. That advice isn't wrong. It's just answering a smaller question than the one being asked.

Renaming /wp-login.php to /my-login moves the login form. It does not change what answers at the old path, what your plugin folders advertise, or what your home page tells a scanner about the stack underneath. If your only problem is the password-guessing bot hammering the default form, a renamer solves it. If your problem is "stop my site from being identified and targeted as WordPress," you've solved maybe a third of it.

Here are the three leaks a login rename leaves open.

Leak 1: the old path still costs a full WordPress boot

When a login-URL renamer "blocks" the default path, the request to /wp-login.php still loads WordPress. PHP starts, the plugin stack initializes, and only then does the plugin decide to return a 404 to the logged-out visitor.

The visitor sees a 404. Your server still did the work of booting WordPress to produce it.

On a quiet site, nobody notices. On a site taking tens of thousands of probes a day, that's tens of thousands of full WordPress boots spent generating 404s. Your security dashboard's "attempts blocked" counter looks great. Your CPU graph disagrees.

The architectural alternative is to reject the request at the rewrite layer, before PHP runs:

# Apache .htaccess — reject the default login path at the server level
<IfModule mod_rewrite.c>
  RewriteEngine On
  RewriteCond %{REQUEST_URI} ^/(wp-login\.php|wp-admin) [NC]
  RewriteCond %{HTTP_COOKIE} !wordpress_logged_in [NC]
  RewriteRule .* - [R=404,L]
</IfModule>
Enter fullscreen mode Exit fullscreen mode
# nginx — same idea, requires a config reload after change
location ~* ^/(wp-login\.php|wp-admin) {
    if ($http_cookie !~* "wordpress_logged_in") { return 404; }
}
Enter fullscreen mode Exit fullscreen mode

The probe to the old path returns 404 from the server, WordPress never loads, and the request costs almost nothing. Same 404 the visitor sees, very different cost on your side, and anything that would have exploited a PHP-level flaw never reaches PHP. (Hand-rolling this is fine on a single site; the edge cases — AJAX on the front end, REST callbacks, WooCommerce account pages — are why people reach for a maintained tool once they run more than one site.)

Leak 2: your plugin and theme folders still announce the stack

Change the login URL and a bot that can't find the form doesn't quit your site. It pivots. The next cheap move is to fingerprint what you run, because a known-vulnerable plugin is a better door than a guessed password.

That fingerprinting reads paths your own HTML hands over:

/wp-content/plugins/woocommerce/
/wp-content/plugins/elementor/
/wp-content/themes/your-theme/style.css?ver=2.4.1
/wp-content/plugins/some-plugin/readme.txt   <-  version in plain text
Enter fullscreen mode Exit fullscreen mode

None of that is behind the login. It's in the page source of your home page. Patchstack counted 11,334 WordPress vulnerabilities disclosed in 2025, and 91% of them live in plugins rather than core. A scanner that reads your plugin inventory off the page source matches it against that disclosure list in milliseconds. Renaming the login form does nothing here, because the inventory never leaked through the login.

Closing this leak means relocating the plugin and theme paths and stripping the version strings, so the same scanner reads asset URLs that carry no wp-content, no plugin slug, and no version to match.

Leak 3: REST, AJAX, and the generator tag keep talking

Even with the form moved and the plugin paths changed, WordPress has a few other mouths:

<meta name="generator" content="WordPress 6.x" />
<link rel="https://api.w.org/" href="https://example.com/wp-json/" />
Enter fullscreen mode Exit fullscreen mode

The wp-json REST API answers at its canonical route and will, by default, enumerate usernames through /wp-json/wp/v2/users. admin-ajax.php sits at its default path. CMS detectors like Wappalyzer and BuiltWith key on exactly these signals. A login-URL renamer touches none of them, which is why a site with a renamed login but a default REST route still reads as unambiguous WordPress.

The honest comparison

Capability Login-URL renamer (e.g. WPS Hide Login) Path + fingerprint layer
Changes the login slug Yes Yes
Old path rejected before PHP loads No (WordPress boots, then 404s) Yes
Relocates wp-content / plugin / theme paths No Yes
Removes generator, ?ver=, RSD from output No Yes
Restricts wp-json username enumeration No Yes
Footprint Very light, single-purpose Heavier, broad config
Free tier Yes Yes

A renamer wins the footprint row honestly. All-in-One Security sits in between: it renames the login URL and adds a .htaccess firewall, but does less with the broader paths and the HTML fingerprint. None of this makes a renamer "bad." It makes it a different size of tool than the question usually wants.

How to test what you actually changed

One mistake to avoid: don't check your own site with Wappalyzer or BuiltWith while logged into wp-admin. The admin screens emit WordPress signals you can't strip, so you'll always see "WordPress" and conclude nothing worked. Test in a clean incognito window, logged out, and check:

# Generator tag and REST link still present?
curl -s https://example.com/ | grep -iE 'generator|api.w.org|/wp-json'

# Default login path still booting WordPress instead of a server 404?
curl -s -o /dev/null -w "%{http_code}\n" https://example.com/wp-login.php

# Username enumeration via REST still open?
curl -s https://example.com/wp-json/wp/v2/users
Enter fullscreen mode Exit fullscreen mode

If the first command returns matches, your fingerprint is still readable. If the second returns 200 (or a slow 404), PHP is still booting for that path. If the third returns a user list, enumeration is open. A login rename leaves all three exactly as they were.

Renaming the form is a reasonable first move. Just measure it for what it is: one URL moved, not a stack reconfigured.

What does your current setup return for those three curl checks — and were you surprised?

Top comments (0)