Защита сайтов на WordPress с помощью Fail2Ban

Автор: Андрей Торженов

Обновление от:

Сейчас все западные СМИ кричат о «русских хакерах», как они всё взламывают и ни кому жить спокойно не дают, а мне жить мешают американские хакеры! 🙂  Мои сайты на WordPress пытаются ломать с американских IP адресов (очень серьёзно не воспринимайте мои слова, это больше шутка, понятно что это не хакеры, а взломанные компьютеры/сайты, но IP действительно из USA, как тут не подколоть 🙂 ).

Мой VDS находится под мониторингом Zabbix’а. Вчера (24/06/2017) я стал активно получать на почту сообщения о большой загрузке сервера. Первое время я игнорировал эти сообщения, т.к. подобное происходило и ранее, но быстро проходило. Кратковременные всплески нагрузки на сервер понятны и допустимы.

Но сейчас данная проблема не исчезала, Zabbix всё настойчивей информировал меня о проблеме.

Я не выдержал и зашел на Zabbix посмотреть графики загрузки.

CPU Utilization

CPU Utilization

CPU Load

CPU Load

То, что я увидел, меня немножко поразило. Идёт постоянная, 100% загрузка CPU пользовательскими процессами (первый график, синий цвет) и резко вырос CPU Load (второй график).

Начиная с 18:00, я поборол попытки взлома и загрузка процессора упала до нормального уровня.

Использовав команду top, я обнаружил, что нагрузку создает процесс httpd (Apache). Это было ожидаемо, больше на сервере ни чего нет, но я не предполагал, что мои скромные сайты, с малой посещаемостью так могут нагрузить сервер. Тут закрались сомнения…

Я полез в логи Apache, запустил Server-Status и увидел, что на одном из моих вириальных хостов, с различных американских IP, каждую секунду долбятся на страницу авторизации WordPress.

...
142.54.188.122 - - [25/Jun/2017:03:07:12 +0300] "GET /wp-login.php HTTP/1.0" 200 12665 "-" "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; .NET CLR 1.0.3705;)"
142.54.188.122 - - [25/Jun/2017:03:07:13 +0300] "POST /wp-login.php HTTP/1.0" 200 12991 "http://4ham.ru/wp-login.php" "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; .NET CLR 1.0.3705;)"
142.54.188.122 - - [25/Jun/2017:03:07:15 +0300] "POST /xmlrpc.php HTTP/1.1" 403 212 "-" "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)"
142.54.188.122 - - [25/Jun/2017:03:07:15 +0300] "GET /wp-login.php HTTP/1.0" 200 12666 "-" "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; .NET CLR 1.0.3705;)"
142.54.188.122 - - [25/Jun/2017:03:07:16 +0300] "POST /wp-login.php HTTP/1.0" 200 12991 "http://4ham.ru/wp-login.php" "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; .NET CLR 1.0.3705;)"
142.54.188.122 - - [25/Jun/2017:03:07:18 +0300] "POST /xmlrpc.php HTTP/1.1" 403 212 "-" "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)"
142.54.188.122 - - [25/Jun/2017:03:07:18 +0300] "GET /wp-login.php HTTP/1.0" 200 12667 "-" "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; .NET CLR 1.0.3705;)"
142.54.188.122 - - [25/Jun/2017:03:07:19 +0300] "POST /wp-login.php HTTP/1.0" 200 12990 "http://4ham.ru/wp-login.php" "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; .NET CLR 1.0.3705;)"
142.54.188.122 - - [25/Jun/2017:03:07:21 +0300] "POST /xmlrpc.php HTTP/1.1" 403 212 "-" "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)"
142.54.188.122 - - [25/Jun/2017:03:07:21 +0300] "GET /wp-login.php HTTP/1.0" 200 12667 "-" "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; .NET CLR 1.0.3705;)"
142.54.188.122 - - [25/Jun/2017:03:07:22 +0300] "POST /wp-login.php HTTP/1.0" 200 12991 "http://4ham.ru/wp-login.php" "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; .NET CLR 1.0.3705;)"
142.54.188.122 - - [25/Jun/2017:03:07:24 +0300] "POST /xmlrpc.php HTTP/1.1" 403 212 "-" "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)"
...

Тут приведен фрагмент только с одним IP адресом, на самом деле их больше.

