Угон BGP-маршрута подменил обновления Virtualizor без взлома серверов
Атака без взлома серверов: маршрут в интернете, валидный сертификат и обновление без проверки подписи. Компания признаёт, что полного списка пострадавших нет, и публикует индикатор для проверки.

Softaculous, разработчик панели Virtualizor для управления виртуальными серверами, 31 августа признал инцидент: с вечера 28 августа по утро 30-го неизвестный объявлял в BGP чужой префикс 162.55.80.0/24, где живут серверы обновлений, клиентская зона и биллинг компании. Часть интернета поверила подмене, атакующий получил настоящий сертификат Let's Encrypt для доменов Virtualizor и раздал «небольшому числу» установок вредоносное обновление.
Подтверждённый вектор атаки не требовал взлома серверов Softaculous: она прошла на уровне маршрутизации интернета и сработала потому, что клиент обновлений Virtualizor не проверял криптографическую подпись пакета, ему хватало валидного TLS. Если у вас стоит Virtualizor, а его используют многие хостинги, включая российские, компания просит проверить сервер по опубликованному индикатору, даже если обновление вручную вы не запускали.
Ключевые выводы
- Окно инцидента около 33 часов: с 28 августа 20:57 UTC до 30 августа 06:10 UTC; активный перехват шёл двумя волнами общей длиной около 22 часов с перерывами, маршрут постоянно менялся.
- Поддельный маршрут /24 был специфичнее легитимного /16 Hetzner; все 368 peers RIPE RIS видели его хотя бы в один момент за окно инцидента; медианное число перенаправленных peers во время активной волны — 266 (около 72%).
- Через перехваченный трафик атакующий прошёл проверку Let's Encrypt и получил технически валидный сертификат для доменов Virtualizor.
- Вредоносное обновление подтверждено для Virtualizor; для других продуктов Softaculous таких пакетов не подтверждено. Индикатор компрометации: служба java-jre-update.service; выпущена версия 3.2.9.9 с инструментом устранения последствий и cleaning script, подпись пакетов обещана.
- Клиент обновлений не проверял подпись пакета; компания не может составить полный список затронутых серверов.
Как работает угон маршрута
BGP — протокол, по которому сети-операторы сообщают друг другу, через кого достижимы те или иные диапазоны IP-адресов. Доверие в нём во многом строится на честном слове: если кто-то объявляет, что диапазон живёт у него, соседи обычно верят. А если объявленный диапазон меньше (специфичнее) настоящего, маршрутизаторы предпочитают именно его. Так и произошло: Hetzner (AS24940) легитимно объявляет 162.55.0.0/16, атакующий объявил внутри него 162.55.80.0/24, и более точный маршрут победил.
В объявлении фигурировали AS62390 (NexonHost) и AS6204 (Zet.net), а в конце пути был оставлен Hetzner как видимый источник, чтобы подмена выглядела правдоподобно. По публичным данным RIPE RIS все 368 peers видели маршрут хотя бы в один момент за окно инцидента, а медианное число перенаправленных peers во время активной волны составляло 266. Перехват шёл двумя волнами общей продолжительностью около 22 часов с паузой примерно в 11 часов между ними, и для отдельных сетей он был прерывистым: маршрут то появлялся, то исчезал.
Почему сертификат оказался настоящим
Let's Encrypt подтверждает владение доменом, обращаясь к нему по HTTP. Если в этот момент трафик к домену идёт на сервер атакующего, проверка проходит, и сертификат выдаётся ему. Именно это и случилось: компания пишет, что злоумышленник получил «технически действительный TLS-сертификат для наших доменов» (перевод редакции). Браузеры и клиенты обновлений видели зелёный замок и доверяли ответам подменённого сервера.
The attacker obtained a technically valid TLS certificate for our domains.
Дальше сработало самое слабое звено: клиент обновлений Virtualizor доверял серверу по TLS и не проверял подпись самого пакета. Правильная схема, при которой пакет подписан офлайн-ключом разработчика и проверяется на сервере клиента, не спасла бы от перехвата трафика, но сделала бы подмену пакета невозможной. Компания обещала внедрить подпись для всех пакетов; срок и реализацию она не назвала.
Кого это задело
По словам компании, вредоносный пакет получила «горстка серверов», а не вся база пользователей Virtualizor. При этом Softaculous прямо признаёт: «Мы не можем составить окончательный список затронутых серверов» (перевод редакции), потому что подмена происходила на сетевом уровне и следов на стороне компании не оставила. Для Softaculous, Webuzo и других продуктов вредоносных пакетов не подтверждено, но те же адреса использовались и для их обновлений. Индикатор компрометации, который называет компания, — служба java-jre-update.service в системе. Softaculous выпустила Virtualizor 3.2.9.9 с инструментом устранения последствий и отдельный cleaning script, но просит при обнаружении индикатора не удалять службу самостоятельно, а связаться с поддержкой.
Что делать администратору
- Если у вас Virtualizor: обновитесь до 3.2.9.9, поищите службу
java-jre-update.serviceи при её наличии свяжитесь с поддержкой Softaculous, как просит компания; проверять стоит, даже если обновления вы не запускали, автообновление могло сработать само. - Сверьте по логам, не обращался ли сервер к
162.55.80.0/24между 28 августа 20:57 UTC и 30 августа 06:10 UTC. - Смените учётные данные панели, API-ключи и пароли, которые могли пройти через клиентскую зону или биллинг в этот период.
- Для собственных систем обновлений: подписывайте пакеты отдельным ключом и проверяйте подпись на клиенте; TLS защищает канал, но не содержимое.
- Если управляете своей сетью: включите RPKI Origin Validation и задайте свои ROA с точной длиной префикса. Оговорка: атакующий оставил Hetzner видимым origin, и без строгого maxLength в ROA такой маршрут ROV не отбросит.
Что дальше
Компания продолжает расследование; индикатор компрометации, версия 3.2.9.9 и cleaning script уже опубликованы. Открытых вопросов два: почему сети-транзиты пропустили объявление чужого /24 без проверки и когда и как будет внедрена обещанная подпись пакетов. Пока её нет, любой повторный угон маршрута снова превратится в атаку на цепочку поставок.
Источник: Security incident: BGP hijacking (Virtualizor)
Изображение на обложке: скриншот bgp.tools












