Моніторинг системних викликів Linux



Якщо ви інженер в організації, що використовує Linux промислової експлуатації, у мене до вас два невеличких питання.
  1. Скільки унікальних вихідних TCP-з'єднань встановили ваші сервери за останню годину?
  2. Які процеси та користувачі ініціювали встановлення цих сполук?
Якщо ви в змозі відповісти на обидва питання, відмінно — далі можете не читати. А якщо відповіді немає, то отримати цю інформацію допоможе go-audit.


Системні виклики (syscalls) — засіб спілкування між користувацькими програмами і ядром Linux. Вони використовуються для таких речей, як з'єднання мережевих сокетів, читання файлів, завантаження модулів ядра, створення нових процесів і т. д. і т. п. Якщо ви коли-небудь використовували strace, dtrace, ptrace або щось подібне зі словом trace у назві, то системні виклики вам вже не в новинку.
Більшість людей використовують згадані trace-інструменти для налагодження стоять осібно одиничних випадків, ми ж в Slack збираємо системні виклики в якості джерела даних для постійного моніторингу, що і вам радимо.


Linux Audit був доданий в ядро починаючи з версії 2.6.(14?). Система аудиту складається з двох основних компонентів: код ядра для моніторингу системних викликів і демон, журналирующий пов'язані з цими викликами події.
Архітектура kauditd і go-audit
Давайте подивимося на приклад використання auditd. Припустимо, ми хочемо записувати в журнал події читання файлу /data/topsecret.data. (будь Ласка, не зберігайте секретну інформацію у файлі під назвою topsecret.data). При використанні auditd потрібно спочатку повідомити ядру про наше бажання отримувати інформацію про цікаві події. Це робиться за допомогою команди
auditctl
, яка запускається від імені суперкористувача:
auditctl -w /data/topsecret.data -p rwxa

Тепер ядро буде генерувати подія кожен раз, коли хтось отримає доступ до
/data/topsecret.data
(в тому числі і через symlink). Це подія надсилається процесу в просторі користувача (зазвичай auditd) через щось під назвою netlink-сокет. (Іншими словами, netlink— це коли ви говорите ядру посилати повідомлення процесу за допомогою його PID на відповідний сокет.)
У більшості Linux-дистрибутивів процес простору користувача auditd пише дані в
/var/log/audit/audit.log
. Якщо підключений до netlink-сокету юзерспейсный процес відсутня, повідомлення будуть з'являтися в консолі і можуть бути переглянуті за допомогою
dmesg
.
Все це чудово, але спостереження за єдиним файлом — це дуже простий приклад. Давайте візьмемо що-небудь цікавіше, що-небудь пов'язане з мережею.
Демони (і ще бідова netcat) зазвичай використовують системний виклик
listen
для організації прийому вхідних мережевих з'єднань. Наприклад, якщо Apache бажає слухати 80-й порт, він надсилає відповідний запит ядру. Для журналювання цих подій ми знову повідомляємо ядру про наші наміри з допомогою
auditctl
:
auditctl -a exit,always -S listen

Тепер кожен раз, коли процес починає слухати на якому-небудь сокеті, ми отримуємо відповідне повідомлення. Здорово! Такий облік може бути налаштована на будь-який системний виклик. Для вирішення зазначених на початку статті питань нам потрібен
connect
. Щоб організувати спостереження за кожним новим процесом і командою, можна використовувати
execve
.
Суперзамечание. Ми не обмежені лише діями користувачів. Подумайте про такі цікаві події, як запуск Апачем
bash
або створення вихідного з'єднання до якоїсь незрозумілої IP-адресою, і про те, що ці дії можуть означати.



Отже, тепер у нас є деяка кількість подій в
/var/log/audit/audit.log
, але файли журналу — це ще не система моніторингу. Що нам робити з усіма зібраними даними? На жаль, у формату журналу auditd є особливості, які ускладнюють його обробку.
  1. Формат даних в основному представлений у вигляді «ключ=значення».
  2. Подія може займати одну або кілька рядків.
  3. Події можуть переплітатися і з'являтися не по порядку.