С помощью команды whois я узнал кому принадлежит IP адрес атакующего (на тот момент, ещё предполагаемого атакующего, т.к. я ещё точно не знал, что он делает и какая его цель).

# whois 142.54.188.122

[Querying whois.arin.net]
[whois.arin.net]
...
NetRange: 142.54.160.0 - 142.54.191.255
CIDR: 142.54.160.0/19
NetName: DSV4-4
NetHandle: NET-142-54-160-0-1
Parent: NET142 (NET-142-0-0-0-0)
NetType: Direct Allocation
OriginAS: AS33387
Organization: DataShack, LC (DL-9)
RegDate: 2012-05-18
Updated: 2012-05-18
Ref: https://whois.arin.net/rest/net/NET-142-54-160-0-1

OrgName: DataShack, LC
OrgId: DL-9
Address: 1321 Burlington
Address: Suite 501
City: North Kansas City
StateProv: MO
PostalCode: 64116
Country: US
RegDate: 2011-03-15
Updated: 2016-03-29
Comment: http://www.nocix.net
Ref: https://whois.arin.net/rest/org/DL-9

Как видим выше данный IP адрес принадлежит сети расположенной в США (поле Country), там есть и другая информация (например название компании кому принадлежит сеть, адрес и т.д.)

Я не особо боялся, что меня взломают. Со стороны WordPress стоят различные средства защиты от взлома (плагины Limit Attempts и Google Captcha (reCAPTCHA)). Они прекрасно защищают, но ни как не помогают снизить нагрузку на сервер когда происходит массированная атака. Атаку отбивает сам WordPress, при попытке подбора пароля (брутфорс) он блокирует IP атакующего добавляя его в чёрный список доступа к сайту, т.е. выполняет функцию схожую с Firewall, но при этом потребляет уйму ресурсов.

Нужно защищать на более низком, сетевом уровне. Я решил применить fail2ban в связке с iptables, который уже установлен и защищает SSH, а теперь пришло время защищать и Apache.

Приступим к настройке

Необходимо, что бы WordPress писал в лог файл информацию о неудачной попытке аутентификации. В дальнейшем, эту информацию будет использовать Fail2ban для добавления IP адреса злоумышленника в iptables (firewall).

Установка плагина для WordPress

Устанавливаем и активируем в WordPress плагин WP fail2ban. Он как раз и занимается тем, что пишет в лог файл сообщения о не удачных аутентификации.

В какой лог файл будет писаться сообщения зависит от настройки syslog. Плагин пишет в LOG_AUTH. В CentOS 7 сообщения пишутся в /var/log/messages.

Установив плагин в логах я сразу увидел множество подобных записей:

Jun 25 19:32:38 2keep wordpress(4ham.ru)[6011]: Authentication attempt for unknown user admin123 from 142.54.171.66
Jun 25 19:32:39 2keep wordpress(4ham.ru)[6827]: Authentication failure for UserLogin from 107.150.58.178
Jun 25 19:32:39 2keep wordpress(4ham.ru)[6827]: Authentication failure for UserLogin from 142.54.188.122

Теперь стало видно, что атакующие пытаются подобрать имя пользователя (admin123) для доступа к сайту и подобрать пароль к существующему пользователю (UserLogin) на сайте.

Установка и настройка fail2ban

Если fail2ban у вас не установлен, то устанавливаем

yum install epel-release
yum install fail2ban
systemctl enable fail2ban

и приступаем к настройке.

Благодаря плагину WP fail2ban, нам известны IP адреса атакующих, теперь необходимо корректно настроить фильтр для fail2ban.

В комплекте с плагином WP fail2ban идёт готовый фильтр, но он какой-то недоделанный. Он не анализирует строку с неверной аутентификацией существующего пользователя:

Jun 25 19:32:39 2keep wordpress(4ham.ru)[6827]: Authentication failure for UserLogin from 142.54.188.122

а это то, ради чего всё и затевалось! Слегка подредактиуем фильтр под наши задачи.

Копируем фильтр из подкаталога плагина в подкаталог фильтров fail2ban:

cp wp-content/plugins/wp-fail2ban/filters.d/wordpress-hard.conf /etc/fail2ban/filter.d

Добавляем в фильтр дополнительное регулярно выражение: 

