Личный опыт Andrew Rudenko
2 661

Полный Кузнец, или как мы отразили DDoS-атаку и нашли дыру в WordPress

Недавно компания «Лайв Тайпинг» впервые стала жертвой DDoS-атаки, что сделало наш сайт недоступным для простых пользователей. Обошлось без утечки данных, но ситуация всё равно неприятная. Эта статья написана для всех, кто ещё не столкнулся, но может столкнуться с DDoS-атаками: для владельцев сайтов, блогов или изданий любого масштаба.

В закладки

Также мы хотим обратиться к тем, чей сайт работает на WordPress, потому что принцип атаки был построен на уязвимости этой CMS. Мы считаем, что наша история дополняет карточки «Медузы» о том, что могут сделать хакеры с вашим интернет-ресурсом. Если после прочтения вы примените все новые знания, то в час Х обойдётесь без паники и траты времени. Мы вот не обошлись.

Появление Кузнеца

Всё началось с того, что нашей коллеге, ответственной за работу с клиентами, пришло вот такое сообщение в Telegram:

За этим удалённым аккаунтом стоял некто под ником Кузнец, и он не врал: нас действительно атаковали. Прежде мы не считали нужным обезопасить себя от DDoS-атак — зачем, если у нас обычный корпоративный сайт, а не сервис с высокой посещаемостью?

О Кузнеце нужно было узнать хоть что-нибудь. Для этого наш PHP-разработчик, интересующийся разного рода атаками и уязвимостями, покопался в логах сервера, на котором находится сайт livetyping.com. За пару-тройку дней набрался 800-мегабайтный архив, скрывавший в себе 11 гигабайт данных о том, кто, когда и откуда заходил на наш сайт.

Самым интересным в них оказалось то, что превалирующими были запросы через UserAgent WordPress; иначе говоря, наш сайт валил трафик с сайтов, построенных на WordPress. Их оказалось примерно три тысячи.

В результате мы обнаружили нечто более интересное, чем просто взлом.

Первая волна атак: дыра в WordPress

У каждого из сайтов был включен интерфейс для удалённого управления платформой через POST-запросы по протоколу XML-RPC. Протокол включен по умолчанию и в обычной жизни используется, допустим, для размещения и удаления постов на WordPress-сайте, когда админ-панель недоступна. Но исследования публикаций на эту тему показали, что уже несколько лет злоумышленники используют XML-RPC для DDoS-атак.

Кузнец поступил так же. Из собранных WordPress-сайтов с включенным протоколом он сделал ботнет, чтобы отправлять запросы нашему сайту. Механика такая: атакующий обращался к этим сайтам, посылая в запросе .XML-строчку с адресом livetyping.com, и после рассылки все WordPress-сайты начинали его пинговать.

Если проще, то три тысячи WP-сайтов разом посылали запросы сайту livetyping.com, сервер не выдержал постоянной активности, перестал отвечать на все приходящие запросы, и сайт оказался недоступен.

Чтобы отразить эту атаку, мы включили на сервере фильтр по UserAgent WordPress. Кузнец это понял и сменил тактику.

Вторая волна атак: запросы со всего света

Природу этой волны мы установить не смогли. По логам, например, было видно, что запросы идут с адресов, которые поставили себе программу для шпионажа за пользователями, и к бреши в WordPress это уже не имело отношения. Источником запросов были разные страны, и для фильтрации мы подключили бесплатный пакет сервиса CloudFlare.

CloudFlare пропускает трафик с сайта через свои центры данных, которые фильтруют запросы, похожие на DDoS-атаки. Под защитой у сервиса находятся данные таких компаний, как Uber, 1Password и Avito.

Атака была нарастающей — сначала из одной страны, потом из других. Фронтенд-разработчик вручную банил все подозрительные страны с большим количеством запросов, кроме России (Румыния, Бразилия, Албания, Индия, Индонезия и т.д.). Бан срабатывал по правилам, заданным в JavaScript Challenge. Это опция CloudFlare, с помощью математических операций проверяющая, кто пытается зайти на сайт — живой человек или вредный бот.

Во время проверки сайт на пять секунд блокируется такой вот заглушкой:

Через пять секунд CloudFlare делает редирект запроса на сайт при условии, что IP-адрес удачно прошёл JavaScript Challenge и признан безопасным.

В настройках JavaScript Challenge разработчик вносит подозрительные страны, запросы из которых считаются нелегитимными.

Когда радостей бесплатного CloudFlare нам стало не хватать, мы купили тариф Pro стоимостью $20 в месяц. К защите от DDoS, пропуску трафика через CDN-сеть и бесплатному SSL-сертификату добавилась система защиты Web Application Firewall, спасающая от SQL-инъекций и прочих атак, несущих сайту неприятности.

CloudFlare: за и против