Приклад виводу auditd
Є кілька інструментів для обробки подій журналу (наприклад,
aureport
та
ausearch
), але вони, схоже, націлені на розслідування вже сталося події, а не на постійний моніторинг.


Ми бачили багато варіантів корисного використання одержуваних від auditd даних. Але потрібно було придумати спосіб масштабування такої системи моніторингу. У підсумку в якості заміни частини auditd, що працює у просторі користувача, ми вирішили створити go-audit. Ось цілі, на які ми орієнтувалися:
  1. Конвертування багаторядкових подій auditd JSON-blob.
  2. Спілкування з ядром безпосередньо з допомогою netlink.
  3. Висока продуктивність.
  4. Мінімізація (або повне виключення) фільтрації подій на спостережуваних вузлах.
Перші три умови, швидше за все, очевидні й зрозумілі, а останнє вимагає пояснення.


Ось два головні запитання, на які ми повинні відповісти при обговоренні четвертого пункту:
  • Чому ви не хочете фільтрувати події на кожному сервері?
  • чи Не будете ви пересилати багато зайвої інформації?
Уявіть, що на ваших серверах встановлена утиліта
curl
(ймовірно, що так воно і є). Під час чергових навчань товариш з «червоної команди» (red team) використовує
curl
для завантаження руткіта і потім для вивантаження даних. Отримавши цей урок, ви починаєте журналювати кожну команду і фільтрувати все, крім
curl
, при запуску якої щоразу піднімається тривога.
У такого підходу є кілька проблем.
  1. Існує приблизно 92 481 124,5 способу виконати завантаження руткіта і вивантаження даних без використання
    curl
    . Ми навіть перерахувати їх не зможемо.
  2. Зломщик може подивитися ваші правила для auditd і помітити, що ви стежите за
    curl
    .
  3. Є цілком легітимні випадки використання
    curl
    .
Нам потрібно дещо краще...
А не посилати всі дані централізованої системи журналювання та оповіщення, замість того щоб виводити конкретні команди на місцях? У цього підходу є дещо дивно корисних властивостей.
  1. Зломщик не знає, які системні виклики вас цікавлять. (А як влучно підмітив Rob Fuller, невидимі пастки викликають у хакерів нічні кошмари.)
  2. Ми можемо аналізувати взаємозв'язок різних подій, щоб розуміти, коли виконання
    curl
    цілком законно, а коли ні.
  3. Нові правила можна оцінювати і тестувати на архівних даних.
  4. Тепер у нас є зовнішнє незалежне сховище криміналістичної інформації.


Отже, друзі, зустрічайте — go-audit. Ми випускаємо цей інструмент як з відкритим вихідним кодом. Їм можна користуватися вільно і абсолютно безкоштовно. Хлопці з нашої команди Secops створили першу версію go-audit більше року тому, і ми використовуємо його в промисловій експлуатації майже стільки ж. Це невеликий, але дуже важливий елемент нашої інфраструктури моніторингу. Рекомендую подивитися мою попередню статтю про прийняте у нас підході до роботи з сигналами тривоги (alerting).
В репозиторії go-audit розміщено безліч прикладів конфігурування та збору даних. Тут в Slack ми використовуємо rsyslog + relp, оскільки хочемо якомога швидше прибирати дані з сервера, але при цьому мати можливість записати події на диск, якщо syslog тимчасово не може передати їх по мережі. Ми б могли без праці перейти на інший механізм доставки логів і будемо раді почути ваші ідеї.
Ми запрошуємо в проект нових учасників і сподіваємося, що go-audit буде корисний не тільки нам. Протягом року цей репозиторій був відкритий певній кількості людей поза Slack, і деякі з наших друзів вже використовують його в промисловій експлуатації.


