Атаки на ланцюг постачання: коли хакери атакують вашого постачальника, а не вас

Було корисно?

Ви можете швидко ставити патчі, міняти секрети й запускати складні системи виявлення—і все одно опинитися зламаними, бо хтось інший доставив вам проблему.
Неприємна правда: нападникам подобаються постачальники, бо в них уже є канали розповсюдження, довіра й прямий доступ до вашого продакшн-кластеру.

Сигнал тривоги не цікавиться, чи почалося порушення у вашому репозиторії, чи в репозиторії залежності. Клієнти бачать лише те, що ви запустили код.
Тож поговорімо, як насправді відбуваються атаки на ланцюг постачання, що перевіряти насамперед при підозрі, і що змінити, щоб ви перестали бути легкою жертвою вниз по ланцюгу.

Що таке атака на ланцюг постачання насправді (і чого це не стосується)

Атака на ланцюг постачання відбувається, коли зловмисник компрометує довірений елемент вгору по ланцюгу—програмне забезпечення постачальника, відкриту залежність,
збірні інструменти, раннери CI, репозиторії пакетів, реєстри контейнерів, канали оновлень або навіть вашого провайдера керованих послуг—
так що жертва встановлює шкідливий код під час «звичайних операцій».

Це не те саме, що «нас фішингували» або «хтось підібрав пароль до VPN». Це прямі атаки. У випадках ланцюга постачання
зловмисник експлуатує ваші відносини довіри. Мета — механізм розповсюдження, а не окремий пристрій.

В операційному сенсі: атака на ланцюг постачання перетворює ваш конвеєр деплою на вектор інфекції. Площа ураження визначається тим,
наскільки широко ви розповсюджуєте артефакти і як швидко можете відповісти на два питання:

  • Що саме ми розгорнули, куди і коли?
  • Чи можемо ми довести, що це походить від очікуваного джерела і не було змінене?

Якщо ви не можете швидко відповісти на це, то проблема не в «відсталих інструментах». Проблема в виживаності.

Цитата, яку варто записати на стікері для реагування на інциденти:
«Надія — це не стратегія.» — Генерал Гордон Р. Салліван

Чому постачальники подобаються нападникам

Компрометація окремого клієнта потребує націлювання на кожного клієнта. Компрометація постачальника дозволяє масову доставку під брендом.
Це як вибирати між спробою відкрити кожні двері в районі і підкупом слюсаря.

Постачальники також дають «приховану активність». Їхнє ПО очікувано шумить: телеметрія, перевірки оновлень, плагіни та інтеграції.
Це чудові схованки для командно-контрольного трафіку.

Кого вважати «постачальником» у 2026 році

Це не лише компанія, якій ви платите за рахунком. Ваш «постачальник» — це:

  • Кожна транзитивна залежність із пакетних екосистем (npm, PyPI, Maven, RubyGems, Go modules).
  • Кожен базовий образ контейнера та репозиторій ОС.
  • Ваш сервіс CI/CD, раннери, плагіни та дії з маркетплейсу.
  • Провайдери інфраструктури як коду і їх модулі.
  • Керовані сервіси та SaaS, що зберігають секрети і мають API-доступ до ваших систем.

Якщо він може пушити код, запускати код або випускати креденшіали — ставте його в модель загроз як потенційний вектор.

Типові шляхи атаки, якими користуються зловмисники

1) Шкідливе оновлення через довірчий канал

Класичний прийом: компрометація збірного оточення постачальника або ключів підписування, випуск підписаного оновлення й проїзд механізму автооновлення в прод.
Ваші захисти можуть навіть допомагати їм: автоматизація патчів сумлінно прискорює розгортання.

2) Заміна залежності (typosquatting і dependency confusion)

Якщо ваша збірка може тягнути пакети з публічних реєстрів, нападники можуть опублікувати пакет із потрібною назвою—або з доволі схожою—і чекати, поки збірка «допоміжно» його підвантажить.
Dependency confusion особливо небезпечний, коли внутрішні імена пакетів конфліктують з публічними просторами імен.

Жарт №1: Імена залежностей як паролі — якщо вам здається, що «util» підходить, ви також вважаєте «Password123» сміливим.

3) Компрометація облікового запису мейнтейнера

Багато проблем з безпекою open-source — це «у мейнтейнера ноутбук, напевно, в порядку». Коли обліковий запис мейнтейнера захоплюють,
нападник може виштовхнути новий реліз, що виглядає законним. Якщо ваш процес трактує «нова версія з’явилась» як «відправити в реліз», ви маєте конвеєр, який автоматично інсталює компрометований код.