До подключения CloudFlare мы боролись с Кузнецом своими силами, но увы, сервер просто проседал от кучи запросов. DigitalOcean, на котором находится наш сайт, из коробки ничего для защиты не предоставляет; максимум, что мы могли бы сделать — это размазать нагрузку по нескольким серверам, но в любом случае это лишь помогло бы принять такой объём запросов, а не добавить защиты. Поэтому понадобился сервис узкого назначения, чья миссия — фильтровать трафик. Им и стал CloudFlare.

Но вместе с избавлением от Кузнеца CloudFlare создал нам несколько проблем:

  • если в браузере включено VPN-расширение, то зайти на livetyping.com и в административную панель не получится. Одна из точек входа для большинства VPN-сервисов — это Румыния. Она же оказалась одной из популярнейших стран в ботнете Кузнеца и расценивается CloudFlare как подозрительная;
  • пострадала конверсия сайта, ведь не всякий реальный пользователь согласен ждать пять секунд;
  • CloudFlare — не только не самая надёжная защита, но и потенциально не работающая в России: часть IP-адресов сервиса находится в реестрах Роскомнадзора, и если попасть на такие адреса, то можно оказаться под блокировкой.

Фильтрация CloudFlare из коробки довольно примитивна и для нас это скорее компромисс. Если вы хотите сервис, который постоянно отслеживал бы вредоносные страницы, подключите QRator, который позиционирует себя как главного по борьбе с DDoS у нас в стране.

Заключение

Посчитаем траты с нашей стороны:

  • $20 за PRO-пакет CloudFlare. По курсу доллара на 28 сентября 2018 года это 1317 рублей;
  • 13 тысяч рублей за 13 часов работы трёх сотрудников компании, ставка 1000 рублей/час.

Итого: 14 317 рублей.

$500, которые с нас запросил Кузнец — это 32 934 рубля. Отказав ему, мы сэкономили 18 617 рублей, получили новый профессиональный опыт и поделились им с вами. Сохранённое чувство собственного достоинства оценке не поддаётся.

Сайт работает, злоумышленник остался ни с чем, а через базу WordPress-сайтов с работающим скриптом мы теперь диктуем свою непреклонную волю остальному мировому сообществу (в смысле, можем сами ддосить всех направо и налево).

Но вместо этого лучше предупредим: если ваш сайт работает на WordPress, его могут использовать во вред другим, а после он окажется заблокированным. Поэтому либо воспользуйтесь руководством о том, как отключить XML-RPC, либо делайте статичные сайты на конструкторах вроде Tilda.

Следите за собой, будьте осторожны.

Материал опубликован пользователем. Нажмите кнопку «Написать», чтобы поделиться мнением или рассказать о своём проекте.

Написать
{ "author_name": "Andrew Rudenko", "author_type": "self", "tags": [], "comments": 9, "likes": 26, "favorites": 20, "is_advertisement": false, "subsite_label": "life", "id": 46357, "is_wide": false, "is_ugc": true, "date": "Fri, 28 Sep 2018 14:15:47 +0300" }
{ "id": 46357, "author_id": 37239, "diff_limit": 1000, "urls": {"diff":"\/comments\/46357\/get","add":"\/comments\/46357\/add","edit":"\/comments\/edit","remove":"\/admin\/comments\/remove","pin":"\/admin\/comments\/pin","get4edit":"\/comments\/get4edit","complain":"\/comments\/complain","load_more":"\/comments\/loading\/46357"}, "attach_limit": 2, "max_comment_text_length": 5000, "subsite_id": 199123 }

9 комментариев 9 комм.

Популярные

По порядку

Написать комментарий...
2

Для новичков действительно будет полезно. Функционал XML-RPC при работе с WP в моей практике приносил только беды, поэтому отключаю каждый раз при старте нового проекта.

Особенно неплохо, что ребята сразу приняли верное решение и подключили Cloudflare PRO, в итоге обошлись в общем то небольшими тратами.

Ответить
1

На вордпресс ставишь All In One WP Security, закручиваешь гайки, если мало, то CloudFlare.
В общем статья дилетантская. Пускай на работу меня возьмут, буду их сайт поддерживать. (шутка)

Ответить
1

Полноценный WAF от NinjaFirewall (WP Edition) работает быстрее и из коробки закрывает львиную долю проблем с безопасностью у WP — https://wordpress.org/plugins/ninjafirewall/

Ответить
0

спасибо, попробую

Ответить
0

Слава, сайт Live Typing не на Wordpress. Это вы всем бедным людям помогите поддерживать их сайты, чтобы хакерам сложнее было.

Ответить
1

W
A aa s s za
Hello I’m

Ответить
0

Битки все равно купите)

Ответить
0

Спасибо за статью.

Ответить
0

Кузнец, все херня. Давай по новому.

Ответить
0

Прямой эфир