Можливо, ви звернули увагу, що в цій статті ще жодного разу не зустрілося слово «безпека». Давайте це обговоримо. Я вважаю, що багато інструменти загального призначення часто можуть бути використані і для забезпечення безпеки, але зворотне, як правило, невірно. Auditd видає дані моніторингу безпеки в такому вигляді, що їх складно використовувати яким-небудь іншим способом, а go-audit був розроблений як інструмент загального призначення. Його корисність відразу очевидна для фахівців служб експлуатації і розробників, які можуть використовувати go-audit для вирішення проблем на всьому різноманітті сучасних і в тому числі дуже великих систем.
Давайте повернемося до питань, поставлених на початку статті. Будь-яка компанія з IDS/IPS/Netflow/PCAP і т. д. на мережевому шлюзі може багато що сказати про своїх мережевих з'єднаннях і, можливо, відповісти на перше питання. Але ні одне з перерахованих рішень не надасть контекст у вигляді user/pid/command, необхідний для відповіді на друге питання. А в ньому якраз і полягає відмінність між «хтось запустив що-то де-то в нашій мережі, і воно з'єдналося з таким-то IP» і «Mallory запустила curl від імені root bigserver01 і підключилася до 1.2.3.4, порт 1337».
У Slack ми часто говоримо: «Не дай краще стати ворогом хорошого». Go-audit не ідеальний, але ми вважаємо, що цей інструмент дійсно дуже непоганий, і ради їм з вами поділитися.


FAQ:

Чому auditd, а не sysdig або osquery?
Osquery — відмінний інструмент. Насправді в Slack ми його теж використовуємо. Але для бойових серверів воліємо go-audit. Причина полягає в тому, що ці системи працюють у режимі 24/7, і нам потрібно постійно передавати дані. З osquery ми отримуємо знімок поточного стану машини. Якщо що-то завершило виконання в інтервалі між опитуваннями, є всі шанси це пропустити. Думаю, така модель підходить для ноутбуків і інших пристроїв, але для високодоступних систем віддаю перевагу передавати дані безперервним потоком.
Sysdig також є чудовим інструментом налагодження, і я використав його досить активно. Основна проблема в тому, що йому потрібен модуль ядра на кожній машині. Sysdig Falco здається корисним, але вони вважають за краще фільтрувати події на кожному об'єкті моніторингу. А, як було сказано вище, нам цікавіше зберігати правила централізовано, поза зоною досяжності зломщика, який отримав доступ до системи.
Auditd гарний тим, що існує вже досить давно і є частиною ядра основної гілки. Це найпоширеніший механізм аудиту системних викликів в світі Linux. Ось тому ми його й вибрали.
Що нам робити з усіма цими сигналами тривоги?
Вони відправляються в кластер Elasticsearch. Там для генерації сигналів тривоги на основі аналізу постійно надходять даних і для загального моніторингу ми використовуємо ElastAlert. Також можна подивитися на інші популярні системи журналювання, здатні працювати з великими обсягами даних, але (моя особиста думка не обов'язково має збігатися з думкою мого роботодавця) у мене фундаментальні проблеми з грошовою оцінкою структур, які спонукають записувати в журнали менше даних, щоб заощадити фінанси.
журналах якого розміру йде мова?
Коротка відповідь: значення може змінюватися в дуже широких межах.
Довгий відповідь: залежить від того, які системні виклики журналювати і як багато серверів будуть це робити. Ми пишемо сотні гігабайт в день. Здається, це багато, але в даний момент у нас постійно журналируются події з 5500 машин. Також слід враховувати виділення кластеру додаткових ресурсів для відбиття атак типу DoS.
Чому rsyslog?
Ми володіємо значним досвідом роботи з rsyslog, у якого є декілька корисних властивостей. Наполегливо рекомендуємо використовувати версію 8.20+, де ми виправили кілька помилок. У нас була можливість довірити виконання доставки повідомлень і самому go-audit, але вигоди такого підходу не переважили переваг використання інструменту, який справно служить нам вже кілька років.
Подяки
  • Моєму колезі Nate Brown, зробила go-audit набагато краще.
  • Хлопцям з Mozilla, які займаються audit-go, за те, що надихнули нас на цей проект.
  • Великій кількості людей, які прочитали цю статтю і написали корисні відгуки.
  • Chicago Cubs за перемогу в чемпіонаті.
Джерело: Хабрахабр

0 коментарів

Тільки зареєстровані та авторизовані користувачі можуть залишати коментарі.