4) Компрометація раннера CI/CD

Раннери — ласий шматок: вони бачать код, секрети, артефакти і зазвичай мають мережевий доступ до всього.
Якщо раннер скомпрометовано, нападник може змінити вихід збірки, вставити бекдор або викрасти ключі підписування.
Так «репозиторій виглядає чистим» перетворюється на «артефакт злий».

5) Отруєння реєстрів артефактів та дзеркал

Якщо ви дзеркалите пакети або образи для швидкості, те дзеркало стає компонентом довіри. Нападники йдуть за ним.
Якщо клієнти довіряють дзеркалу без перевірки, ви централізували режим відмови.

6) Виконання скриптів під час збірки

Встановлення пакетів часто виконує скрипти (postinstall hooks, setup.py тощо). Це означає, що «збірка» — це також «запуск недовіреного коду».
Іншими словами, ваша система збірки — це оточення, схоже на продакшн, для нападників.

7) Зловживання інтеграціями SaaS

OAuth-додатки, GitHub Apps, дії маркетплейсу CI, боти для чатопсу — це «постачальники», які можуть читати й писати репозиторії, задачі, секрети й конвеєри.
Багато таких додатків надмірно привілейовані, бо люди налаштовували їх, орієнтуючись на «щоб працювало», а не на «щоб вижило».

Факти та історичний контекст, які варто знати

  • Розповсюдження програмного забезпечення було мішенню ще з 1980-х: ранні віруси поширювалися через спільні диски й «корисні утиліти» — примітивний ланцюг постачання.
  • Цифрове підписування стало масовим, бо цілісність не можна було масштабувати вручну: коли завантаження замінило фізичні носії, постачальники потребували способу сказати «це від нас».
  • Пакетні екосистеми перетворили бібліотеки на інфраструктуру: сучасні додатки регулярно залежать від сотень і тисяч транзитивних пакетів, багато з яких підтримують волонтери.
  • Системи збірки стали мережевими: CI/CD підключили збірки до інтернету, до реєстрів, до метаданих хмари та сховищ секретів — добре для швидкості, добре для нападників.
  • «Dependency confusion» не з’явився раптом із назвою: колізії внутрішніх і публічних просторів імен існували роками; назва зробила легше пояснити проблему керівникам.
  • SBOM зросли через потребу закупівель у відстежуваності: інженери вже знали, що залежності хиткі; SBOM формалізували хаос у формат, до якого могли доторкнутися контролі.
  • Відтворювані збірки — відповідь на «довіряй мені» бінарники: якщо ви можете перебудувати та отримати біт-в-біт ідентичний результат, ви зменшуєте залежність від збірного середовища постачальника.
  • Сучасні нападники оптимізують час присутності: доступ у ланцюзі постачання часто дозволяє довго залишатися непоміченими, бо payload може виглядати як легітимний компонент.
  • Хмарна ідентичність змінила площу ураження: скомпрометований CI-токен може бути потужнішим за скомпрометований сервер, бо він може створювати та розгортати скрізь.

Швидкий план діагностики (перший/другий/третій)

Інциденти в ланцюзі постачання — це гонка між вашою здатністю обмежити площу ураження та здатністю нападника закріпитися.
Мета швидкої діагностики — не ідеальна атрибуція. Мета — локалізація з доказами.

Перший крок: Доведіть, що змінилося

  1. Перелічіть розгорнуті артефакти (дайджести образів, версії пакетів, ID збірок) у прод/стейдж/дев.
  2. Визначте найраніше розгортання підозрілої версії. Час важливий для масштабу.
  3. Заморозьте шлях оновлення: зупиніть авто-деплой і автооновлення, але не видаляйте докази.

Другий крок: Перевірте походження й цілісність

  1. Перевірте підписи артефактів і впевніться, що особа, яка підписала, відповідає політиці.
  2. Порівняйте SBOM між відомо чистою і підозрілою збіркою, щоб знайти інжектовані залежності.
  3. Перебудуйте з вихідників, якщо можливо, і порівняйте хеші (або хоча б lockfile залежностей).

Третій крок: Полюйте за виконанням і персистентністю

  1. Шукайте рантайм-індикатори: незвичні вихідні підключення, нові cron/systemd-одиниці, нові бінарні файли, підозрілі процеси.
  2. Аудитуйте креденшіали, які використовує компонент постачальника: API-ключі, OAuth-токени, ролі в хмарі.
  3. Міняйте і перевипускайте креденшіали після локалізації; вважайте, що все, до чого торкався CI, скомпрометовано.