^%(__prefix_line)sAuthentication failure for .* from <HOST>$

Мой фильтр выглядит следующим образом:

# Fail2Ban filter for WordPress hard failures
#

[INCLUDES]

before = common.conf

[Definition]

_daemon = (?:wordpress|wp)

failregex = ^%(__prefix_line)sAuthentication attempt for unknown user .* from <HOST>$
            ^%(__prefix_line)sAuthentication failure for .* from <HOST>$
            ^%(__prefix_line)sBlocked user enumeration attempt from <HOST>$
            ^%(__prefix_line)sBlocked authentication attempt for .* from <HOST>$
            ^%(__prefix_line)sPingback error .* generated from <HOST>$
            ^%(__prefix_line)sSpam comment \d+ from <HOST>$
            ^%(__prefix_line)sXML-RPC authentication attempt for unknown user .* from <HOST>$
            ^%(__prefix_line)sXML-RPC multicall authentication failure from <HOST>$

ignoreregex =

Настраиваем конфигурационный файл fail2ban /etc/fail2ban/jail.conf

Добавляем секцию:

[wordpress-hard]

enabled = true
filter = wordpress-hard
logpath = /var/log/messages
action   = iptables-multiport[name=APACHE, port="http,https", protocol=tcp]
           sendmail-whois[name=WordPress, dest=your@email.local]
maxretry = 3
findtime  = 7200
# bantime: 1 year
bantime = 31536000

  • port — блокируем сразу для двух портов 80 и 443;
  • dest — email на который будут приходить отчёты о бане IP;
  • maxretry — после какого количества неудачных попыток аутентификации, будет забанен IP;
  • findtime — время в секундах, в течение которого учитывается maxretry (сейчас у ботов пошла новая стратегия по подбору паролей, они делают две попытки, потом ждут час и опять две попытки, так что лучше это параметр установить минимум на два часа [08/11/2018]);
  • bantime  — на сколько секунд банить IP (в моём случае на 1 год).

Перезапускаем fail2ban:

systemctl restart fail2ban

Мониторинг работы fail2ban

Настройка закончена, теперь посмотрим, что происходит с атаками на нас.

Смотрим лог fail2ban /var/log/fail2ban.log:

2017-06-25 19:57:21,767 fail2ban.jail    [9510]: INFO    Creating new jail 'wordpress-hard'
2017-06-25 19:57:21,768 fail2ban.jail    [9510]: INFO    Jail 'wordpress-hard' uses poller {}
2017-06-25 19:57:21,770 fail2ban.jail    [9510]: INFO    Initiated 'polling' backend
2017-06-25 19:57:21,812 fail2ban.filter  [9510]: INFO    Added logfile = /var/log/messages
2017-06-25 19:57:21,815 fail2ban.filter  [9510]: INFO    Set maxRetry = 3
2017-06-25 19:57:21,820 fail2ban.filter  [9510]: INFO    Set jail log file encoding to UTF-8
2017-06-25 19:57:21,822 fail2ban.actions [9510]: INFO    Set banTime = 3600
2017-06-25 19:57:21,836 fail2ban.filter  [9510]: INFO    Set findtime = 120
2017-06-25 19:57:22,582 fail2ban.jail    [9510]: INFO    Jail 'wordpress-hard' started
2017-06-25 19:57:24,271 fail2ban.actions [9510]: NOTICE  [wordpress-hard] Ban 142.54.171.66
2017-06-25 19:57:27,501 fail2ban.filter  [9510]: INFO    [wordpress-hard] Found 107.150.58.178с
2017-06-25 19:57:27,504 fail2ban.filter  [9510]: INFO    [wordpress-hard] Found 69.197.132.42
2017-06-25 19:57:28,527 fail2ban.filter  [9510]: INFO    [wordpress-hard] Found 107.150.58.194
2017-06-25 19:57:29,547 fail2ban.filter  [9510]: INFO    [wordpress-hard] Found 142.54.188.122
2017-06-25 19:57:29,549 fail2ban.filter  [9510]: INFO    [wordpress-hard] Found 142.54.171.66
2017-06-25 19:57:45,868 fail2ban.filter  [9510]: INFO    [wordpress-hard] Found 107.150.58.194
2017-06-25 19:57:45,988 fail2ban.filter  [9510]: INFO    [wordpress-hard] Found 142.54.188.122
2017-06-25 19:57:45,988 fail2ban.filter  [9510]: INFO    [wordpress-hard] Found 69.197.132.42
2017-06-25 19:57:45,989 fail2ban.filter  [9510]: INFO    [wordpress-hard] Found 107.150.58.178
2017-06-25 19:57:58,154 fail2ban.filter  [9510]: INFO    [wordpress-hard] Found 107.150.58.178
2017-06-25 19:57:58,164 fail2ban.filter  [9510]: INFO    [wordpress-hard] Found 69.197.132.42
2017-06-25 19:57:58,164 fail2ban.filter  [9510]: INFO    [wordpress-hard] Found 107.150.58.194
2017-06-25 19:57:59,096 fail2ban.actions [9510]: NOTICE  [wordpress-hard] Ban 69.197.132.42
2017-06-25 19:57:59,233 fail2ban.filter  [9510]: INFO    [wordpress-hard] Found 142.54.188.122
2017-06-25 19:58:01,585 fail2ban.actions [9510]: NOTICE  [wordpress-hard] Ban 107.150.58.194
2017-06-25 19:58:04,167 fail2ban.actions [9510]: NOTICE  [wordpress-hard] Ban 107.150.58.178
2017-06-25 19:58:06,178 fail2ban.actions [9510]: NOTICE  [wordpress-hard] Ban 142.54.188.122
2017-06-25 19:58:09,281 fail2ban.filter  [9510]: INFO    [wordpress-hard] Found 142.54.188.122
2017-06-25 20:02:57,933 fail2ban.filter  [9510]: INFO    [wordpress-hard] Found 36.70.184.77