[ { "id": 1, "label": "100%×150_Branding_desktop", "provider": "adfox", "adaptive": [ "desktop" ], "adfox_method": "createAdaptive", "auto_reload": true, "adfox": { "ownerId": 228129, "params": { "pp": "g", "ps": "bugf", "p2": "ezfl" } } }, { "id": 2, "label": "1200х400", "provider": "adfox", "adaptive": [ "phone" ], "auto_reload": true, "adfox": { "ownerId": 228129, "params": { "pp": "g", "ps": "bugf", "p2": "ezfn" } } }, { "id": 3, "label": "240х200 _ТГБ_desktop", "provider": "adfox", "adaptive": [ "desktop" ], "adfox": { "ownerId": 228129, "params": { "pp": "g", "ps": "bugf", "p2": "fizc" } } }, { "id": 4, "label": "240х200_mobile", "provider": "adfox", "adaptive": [ "phone" ], "adfox": { "ownerId": 228129, "params": { "pp": "g", "ps": "bugf", "p2": "flbq" } } }, { "id": 5, "label": "300x500_desktop", "provider": "adfox", "adaptive": [ "desktop" ], "adfox": { "ownerId": 228129, "params": { "pp": "g", "ps": "bugf", "p2": "ezfk" } } }, { "id": 6, "label": "1180х250_Interpool_баннер над комментариями_Desktop", "provider": "adfox", "adaptive": [ "desktop" ], "adfox": { "ownerId": 228129, "params": { "pp": "h", "ps": "bugf", "p2": "ffyh" } } }, { "id": 7, "label": "Article Footer 100%_desktop_mobile", "provider": "adfox", "adaptive": [ "desktop", "tablet", "phone" ], "adfox": { "ownerId": 228129, "params": { "pp": "g", "ps": "bugf", "p2": "fjxb" } } }, { "id": 8, "label": "Fullscreen Desktop", "provider": "adfox", "adaptive": [ "desktop", "tablet" ], "auto_reload": true, "adfox": { "ownerId": 228129, "params": { "pp": "g", "ps": "bugf", "p2": "fjoh" } } }, { "id": 9, "label": "Fullscreen Mobile", "provider": "adfox", "adaptive": [ "phone" ], "auto_reload": true, "adfox": { "ownerId": 228129, "params": { "pp": "g", "ps": "bugf", "p2": "fjog" } } }, { "id": 10, "disable": true, "label": "Native Partner Desktop", "provider": "adfox", "adaptive": [ "desktop", "tablet" ], "adfox": { "ownerId": 228129, "params": { "pp": "g", "ps": "clmf", "p2": "fmyb" } } }, { "id": 11, "disable": true, "label": "Native Partner Mobile", "provider": "adfox", "adaptive": [ "phone" ], "adfox": { "ownerId": 228129, "params": { "pp": "g", "ps": "clmf", "p2": "fmyc" } } }, { "id": 12, "label": "Кнопка в шапке", "provider": "adfox", "adaptive": [ "desktop" ], "adfox": { "ownerId": 228129, "params": { "p1": "bscsh", "p2": "fdhx" } } }, { "id": 13, "label": "DM InPage Video PartnerCode", "provider": "adfox", "adaptive": [ "desktop", "tablet", "phone" ], "adfox_method": "createAdaptive", "adfox": { "ownerId": 228129, "params": { "pp": "h", "ps": "bugf", "p2": "flvn" } } }, { "id": 14, "label": "Yandex context video banner", "provider": "yandex", "yandex": { "block_id": "VI-223676-0", "render_to": "inpage_VI-223676-0-1104503429", "adfox_url": "//ads.adfox.ru/228129/getCode?pp=h&ps=bugf&p2=fpjw&puid1=&puid2=&puid3=&puid4=&puid8=&puid9=&puid10=&puid21=&puid22=&puid31=&puid32=&puid33=&fmt=1&dl={REFERER}&pr=" } }, { "id": 15, "label": "Плашка на главной", "provider": "adfox", "adaptive": [ "desktop", "tablet", "phone" ], "adfox": { "ownerId": 228129, "params": { "p1": "byudx", "p2": "ftjf" } } }, { "id": 16, "label": "Кнопка в шапке мобайл", "provider": "adfox", "adaptive": [ "tablet", "phone" ], "adfox": { "ownerId": 228129, "params": { "p1": "byzqf", "p2": "ftwx" } } }, { "id": 17, "label": "Stratum Desktop", "provider": "adfox", "adaptive": [ "desktop" ], "auto_reload": true, "adfox": { "ownerId": 228129, "params": { "pp": "g", "ps": "bugf", "p2": "fzvb" } } }, { "id": 18, "label": "Stratum Mobile", "provider": "adfox", "adaptive": [ "tablet", "phone" ], "auto_reload": true, "adfox": { "ownerId": 228129, "params": { "pp": "g", "ps": "bugf", "p2": "fzvc" } } }, { "id": 19, "label": "Тизер на главной", "provider": "adfox", "adaptive": [ "desktop", "tablet", "phone" ], "auto_reload": true, "adfox": { "ownerId": 228129, "params": { "p1": "cbltd", "p2": "gazs" } } } ]
Нейронная сеть научилась читать стихи
голосом Пастернака и смотреть в окно на осень
Подписаться на push-уведомления