Якщо виконувати ці кроки в порядку, ви зможете швидко відповісти на питання керівництва:
«Чи ми постраждали?», «Який масштаб?», «Чи можемо зупинити це?», «Що міняти?»

Практичні завдання: команди, виходи, рішення (12+)

Сенс цих завдань — операційна ясність: команди, які можна виконати під тиском, вихід, на який слід звертати увагу,
та рішення, що за цим слідують. Підбирайте під ваш стек.

Завдання 1: Визначити запущені образи контейнерів по дайджесту (Kubernetes)

cr0x@server:~$ kubectl get pods -A -o=jsonpath='{range .items[*]}{.metadata.namespace}{"\t"}{.metadata.name}{"\t"}{range .status.containerStatuses[*]}{.image}{"\t"}{.imageID}{"\n"}{end}{end}'
prod	api-7b9c7bdfb8-k8r9t	registry.local/api:1.4.2	docker-pullable://registry.local/api@sha256:8e6b...
prod	worker-6f5c9cc8d9-2qvxn	registry.local/worker:2.1.0	docker-pullable://registry.local/worker@sha256:2c1a...

Що це означає: Теги брешуть; дайджести — ні. sha256 ідентифікує те, що реально запущено.

Рішення: Якщо підозрювана компрометація прив’язана до тега, негайно переходьте на дайджести і перелічте всі ворклоади, що використовують ці дайджести.

Завдання 2: Перелік деплойментів та їхніх тегів образів (швидкий охват)

cr0x@server:~$ kubectl get deploy -A -o=jsonpath='{range .items[*]}{.metadata.namespace}{"\t"}{.metadata.name}{"\t"}{range .spec.template.spec.containers[*]}{.image}{"\n"}{end}{end}'
prod	api	registry.local/api:1.4.2
prod	worker	registry.local/worker:2.1.0

Що це означає: Це ваш список «хто може бути ураженим», а не доказ.

Рішення: Використайте його для пріоритетизації, які дайджести перевіряти і які команди повідомити першими.

Завдання 3: Перевірити підпис образу за допомогою cosign

cr0x@server:~$ cosign verify --key /etc/cosign/cosign.pub registry.local/api@sha256:8e6b...
Verification for registry.local/api@sha256:8e6b... --
The following checks were performed on each of these signatures:
  - The cosign claims were validated
  - Existence of the claims in the transparency log was verified offline
  - The signatures were verified against the specified public key

Що це означає: Підпис перевірено проти вашого ключа. Це перевіряє цілісність і особу підписувача (за умови правильної роботи з ключами).

Рішення: Якщо перевірка неуспішна — ізолюйте дайджест: блокувати на admission control і зупинити rollout’и, що його посилаються.

Завдання 4: Fail-closed з політикою валідації Kubernetes (виявляти неподписані)

cr0x@server:~$ kubectl get validatingadmissionpolicies
NAME                      AGE
require-signed-images      41d

Що це означає: У вас є об’єкт політики, але це не означає, що він всюди застосовується.

Рішення: Підтвердіть binding-и і протестуйте з відомим неподписаним образом. Якщо застосування часткове — вважайте це помилкою підготовки до інциденту.

Завдання 5: Перевірити, які версії Debian-пакетів встановлені (охват хостів)

cr0x@server:~$ dpkg -l | grep -E '^ii\s+(openssl|curl|sudo)\s'
ii  curl     7.88.1-10+deb12u4   amd64  command line tool for transferring data with URL syntax
ii  openssl  3.0.11-1~deb12u2    amd64  Secure Sockets Layer toolkit - cryptographic utility
ii  sudo     1.9.13p3-1+deb12u1  amd64  Provide limited super user privileges to specific users

Що це означає: Конкретні версії пакетів для зіставлення з advisory / IOC від постачальника.

Рішення: Якщо версії відповідають вразливому діапазону — ізолюйте хости від мережі і плануйте відновлення, а не «гаряче патчення і надію».

Завдання 6: Перевірити походження пакета і репозиторій (APT)

cr0x@server:~$ apt-cache policy curl
curl:
  Installed: 7.88.1-10+deb12u4
  Candidate: 7.88.1-10+deb12u4
  Version table:
 *** 7.88.1-10+deb12u4 500
        500 http://deb.debian.org/debian bookworm/main amd64 Packages
        100 /var/lib/dpkg/status

Що це означає: Підтверджує джерело репозиторію для встановленого пакета.

