Evil Merge: как малварь пряталась в git merge-коммите 3,5 месяца |
||
|
МЕНЮ Главная страница Поиск Регистрация на сайте Помощь проекту Архив новостей ТЕМЫ Новости ИИ Голосовой помощник Разработка ИИГородские сумасшедшие ИИ в медицине ИИ проекты Искусственные нейросети Искусственный интеллект Слежка за людьми Угроза ИИ Атаки на ИИ Внедрение ИИИИ теория Компьютерные науки Машинное обуч. (Ошибки) Машинное обучение Машинный перевод Нейронные сети начинающим Психология ИИ Реализация ИИ Реализация нейросетей Создание беспилотных авто Трезво про ИИ Философия ИИ Big data Работа разума и сознаниеМодель мозгаРобототехника, БПЛАТрансгуманизмОбработка текстаТеория эволюцииДополненная реальностьЖелезоКиберугрозыНаучный мирИТ индустрияРазработка ПОТеория информацииМатематикаЦифровая экономика
Генетические алгоритмы Капсульные нейросети Основы нейронных сетей Промпты. Генеративные запросы Распознавание лиц Распознавание образов Распознавание речи Творчество ИИ Техническое зрение Чат-боты Авторизация |
2026-04-07 12:18 Несколько месяцев назад я делал плановую проверку кодовой базы на одном из проектов и нашёл обфусцированный код в файле Я пошёл смотреть через Merge, который не должен был ничего менять У merge-коммита было два родителя. Я проверил файл в обоих — идентичный. Одинаковое содержимое, одинаковый MD5: Если вы понимаете как работает трёхстороннее слияние в git — вы уже видите проблему. Когда оба родителя содержат одинаковый файл, git просто берёт его как есть. Ему нечего мержить. Единственный способ получить другой результат — вручную отредактировать файл в процессе merge до коммита. Именно это и произошло. Контрибьютор, нажавший кнопку merge в PR, добавил код которого не было ни в одной из веток. Git записал это как обычный merge-коммит, и никто не обратил внимания. То же самое было сделано с двумя файлами в двух разных модулях. Идентичный пейлоад в обоих. Что делал этот код Я потратил день на деобфускацию. Коротко: Первый слой восстанавливает строки Второй слой — кастомный декодер на таблице замены символов. Декодирует большой зашифрованный блок в настоящий пейлоад. Дальше — самое интересное. Пейлоад не содержит ни одного URL и ни одного IP-адреса. Вместо этого он запрашивает TRON-кошелёк на последнюю транзакцию, берёт из неё BSC-хеш транзакции, делает Канал управления — блокчейн. Его нельзя заблокировать по домену, нельзя вынуть сервер. В исходниках нет никаких очевидных индикаторов компрометации. Есть резервный путь через Aptos на случай если TRON недоступен. Вся инфраструктура — кошельки, транзакции — была подготовлена до внедрения кода. Финальный этап запускает отдельный фоновый процесс ( Всё это запускалось при каждом Почему никто не заметил GitHub не показывает diff merge-коммитов в PR. Ревью PR показывало изменения ветки — всё чисто. Сама инъекция произошла на шаге merge, который никто не ревьюит. Ну а зачем? Это же просто слияние. Файл в любом редакторе выглядел нормально. Вредоносный код был на той же строке что и легитимный, просто сдвинут вправо пробелами. Его не увидеть, если специально не скроллить за колонку 200. SAST не поднял тревогу, потому что явных сигнатур не было — ни Что такое evil merge После этого инцидента я начал копать — есть ли для этого название и известна ли такая техника. Оказалось, термин есть, и он официальный. Из документации git (
Термин закреплён в официальном глоссарии git. В 2013 году Junio C Hamano — нынешний мейнтейнер git — написал единственный серьёзный пост на эту тему, объясняя как evil merge может возникнуть случайно при семантических конфликтах. То что я нашёл — не случайность. На Хабре по этой теме нет ни одной публикации. На dev.to — одно упоминание в комментарии. На HN — пара реплик в чужих тредах. Тема, которую мейнтейнер git описывал ещё в 2013-м, в 2024-м году практически неизвестна разработчикам. С инструментами ещё хуже. Есть Детектор После того как паника улеглась и мы поменяли все секреты которые смогли найти, я начал думать — а можно ли это было поймать автоматически? Логика простая: для каждого merge-коммита восстановить то что git должен был сгенерировать — чистое трёхстороннее слияние деревьев родителей через общего предка — и сравнить с тем что merge-коммит реально содержит. Любое расхождение означает что файл редактировался вручную в процессе merge. Из этого получился Evil Merge Detector — CLI на Go: Он проходит по всем merge-коммитам, сравнивает ожидаемое дерево с реальным и выводит расхождения. Есть Есть GitHub Action для добавления в CI: И GitHub App — устанавливается на репозиторий и автоматически проверяет каждый PR через Checks API. При первой установке он сканирует всю историю репозитория — на случай если инцидент уже произошёл. Для GitLab, Bitbucket или self-hosted git-серверов — готовые шаблоны в директории Шире Атаки на supply chain через зависимости open source получают много внимания. Атаки через contributor-доступ к приватным репозиториям — почти никакого. Паттерн простой: получить доступ контрибьютора, несколько месяцев делать легитимные коммиты, потом внедрить код во время merge. PR чистый. Merge-коммит выглядит как рутинная интеграция. Стандартный совет — требовать линейную историю (squash/rebase only) или поставить pre-receive хук на своём git-сервере. Оба варианта меняют workflow или требуют self-hosted инфраструктуру. На GitHub это не так просто. Я отправил репорт в GitHub Security. Полный ответ:
В качестве существующей митигации указали “Dismiss stale reviews” — правило защиты ветки, которое требует повторного ревью при каждом новом коммите в PR-ветку. “Dismiss stale reviews” действительно усложняет атаку. Но это prevention, не detection. Он не сканирует существующую историю на предмет прошлых инъекций. Требует ручной настройки на каждый репозиторий. И может быть отключён любым администратором. Если правило не было включено до инцидента — или он произошёл в репозитории без активного мониторинга — вы об этом не узнаете. GitHub оставил дверь открытой для будущих изменений, но ничего конкретного не анонсировал. Пока — merge workflow работает так же. Я не знаю насколько это распространено. Может наш случай редкий. Но то что это работало 3,5 месяца в репозитории с CI, code review и несколькими разработчиками которые работали с ним каждый день — говорит о том что мы, возможно, проверяем не то. Телеграм: t.me/ainewsline Источник: habr.com Комментарии: |
|