Видим, что fail2ban подгрузил наш фильтр wordpress-hard, сразу увидел попытки взлома и при превышении количества попыток банит (блокирует) IP.

Смотрим какие IP уже забаненны:

# fail2ban-client status wordpress-hard

Status for the jail: wordpress-hard
|- Filter
|  |- Currently failed: 1
|  |- Total failed:     15
|  `- File list:        /var/log/messages
`- Actions
   |- Currently banned: 5
   |- Total banned:     5
   `- Banned IP list:   142.54.171.66 69.197.132.42 107.150.58.194 107.150.58.178 142.54.188.122

Смотрим, что в iptables:

# iptables -L -nv

Chain INPUT (policy ACCEPT 383 packets, 21828 bytes)
 pkts bytes target     prot opt in     out     source               destination
 427K   40M f2b-APACHE  tcp  --  *      *       0.0.0.0/0            0.0.0.0/0            multiport dports 80,443

Chain f2b-HTTP (1 references)
 pkts bytes target     prot opt in     out     source               destination
   94  4632 REJECT     all  --  *      *       142.54.188.122       0.0.0.0/0            reject-with icmp-port-unreachable
   94  4644 REJECT     all  --  *      *       107.150.58.178       0.0.0.0/0            reject-with icmp-port-unreachable
   95  4696 REJECT     all  --  *      *       107.150.58.194       0.0.0.0/0            reject-with icmp-port-unreachable
   94  4656 REJECT     all  --  *      *       69.197.132.42        0.0.0.0/0            reject-with icmp-port-unreachable
   99  4896 REJECT     all  --  *      *       142.54.171.66        0.0.0.0/0            reject-with icmp-port-unreachable
 2345  519K RETURN     all  --  *      *       0.0.0.0/0            0.0.0.0/0

Вот они, все забаненные тут видны…

Теперь у меня тишины в логах и загрузка процессора опустилась до нормальных пределов.

Загрузка CPU после установки fail2ban

Загрузка CPU после установки fail2ban

Периодически на почту приходят сообщения о новых забаненных IP.

Статистика за неделю

За неделю заблокировано всего 25  IP адресов… но эти IP адреса очень активно ломали сайт. После их блокировки, сайт стал работать значительно быстрей, т.к. снизилась нагрузка на сервер.

The following two tabs change content below.
В профессиональной сфере занимаюсь всем, что связанно с IT. Основная специализация - VoIP и сети передачи данных. Стараюсь не заниматься Windows серверами (но иногда приходится) и 1С.

Добавить комментарий