Рішення: Якщо бачите несподівані репозиторії (особливо ad-hoc дзеркала), припускайте компрометацію або неправильну конфігурацію репозиторію та перемикайтеся на відомо безпечне дзеркало.

Завдання 7: Перевірити нещодавні інсталяції і оновлення пакетів (таймлайн хоста)

cr0x@server:~$ grep -E " install | upgrade " /var/log/dpkg.log | tail -n 5
2026-01-20 12:14:02 upgrade curl:amd64 7.88.1-10+deb12u3 7.88.1-10+deb12u4
2026-01-20 12:14:03 upgrade openssl:amd64 3.0.11-1~deb12u1 3.0.11-1~deb12u2

Що це означає: Мітки часу і переходи версій дають мінімальну межу, коли зміна з’явилася.

Рішення: Корелюйте з деплойментами й піками вихідного трафіку. Якщо інсталяція співпадає з підозрілою поведінкою — вважайте ці хости потенційно скомпрометованими.

Завдання 8: Знайти підозрілі нові systemd-одиниці (перевірка персистентності)

cr0x@server:~$ systemctl list-unit-files --type=service --state=enabled | tail -n 10
ssh.service                               enabled
systemd-timesyncd.service                 enabled
telegraf.service                          enabled
vendor-agent.service                      enabled

Що це означає: Нова увімкнена служба — кандидат на персистентність. «vendor-agent» може бути легітимним або проблемним.

Рішення: Якщо одиниця з’явилася в межах вікна інциденту і не входить до вашого золотого образу, ізолюйте і розслідуйте перед відключенням (спочатку збирайте докази).

Завдання 9: Переглянути визначення сервісу та шлях бінарника

cr0x@server:~$ systemctl cat vendor-agent.service
# /etc/systemd/system/vendor-agent.service
[Unit]
Description=Vendor Agent
After=network-online.target

[Service]
ExecStart=/usr/local/bin/vendor-agent --config /etc/vendor/agent.yaml
Restart=always

[Install]
WantedBy=multi-user.target

Що це означає: Показує точно, що запускається і звідки.

Рішення: Якщо воно запускається з записуваних шляхів (/usr/local, домашні каталоги), вважайте ризик вищим і перемістіть компонент в імунні, керовані шляхи.

Завдання 10: Перевірити, чи бінарник не змінювався нещодавно (швидка триаж)

cr0x@server:~$ ls -l --time-style=long-iso /usr/local/bin/vendor-agent
-rwxr-xr-x 1 root root 184320 2026-01-20 12:13 /usr/local/bin/vendor-agent

Що це означає: Час модифікації дає орієнтир. Не доказ, але підказка.

Рішення: Якщо mtime збігається з підозрілим оновленням — порахуйте хеш, порівняйте з відомо чистим і розгляньте відновлення хостів з довіреного образу.

Завдання 11: Хешувати бінарник і порівняти по флоту (цілісність)

cr0x@server:~$ sha256sum /usr/local/bin/vendor-agent
9d3f5a2c8f6d2c0e7c1a3b7b0d4f11d0f3e0f9a7a1c2b3d4e5f6a7b8c9d0e1f2  /usr/local/bin/vendor-agent

Що це означає: Це фактична ідентичність бінарника, який ви виконали.

Рішення: Якщо хеші відрізняються між хостами, які «мають бути однаковими», вважайте це неконтрольованим розповсюдженням і припиніть довіряти рядкам версій.

Завдання 12: Виявити несподівані вихідні підключення (рантайм-індикатори)

cr0x@server:~$ sudo ss -tpn | head -n 12
State  Recv-Q Send-Q Local Address:Port  Peer Address:Port Process
ESTAB  0      0      10.0.4.12:43122    203.0.113.77:443 users:(("vendor-agent",pid=1842,fd=9))
ESTAB  0      0      10.0.4.12:53618    10.0.1.9:5432   users:(("api",pid=2210,fd=12))

Що це означає: Акаунт агент постачальника, що говорить на публічну IP, може бути нормою — або ексфільтрацією.

Рішення: Якщо адреса призначення не в списку дозволеного egress — блокуйте її на фаєрволі/egress-шлюзі і почніть захоплення пакетів на ізольованому клоні.

Завдання 13: Переглянути DNS-запити на дивні домени (поведінкова підказка)

cr0x@server:~$ sudo journalctl -u systemd-resolved --since "2 hours ago" | grep -i "query" | tail -n 5
Jan 22 10:11:03 node-12 systemd-resolved[512]: Querying A record for updates.vendor.example.
Jan 22 10:11:09 node-12 systemd-resolved[512]: Querying A record for telemetry.vendor.example.

