| 开发者 | webmastersteam |
|---|---|
| 更新时间 | 2026年11月12日 23:23 |
| 捐献地址: | 去捐款 |
| PHP版本: | 8.0 及以上 |
| WordPress版本: | 7.1 |
| 版权: | GPLv2 or later |
| 版权网址: | 版权信息 |
wp-config.php, or .htaccess. Everything works through WordPress hooks and can be disabled at any moment with a single click.
The plugin is completely free, without a PRO version, without ads, and without sending data to external servers. Built by the Webmasters.Team crew for daily WordPress work.
Modules
xmlrpc.php (403) and filters the XML-RPC methods. Stops brute-force attacks through the most attacked WordPress endpoint./wp/v2/users in the REST API for unauthenticated users./?author=1 and author archive URLs to the homepage for visitors who are not logged in, and removes the users sitemap (another enumeration vector).author_name and author_url from oEmbed responses (WPScan-detectable user-enumeration vector) and drops the oEmbed discovery <link> tags from <head>.<meta name="generator"> tag and redundant meta tags (wlwmanifest, rsd, shortlink), and replaces the ?ver= values of front-end assets with a short keyed hash: the versions are not revealed, but the value still changes after every update, so browsers and caches load the new files.X-Pingback HTTP header from all responses.wp_options), with hourly cleanup of old entries.DISALLOW_FILE_EDIT, hiding the theme and plugin editor in the admin (an attacker who compromises an account cannot inject a backdoor through the browser).X-Frame-Options, X-Content-Type-Options, Referrer-Policy, Permissions-Policy, optionally HSTS (use with care because browsers cache it for a year) with a separate opt-in for includeSubDomains. HSTS is also sent when HTTPS ends at Cloudflare or at a trusted reverse proxy (X-Forwarded-Proto).__()/esc_html__(), a POT file for translators and a bundled Polish translation.wt-hardening folder to wp-content/plugins/ on your server.No. Everything is wired through WordPress hooks. Deactivating the plugin instantly reverts all changes (except HSTS, which browsers cache, so enabling HSTS is a conscious decision).
Possibly, if you actually rely on them. Disable the XML-RPC module in the settings. The other protection layers stay active.
The table stays in the database (useful for later analysis). On full uninstall the tables are dropped cleanly.
Tested on a single-site install. Settings, tables and cleanup jobs are per site; tables are created on each site the first time the plugin runs there, and uninstalling removes the data from every site of the network. Multisite is not yet formally supported, so file an issue if something breaks.
Wait until the lockout expires, log in from another network (e.g. your phone’s mobile data), or ask another administrator to click Unlock under Webmasters.Team → WT Hardening → Login log tab. With WP-CLI access you can remove the lockout directly: wp db query "DELETE FROM wp_wt_hardening_lockouts WHERE ip='1.2.3.4'" (adjust the table prefix; for IPv6 use the /64 network shown in the log, e.g. 2001:db8:1:2::/64). Add your office IP to the allowlist to avoid this in the future.
Nothing. Since 1.1.1 Cloudflare is recognised automatically. When a request comes from Cloudflare’s published IP ranges (updated weekly from cloudflare.com, with a bundled copy as fallback), the visitor address is taken from the CF-Connecting-IP header, also with Site behind Cloudflare / proxy left at No. The header is ignored for requests from any other address, so it cannot be spoofed by hitting your server directly. Choosing Cloudflare explicitly works the same way. Without this every visitor would appear with a Cloudflare IP, so one attacker could lock everyone out.
Set Site behind Cloudflare / proxy to Reverse proxy on the local network. X-Forwarded-For is then trusted only from private-network addresses. When the plugin sees such a proxy while the setting is still No, it shows a notice on its admin pages.
Modules only register the hooks they actually need. The event log is a single INSERT per event. No scanner, no background work beyond an hourly and daily cleanup of old rows. Real impact on response time: under 1 ms.
Because Strict-Transport-Security has a sticky effect (browsers remember the header for a year). Enabling it too early (before your entire traffic works on HTTPS without errors) can lock users out of the site for a long time. Turn it on once HTTPS is rock-solid. includeSubDomains is a separate setting (off by default) because it also forces HTTPS on every subdomain; preload is never added.
The header is sent only over HTTPS. When HTTPS ends at a proxy, WordPress sees plain HTTP and the plugin relies on the X-Forwarded-Proto: https header, but only from a proxy it trusts: Cloudflare’s IP ranges (always) or, with Site behind Cloudflare / proxy set to Reverse proxy on the local network, a private-network address. From any other address the header is ignored, so it cannot be spoofed.
wp_create_user()?No. The policy hooks into form validation (profile, registration, reset) and the REST API users endpoints. Programmatic user creation bypasses these hooks by design. For a typical client workflow (users are created through the admin panel) this is enough.
The login limiter stores the IP address and the login typed in failed attempts (kept for the configured counter window, at most 7 days) and in lockouts (kept until 24 hours after they end). The event log stores the user, IP address and event details, including logins typed in failed attempts and the email of new users (kept for the configured retention, 30 days by default). Everything stays in your database. The data is included in Tools → Export Personal Data, and Tools → Erase Personal Data deletes the person’s event log entries and removes their login from attempts and lockouts. The attempt and lockout records themselves, with their IP addresses, are kept until they expire (a security log); the erase tool reports them as retained and explains why. Mention the login security log in your privacy policy: the plugin adds suggested text with the current retention periods to Settings → Privacy → Policy guide.
network on plugin activation) instead of an empty value.wt_hardening_limit_application_passwords filter.wt_hardening_lockout action now receives the network (e.g. 2001:db8:1:2::/64)./?author=1 no longer reveals the login. WordPress redirected it to /author/<login>/ before the author archive module ran; the module now redirects first. Author URLs of logins that do not exist are redirected the same way (a 301 vs 404 difference revealed which logins exist), and the users sitemap is removed while the module is on./wp/v2/users, /wp/v2/users/me), which previously accepted any password.invalid_credentials error (401) for an unknown username, an unknown email and a wrong password, and XML-RPC returns the same fault for both. Failed attempts are still counted by the login limiter.includeSubDomains is now a separate setting (HSTS: include subdomains). Sites that already had HSTS enabled keep sending it after the update; new installations start with it off, because it forces HTTPS on every subdomain. preload is never added.X-Forwarded-Proto: https. The header is ignored from other addresses, also in the default mode.CF-Connecting-IP in this mode too; the header is ignored for requests from any other address. The Cloudflare and Reverse proxy modes work as before.wt_hardening_update_cloudflare_ranges filter.X-Forwarded-For / X-Real-IP) while “Site behind Cloudflare / proxy” is set to No.::ffff:203.0.113.5). On servers that report clients this way, the “reverse proxy” mode treated every visitor as a local proxy and trusted a spoofed X-Forwarded-For, which allowed bypassing the login limiter.?ver= in wp-admin, so the block editor does not load stale cached files after updates.?ver= from front-end assets, which kept visitors on stale cached CSS/JS after updates. The value is now replaced with a 10-character hash keyed with the site’s secret salts: it does not reveal the WordPress, plugin or theme version, but changes whenever the asset version changes.Webmasters\Security to WebmastersTeam\Hardening); old names kept as aliases for this release. Option, table, hook and cron names are unchanged.CF-Connecting-IP only from Cloudflare’s IP ranges, proxy mode trusts X-Forwarded-For only from private-network proxies. Replaces the need for the wt_hardening_trust_proxy_headers filter (still supported).wt_hardening_lockout and wt_hardening_unlocked actions.X-Forwarded-For, CF-Connecting-IP and X-Real-IP request headers unconditionally. On any site that is not behind a trusted reverse proxy those headers are attacker-controlled, which allowed the brute-force protection to be bypassed (rotate the header and every attempt is counted as a fresh IP), allowed an attacker to lock out a chosen account, and allowed the IP stored in the security event log to be forged. The client IP is now read from REMOTE_ADDR by default; proxy headers are honoured only when you opt in via the new wt_hardening_trust_proxy_headers filter (return true when WordPress runs behind Cloudflare, nginx or a load balancer that sets those headers).mb_strlen) rather than bytes, so multibyte passwords are validated correctly against the policy.author_name and author_url from oEmbed JSON responses (a low-effort user-enumeration vector automatically picked up by WPScan) and drops the oEmbed discovery <link> tags from <head> to reduce the public surface. Enabled by default.EventsPage).parse_url() with wp_parse_url() in the XML-RPC module.uninstall.php and add safe-query annotations.