Атака на цепочку поставок Rust: заражённые arrayref 0.3.10 и тайпсквот proc-macro1
Утром 20 августа 2026 года в экосистеме Rust произошла атака на цепочку поставок, затронувшая один из самых распространённых крейтов. Скомпрометированная версия arrayref 0.3.10 незаметно добавила зависимость от proc-macro1 1.0.107 — тайпсквота вездесущего proc-macro2. Сборочный скрипт этого пакета скачивал бинарный файл с удалённого сервера и запускал его на любой машине, которая собирала проект. Поскольку вредоносный код жил в build.rs, для заражения достаточно было просто скомпилировать проект — вызывать что-либо из крейта не требовалось.
Как разворачивалась атака
Подготовка велась в тот же день. Ночью был создан аккаунт dtolney, выдававший себя за Дэвида Толная (dtolnay), автора настоящего proc-macro2. Сначала под сквоттнутым именем опубликовали чистую копию proc-macro2 — исключительно ради правдоподобия. Затем вышла версия 1.0.107 с подозрительными сборочными зависимостями (base64, rustls, ureq), которые честной библиотеке макросов ни к чему.
В 07:15 UTC из аккаунта владельца droundy вышел arrayref 0.3.10 — первая настоящая зависимость за десятилетнюю историю крейта. В ту же минуту скриптом с интервалом около четырёх секунд были отозваны (yanked) версии с 0.3.5 по 0.3.9, чтобы предупреждение Cargo о «отозванной версии» подталкивало пользователей к обновлению прямиком в ловушку. Окно уязвимости составило примерно 86 минут: около 08:03 crates.io удалил proc-macro1, а к 08:41 убрал из индекса и arrayref 0.3.10.
Механика вредоноса
Скрипт build.rs собирал адреса инфраструктуры из base64-фрагментов, скачивал по TLS полезную нагрузку второй ступени с намеренно отключённой проверкой сертификата, сбрасывал её в /tmp/rust-setup на Unix (или в %TEMP% через скрытый wscript.exe на Windows) и запускал отдельным процессом, аккуратно выходя за пределы job-объекта Cargo, чтобы сборка завершалась как ни в чём не бывало. При этом код самой библиотеки оставался подлинным proc-macro2, и заражение никак не проявлялось в выводе.
Масштаб
У arrayref около 245 миллионов загрузок за всё время. Он лежит в основе множества GUI-приложений на Rust (egui/eframe, iced, winit), а также попадает в зависимости blake3, revm-precompile для Ethereum и solana-runtime/spl-token для Solana. Любая CI-задача или сборка разработчика, которая заново разрешала arrayref ^0.3 в течение этих 86 минут, выполнила payload с правами текущего пользователя.
Что делать
Проверьте Cargo.lock: наличие версии 0.3.10 или любой записи proc-macro1 означает, что код отработал. Ищите артефакты /tmp/rust-setup, %TEMP%\rust-setup.ps1 и сетевой трафик к 23.254.165.112. При обнаружении следов считайте хост скомпрометированным и ротируйте все доступные с него секреты, токены и ключи. Если следов нет — закрепите arrayref = "=0.3.9" и не устраняйте предупреждения об отзыве слепым обновлением.
Источник: Lobsters
Комментарии
Войдите, чтобы комментировать.