Що це означає: Система резолвить ендпоінти постачальника. Назви мають значення: «updates» очікуване; випадкові lookalike’и — ні.

Рішення: Якщо бачите нові домени, введені після оновлення — вимагайте від постачальника пояснень і блокуйте до задовільного пояснення.

Завдання 14: Перевірити підписи комітів Git (гігієна репозиторію)

cr0x@server:~$ git log --show-signature -n 3
commit 1a2b3c4d5e6f7g8h9i0j
gpg: Signature made Tue 21 Jan 2026 09:12:33 AM UTC
gpg:                using RSA key 4A5B6C7D8E9F0123
gpg: Good signature from "Build Bot <buildbot@example.com>"
Author: Build Bot <buildbot@example.com>
Date:   Tue Jan 21 09:12:33 2026 +0000

    release: bump api to 1.4.2

Що це означає: «Good signature» означає, що коміт відповідає довіреному ключу, а не те, що вміст безпечний.

Рішення: Якщо підписи відсутні або ключі несподівані — заморозьте релізи і проведіть аудит, хто може пушити в релізні гілки.

Завдання 15: Виявити дрейф залежностей за diff-ами lockfile

cr0x@server:~$ git diff --name-only HEAD~1..HEAD | grep -E 'package-lock.json|poetry.lock|go.sum'
package-lock.json

Що це означає: Lockfile змінився. Саме там з’являються несподівані залежності.

Рішення: Розглядайте зміни lockfile як чутливі до безпеки. Вимагайте рев’ю тим, хто вміє читати граф залежностей, а не лише код застосунку.

Завдання 16: Аудит використання токенів CI/CD (приклад AWS CloudTrail)

cr0x@server:~$ aws cloudtrail lookup-events --lookup-attributes AttributeKey=Username,AttributeValue=ci-deploy-role --max-results 3
{
  "Events": [
    {
      "EventName": "AssumeRole",
      "EventTime": "2026-01-22T09:58:14Z",
      "Username": "ci-deploy-role"
    },
    {
      "EventName": "PutObject",
      "EventTime": "2026-01-22T09:58:55Z",
      "Username": "ci-deploy-role"
    }
  ]
}

Що це означає: Показує активність ролі, часто використовуваної в пайплайнах.

Рішення: Якщо бачите дивні регіони, часи або API-виклики для ролі — вважайте, що креденшіали CI скомпрометовано, і негайно обертайте/звужуйте їх права.

Три корпоративні міні-історії з поля бою

Міні-історія 1: Інцидент через неправильне припущення

Середня фінтех-компанія використовувала популярний комерційний агент моніторингу. Агент мав глибокий доступ до хостів (звісно),
а постачальник мав бездоганну репутацію. Внутрішнє припущення було просте: «Якщо підписано — безпечно».

Прийшов алерт: набір хостів застосунків почав робити вихідні TLS-з’єднання на IP-діапазон, який ніхто не впізнавав.
NetOps відмітив це як «ймовірно телеметрія від постачальника». SRE на виклику не дуже порадів, але вікно змін було хаотичним,
і ніхто не хотів бути тим, хто заблокує моніторинг.

Помилка була в припущенні, що підпис означає безпеку. Підпис означає автентичність. Якщо підписний пайплайн постачальника скомпрометовано,
підпис стає підтвердженням доставки.

Коли вони нарешті витягли бінарник агента з трьох хостів і порівняли хеші, вони не збіглися — незважаючи на «ту ж версію».
Виявилося, що існували два шляхи доставки: нормальний канал оновлень і «гарячий» канал хотфіксів, який підтримка включила місяці тому.
Один шлях був скомпрометований, інший — ні. Той же рядок версії. Різний payload.

Виправлення не було героїчним. Вони ввели політику: дозволяти оновлення агента лише з внутрішнього дзеркала за дайджестом,
і вимагати внутрішньої повторної підписки. Також: агенти моніторингу більше не мали загального права egress.
Найбільша культурна зміна — визнати, що «довіра постачальникові» не є контролем.

Міні-історія 2: Оптимізація, що обернулася проти

B2B SaaS компанія оптимізувала збірки за швидкістю. Вони використовували спільний кеш CI для багатьох репозиторіїв.
Залежності, скомпільовані артефакти, навіть деякі бінарники інструментів кешувалися глобально. Було швидко. Також це було спільною поверхнею інфікування.

