Прежде чем подбирать пароль, злоумышленнику нужно узнать имя пользователя. На стандартном сайте WordPress получить его проще простого, и для атакующего это не стоит ровным счетом ничего. Поэтому первое, что я проверяю на переданном мне сайте, — это то, сколько имен пользователей он отдаёт даром.

Существует четыре основных пути раскрытия. Вы можете проверить каждый из них с помощью curl с устройства, на котором не выполнена авторизация.

1. Архив автора

Запросите автора по его числовому ID, и WordPress перенаправит вас на архив этого автора, содержащий логин прямо в URL:

 curl -s -o /dev/null -w "%{http_code} %{redirect_url}\n" "https://example.com/?author=1"
 

Ответ  301  на запрос  https://example.com/author/johnd/  только что сообщил вам, что пользователь с ID 1 логинится как  johnd . Бот просто перебирает ID по порядку, начиная с 1, и собирает все имена, на которые происходит редирект.

Решение (если вы специально не публикуете страницы авторов) — отклонять запросы к архивам авторов для неавторизованных посетителей:

 <?php
add_action( 'template_redirect', function () {
    if ( is_author() && ! is_user_logged_in() ) {
        wp_redirect( home_url(), 301 );
        exit;
    }
} );
 

Если же вы используете страницы авторов, измените базовый URL авторов и публичный слаг вместо полной их блокировки.

2. Эндпоинт users в REST API

 curl -s "https://example.com/wp-json/wp/v2/users" | head
 

JSON-массив с  id ,  name  и  slug  для каждого автора — это та же самая утечка, но в более удобной обёртке. Проверяйте и вариант с query-параметрами, так как блокировка, настроенная только на  /wp-json/ , пропустит его:

 curl -s -o /dev/null -w "%{http_code}\n" "https://example.com/?rest_route=/wp/v2/users"
 

Отключите эндпоинты пользователей для гостей с помощью фильтра  rest_endpoints :

 <?php
add_filter( 'rest_endpoints', function ( $endpoints ) {
    if ( ! is_user_logged_in() ) {
        unset( $endpoints['/wp/v2/users'] );
        unset( $endpoints['/wp/v2/users/(?P<id>[\d]+)'] );
    }
    return $endpoints;
} );
 

3. Встроенная карта сайта (sitemap)

Начиная с версии WordPress 5.5, в встроенной карте сайта появился раздел пользователей:

 curl -s -o /dev/null -w "%{http_code}\n" "https://example.com/wp-sitemap-users-1.xml"
 

Запрос  200  отображает список ваших авторов для любого желающего и для поисковых систем. Отключите именно этот провайдер:

 <?php
add_filter( 'wp_sitemaps_add_provider', function ( $provider, $name ) {
    return ( 'users' === $name ) ? false : $provider;
}, 10, 2 );
 

4. Форма входа

Этот способ проверяется вручную, а не через curl. Введите несуществующее имя, и WordPress выведет: «The username is not registered». Введите имя существующего пользователя с неверным паролем, и появится сообщение: «The password you entered is incorrect». В этой разнице и кроется подтверждение реальных логинов. Настройте форму так, чтобы в обоих случаях выводилось одно и то же общее сообщение.

Ошибка, сводящая на нет защиту трёх предыдущих путей

Если ваш логин —  john , и в подписи к каждой статье отображается  john , перекрытие трёх вышеописанных путей мало что даст. Имя пользователя и так выведено на странице. Откройте свой профиль, установите публично отображаемое имя, отличающееся от логина, и по возможности создавайте аккаунт с логином, который изначально не является настоящим именем.

Зачем этим заниматься, если имя пользователя — это лишь половина данных для входа?

Потому что подобрать вторую половину намного проще, когда имя уже известно. В отчете Verizon Data Breach Investigations Report за 2025 год украденные учетные данные фигурировали в 88% базовых атак на веб-приложения. Зная реальное имя пользователя, атакующий переходит от перебора по тысячам аккаунтов к точечной атаке на один конкретный профиль — как правило, администратора.

Проведите эти четыре проверки на одном из своих сайтов прямо сегодня, затем повторите их после исправления и сохраните результаты до и после. А какие еще способы утечки имени пользователя в WordPress вы встречали, помимо описанных в статье?