Stack Canaries

Вивчайте хакінг AWS від нуля до героя з htARTE (HackTricks AWS Red Team Expert)!

Інші способи підтримки HackTricks:

StackGuard та StackShield

StackGuard вставляє спеціальне значення, відоме як канарейка, перед EIP (Extended Instruction Pointer), зокрема 0x000aff0d (представляє собою нуль, символ нового рядка, кінець файлу, символ повернення каретки), щоб захистити від переповнення буфера. Однак функції, такі як recv(), memcpy(), read() та bcopy(), залишаються вразливими, і вони не захищають EBP (Base Pointer).

StackShield використовує більш складний підхід, ніж StackGuard, зберігаючи Глобальний Стек Повернення, який зберігає всі адреси повернення (EIP). Ця настройка забезпечує відсутність шкоди від будь-якого переповнення, оскільки вона дозволяє порівняння збережених та фактичних адрес повернення для виявлення випадків переповнення. Крім того, StackShield може перевіряти адресу повернення на межеве значення, щоб виявити, чи вказує EIP за межі очікуваного простору даних. Однак цей захист можна обійти за допомогою технік, таких як Return-to-libc, ROP (Return-Oriented Programming) або ret2ret, що свідчить про те, що StackShield також не захищає локальні змінні.

Stack Smash Protector (ProPolice) -fstack-protector:

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

Канарейка - це випадкове число, отримане з /dev/urandom або значення за замовчуванням 0xff0a0000. Вона зберігається в TLS (Thread Local Storage), що дозволяє спільним просторам пам'яті між потоками мати потокові глобальні або статичні змінні. Ці змінні спочатку копіюються з батьківського процесу, і дочірні процеси можуть змінювати їх дані без впливу на батька або сестер. Однак, якщо використовується fork() без створення нової канарейки, всі процеси (батько і діти) діляться однією і тією ж канарейкою, що робить її вразливою. На архітектурі i386 канарейка зберігається за адресою gs:0x14, а на x86_64 - за адресою fs:0x28.

Ця локальна захист ідентифікує функції з буферами, які вразливі до атак, та впроваджує код на початку цих функцій для розміщення канарейки, а в кінці - для перевірки її цілісності.

Коли веб-сервер використовує fork(), це дозволяє проводити атаку методом брутфорсу для вгадування канарейки по байтам. Однак використання execve() після fork() перезаписує простір пам'яті, анулюючи атаку. vfork() дозволяє дочірньому процесу виконуватися без дублювання до тих пір, поки він не спробує записати, після чого створюється дублікат, пропонуючи інший підхід до створення процесу та роботи з пам'яттю.

Обхід

  • Витік канарейки та подальше перезаписування її (наприклад, переповнення буфера) її власним значенням.

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

  • Якщо в бінарному файлі є якась цікава вразливість витоку, можливо її витік.

Last updated