Один репозиторій підхопив скомпрометовану залежність через публічний реєстр. Залежність мала скрипт збірки, який виконувався під час інсталяції.
Він скинув «корисний» бінарник у спільний кеш під назвою звичайного інструмента. Майбутні збірки в інших репозиторіях почали його використовувати,
бо PATH і пошук кешу віддавали перевагу прогрітому кешу.

Дивний симптом: збірки проходили, тести — теж, але релізні артефакти мали тонкі відмінності. Репорти про баги рантайму були непослідовні:
логування трохи інше, кілька запитів почали таймаути під навантаженням. Це нагадувало регресію додатку, а не інцидент безпеки.

Поворотним моментом стало те, що хтось перебудував той самий коміт на чистому раннері і отримав інший дайджест контейнера.
Такого не повинно було відбуватися в здоровому пайплайні. Вони відслідкували проблему до спільного кеша: збірка не була герметичною.

Вони прибрали глобальний кеш, або точніше: зробили кеші на репозиторій/гілку з чітким власництвом і періодичним очищенням.
Заблокували джерела залежностей внутрішніми проксі і вимагали фіксування lockfile. Збірки стали повільніші. Інциденти — рідшими.
Керівництво перестало поклонятися «швидкому CI», коли йому показали вартість «швидкого компромісу».

Міні-історія 3: Сумна, але правильна практика, що врятувала ситуацію

Організація в сфері охорони здоров’я мала політику, за яку всі нарікали: продакшн-деплоям дозволялося використовувати тільки артефакти з внутрішнього реєстру,
і реєстр приймав лише артефакти, підписані збірною системою та супроводжувані SBOM.
Люди називали це «бюрократією». Це справді було трохи бюрократично.

Вийшов advisory від постачальника: у екосистемі циркулював компрометований варіант широко вживаного базового образу.
Команди запанікували, бо їхні образи були «FROM того базового». Slack вибухнув.

Командир інциденту виконав простий запит: перелік усіх запущених образів по дайджесту, потім перевірка, які дайджести є у внутрішньому реєстрі.
Більшість продакшн-дайджестів були в реєстрі; кілька — ні. Ті, що не були — прийшли з неврегульованого skunkworks-середовища, яке обходило стандартний пайплайн.

Вони заблокували зовнішні витягування реєстрів на шарі кластера egress і admission. Продакшн залишився стабільним.
Єдині ворклоади, що зламалися — ті, що вже порушували політику, що зробило розмову короткою.

Сумна практика не була «ми безпечні». Вона була «ми можемо довести, що запускаємо».
Ось різниця між інцидентом і пліткою.

Жарт №2: Ваші журнали аудиту як овочі — ніхто їх не любить, але ігнорувати їх з часом стає стилем життя.

Контрольні списки / покроковий план

Покроково: загартуйте ваш intake-пайплайн (те, що ви тягнете в збірки)

  1. Зробіть інвентар всіх зовнішніх джерел: реєстри, репозиторії, Git submodule’і, дії CI, Terraform-модулі, кінцеві точки оновлень постачальників.
  2. Впровадьте внутрішні проксі/дзеркала для пакетів і образів; змусьте збірки тягнути з одного контрольованого місця.
  3. Фіксуйте залежності за допомогою lockfile і незмінних дайджестів. Забороніть «latest» і плаваючі теги в продакшні.
  4. Вимагайте походження: забезпечте, щоб артефакти були підписані і (по можливості) мали метадані атестації/походження.
  5. Скануйте, але не поклоняйтеся сканінгу: використовуйте сканування для пріоритетизації, а не як остаточний вердикт. Чистий скан — не означає чисте ПО.
  6. Розділіть ідентичності збірки та деплою: роль, що збирає, не повинна мати змогу деплойнути в прод без політичних перевірок.
  7. Зробіть оновлення видимими: записуйте кожен артефактний дайджест, який розгорнуто, і зберігайте ці дані для оперативного використання під час інцидентів.

Покроково: загартуйте раннери CI/CD (де атаки на ланцюг постачання стають реальністю)

  1. Ефемерні раннери: віддавайте перевагу короткоживучим раннерам над довгоживучими істотами. Компрометація має помирати разом з VM/контейнером.
  2. Контроль виходу в мережу: збірки за замовчуванням не повинні мати відкритий інтернет; дозволяйте лише переліку реєстрів і проксі пакетів.
  3. Дисципліна зі секретами: використовуйте короткоживучі токени, OIDC-федерування де можливо і обмежуйте креденшіали під конкретніジョоб-и.
  4. Безпечний кеш: кеші на репозиторій/гілку, без спільних записуваних шляхів через межі довіри і періодичне очищення.
  5. Захистіть ключі підписування: тримайте їх у HSM/KMS; ніколи не лишайте їх у файловій системі раннера.
  6. Записуйте метадані збірки: хто збудував, з якого коміту, з якими залежностями, на якому образі раннера.

Покроково: запобіжні заходи в продакшні (де ви зупиняєте погані артефакти)

  1. Admission control, що примушує перевірку підписів і блокує невідомі реєстри.
  2. Фільтрація egress, щоб компоненти постачальників не могли дзвонити куди завгодно.
  3. Рантайм-моніторинг, налаштований під постачальників: базуйте очікувані домени/порти/процеси; алертьте при відхиленнях.
  4. Rollback за дайджестом: можливість швидко відкотитися до відомого доброго дайджесту, без «перебудуй і надійся».
  5. Дріллі з ротації креденшіалів: якщо компонент постачальника скомпрометовано, ви маєте знати, які секрети він міг торкнутися.

Поширені помилки (симптоми → корінь проблеми → виправлення)

1) «Ми розгорнули ту саму версію скрізь, але поведінка різна»

Симптоми: Та сама семантична версія, різні хеші, непослідовна мережева активність.

Корінь проблеми: Ви відстежуєте за тегом/рядком версії замість незмінного дайджесту; існують кілька шляхів доставки (дзеркало vs пряме, stable vs hotfix).

Виправлення: Нав’язуйте фіксацію за дайджестом і єдиний шлях intake. Записуйте дайджести під час деплою і блокуйте дрейф на admission.

2) «Репозиторій виглядає чистим, але зібраний артефакт інший»

Симптоми: Перебудова того ж коміту дає різні артефакти; зачіплені лише CI-збірки.

Корінь проблеми: Не герметичні збірки: підвантаження залежностей під час збірки, змінні базові образи, спільні кеші, скомпрометований раннер/тулчейн.

Виправлення: Робіть збірки детермінованими де можливо: зафіксовані залежності, зафіксовані базові образи, ізольовані кеші, зміцнення раннерів і атестації походження.

3) «Скан безпеки каже зелено, але нас все одно зламали»

Симптоми: Немає виявлених CVE; але спостерігається підозрілий вихідний трафік або доступ до даних.

Корінь проблеми: Payload в ланцюгу постачання — не відомий CVE; це навмисна функція. Сканери знаходять відоме зло, а не намір.

Виправлення: Додавайте перевірки походження, поведінковий моніторинг і сувору політику egress. Сканінг — один з входів, а не вирок.

4) «Ми не можемо сказати, хто що запускав і де»

Симптоми: Під час IR команди сперечаються про версії, ніхто не може швидко надати визначений інвентар.

Корінь проблеми: Відсутність логування подій деплою з дайджестами; недостатній retention; забагато ручних шляхів деплою.

Виправлення: Централізуйте метадані деплою, вимагайте хуків управління змінами і робіть інвентар запитуваним (не похованим в Slack).

5) «Постачальник каже: міняйте ключі, але ми не знаємо які»

Симптоми: Панічні ротації, збої сервісів, втрачені креденшіали.

Корінь проблеми: Надмірно привілейовані інтеграції постачальника і неконтрольований розкиданий масив секретів.

Виправлення: Побудуйте карту секретів: який сервіс використовує який креденшіал, звужуйте їх, і проводьте планові ротації, щоб екстрена ротація не була першим досвідом.

6) «Ми заблокували поганий пакет, але він повернувся»

Симптоми: Залежність з’являється в збірках після видалення; розробники ненавмисно її знову додають.

Корінь проблеми: Транзитивне підвантаження; відсутність політик; lockfile не зафіксований або не перевіряється в CI.

Виправлення: Використовуйте lockfile як джерело істини, примушуйте «без дрейфу lockfile» і додайте allow/deny-політики на рівні проксі/дзеркала.

7) «Наше дзеркало зробило гірше»

Симптоми: Багато систем швидко отримали компрометований пакет, всі з того самого внутрішнього джерела.

Корінь проблеми: Дзеркало довіряється, але не моніториться; ingest автоматичний без верифікації; немає правил незмінності чи збереження.

Виправлення: Додайте верифікацію ingest (підписи, контрольні суми), робіть дзеркало додавальним/незмінним для релізів і алертіть на несподівані upstream-зміни.

Питання та відповіді (FAQ)

1) Атаки на ланцюг постачання — це головно проблема open-source?

Ні. Open-source видимий, тому про нього більше говорять. Комерційні постачальники теж компрометуються — і інколи мають ширше розповсюдження та глибші привілеї.
Ризик пов’язаний з довірою та доступом, а не з ліцензією.

2) Якщо ми вимагаємо підписування коду, ми у безпеці?

Безпечніше, але не гарантія. Підпис повідомляє, хто підписав. Якщо ключ підписування або пайплайн підписування компрометовано, ви вірно підтверджуватимете шкідливий артефакт.
Потрібен захист ключів, інформація про походження і виявлення зміни підписних ідентичностей.

3) У чому різниця між SBOM і походженням (provenance)?

SBOM перераховує, що всередині (компоненти). Provenance розповідає, як це побудовано (процес, середовище, ідентичності).
SBOM допомагає оцінити вплив; provenance допомагає вирішити, чи варто довіряти артефакту.

4) Чи потрібні відтворювані збірки, щоб бути «добрим» у цьому?

Відтворювані збірки — відмінно, але не дозволяйте перфекціонізму блокувати прогрес. Почніть з незмінних дайджестів, підписування артефактів та фіксованих залежностей.
Відтворюваність — довший проєкт, вартий для критичних компонентів.

5) Як поводитися з постачальниками, яким потрібен вихід в інтернет?

Ставте це як високоризикову інтеграцію: явні allow-листи, TLS-інспекція де доречно та логування.
Попросіть у постачальника фіксований набір доменів/IP і документований протокол. Якщо не можуть надати — це рішення ризику, а не технічна дрібниця.

6) Що робити, коли постачальник публікує вказівку «міняйте креденшіали»?

Міняйте в такому порядку: (1) креденшіали, що використовуються CI/CD і системами збірки, (2) токени інтеграцій постачальника з широким API-доступом,
(3) довгоживучі спільні секрети. Також аудитуйте логи використання до і після ротації, щоб виявити продовження зловживань.

7) Можемо просто заблокувати публічні реєстри повністю?

Часто — так, і це слід робити для продакшн-збірок. Розробникам може знадобитися інтернет для досліджень, але CI має тягнути через контрольовані проксі.
Блокування просте; складніше зробити проксі зручним і швидким, щоб команди не обходили його.

8) Як запобігти dependency confusion?

Використовуйте приватні простори імен де можливо, налаштовуйте менеджери пакетів віддавати перевагу внутрішнім реєстрам і блокуйте невідомі пакети на проксі.
Операційний трюк: зробіть безпечний шлях найпростішим, або люди знайдуть творчі способи його обійти.

9) Який перший метрік варто відстежувати, щоб знати, що ви покращуєтеся?

Середній час до інвентаризації: скільки часу потрібно, щоб відповісти «де запущено дайджест X?» по середовищах.
Якщо це більше ніж хвилини, ваш наступний інцидент дорого коштуватиме.

Висновок: кроки, які ви можете виконати цього тижня

Безпека ланцюга постачання — це не модний тренд. Це здатність обмежувати довіру, доводити походження і реагувати без здогадок.
Нападники ставлять на те, що ви не зможете відповісти на базові питання під тиском. Доведіть їм протилежне.

  • Виберіть одне: примусіть фіксацію образів за дайджестом у продакшні або заблокуйте зовнішні реєстри. Зробіть хоча б одне цього тижня.
  • Полегшіть інвентаризацію: зберігайте метадані деплоїв (дайджести, версії пакетів, ID збірок) там, де командири інцидентів можуть швидко їх запитати.
  • Зміцніть CI: ізолюйте раннери, обмежте egress і перемістіть ключі підписування поза файловою системою раннерів.
  • Перетворіть довіру до постачальників на обмеження: принцип найменших привілеїв, явний egress і лише перевірені артефакти.
  • Проведіть тренування: симулюйте «оновлення постачальника скомпрометоване» і виміряйте час на обсяг, блокування та ротацію.

Якщо нічого більше не зробите: припиніть деплой за тегом, почніть деплой за дайджестом і вимагайте підпису, який ви дійсно перевіряєте.
Це перетворить широкий клас інцидентів ланцюга постачання з «загадкового масового зараження» в «заблоковано на вході».

← Попередня
Ubuntu 24.04 «Неприпустима інструкція»: прапорці CPU проти бінарників — виправлення розгортань чисто (випадок №56)
Наступна →
Ubuntu 24.04: VPN ламає DNS — виправте резолвери та маршрути у правильному порядку (випадок №52)

Залишити коментар