Off by one overflow
Last updated
Last updated
Learn & practice AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE) Learn & practice GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Маючи доступ лише до переповнення на 1 байт, зловмисник може змінити поле size
наступного блоку. Це дозволяє маніпулювати тим, які блоки насправді звільнені, потенційно створюючи блок, що містить інший легітимний блок. Експлуатація подібна до подвійного звільнення або перекриваючих блоків.
Існує 2 типи вразливостей відхилення на один:
Довільний байт: Цей тип дозволяє перезаписати цей байт будь-яким значенням
Нульовий байт (off-by-null): Цей тип дозволяє перезаписати цей байт лише значенням 0x00
Загальний приклад цієї вразливості можна побачити в наступному коді, де поведінка strlen
і strcpy
є непослідовною, що дозволяє встановити байт 0x00 на початку наступного блоку.
Це можна експлуатувати за допомогою House of Einherjar.
Якщо використовувати Tcache, це можна використати для ситуації подвійного звільнення.
Серед інших перевірок, тепер щоразу, коли шматок вільний, попередній розмір порівнюється з розміром, налаштованим у метаданих шматка, що робить цю атаку досить складною з версії 2.28.
Ця атака більше не працює через використання Tcaches.
Більше того, якщо ви спробуєте зловживати нею, використовуючи більші шматки (щоб tcaches не були залучені), ви отримаєте помилку: malloc(): invalid next size (unsorted)
Зробити так, щоб шматок містився всередині іншого шматка, щоб запис доступу до цього другого шматка дозволяв перезаписати вміщений.
Off by one overflow для зміни інформації про метадані розміру.
Виділити три шматки A
, B
і C
(скажімо, розміри 0x20), і ще один, щоб запобігти консолідації з top-chunk.
Вивільнити C
(вставлений у 0x20 Tcache free-list).
Використати шматок A
, щоб переповнити B
. Зловживати off-by-one, щоб змінити поле size
у B
з 0x21 на 0x41.
Тепер у нас є B
, що містить вільний шматок C
.
Вивільнити B
і виділити шматок 0x40 (він знову буде розміщений тут).
Ми можемо змінити вказівник fd
з C
, який все ще вільний (отруєння Tcache).
3 шматки пам'яті (a, b, c) резервуються один за одним. Потім середній шматок звільняється. Перший шматок містить уразливість off by one overflow, і зловмисник зловживає нею з 0x00 (якщо попередній байт був 0x10, це змусить середній шматок вказувати, що він на 0x10 менший, ніж є насправді).
Потім у середньому звільненому шматку (b) виділяються ще 2 менші шматки, однак, оскільки b + b->size
ніколи не оновлює шматок c, тому що вказана адреса менша, ніж повинна бути.
Потім b1 і c звільняються. Оскільки c - c->prev_size
все ще вказує на b (тепер b1), обидва консолідуються в один шматок. Однак b2 все ще знаходиться між b1 і c.
Нарешті, виконується новий malloc, що відновлює цю область пам'яті, яка насправді буде містити b2, що дозволяє власнику нового malloc контролювати вміст b2.
Це зображення ідеально пояснює атаку:
Off-by-one через strlen
, що враховує поле size
наступного шматка.
Використовується Tcache, тому загальна атака off-by-one працює для отримання примітиву довільного запису з отруєнням Tcache.
Можливо зловживати off by one, щоб витягти адресу з купи, оскільки байт 0x00 в кінці рядка перезаписується наступним полем.
Довільний запис отримується шляхом зловживання записом off by one, щоб вказівник вказував на інше місце, де буде побудовано фейкову структуру з фейковими вказівниками. Потім можна слідувати за вказівником цієї структури, щоб отримати довільний запис.
Адреса libc витікає, оскільки якщо купа розширюється за допомогою mmap, пам'ять, виділена mmap, має фіксований зсув від libc.
Нарешті, довільний запис зловживається для запису в адресу __free_hook з адресою одного гаджета.
Існує уразливість NULL off by one у функції getline
, яка читає рядки введення користувача. Ця функція використовується для читання "ключа" вмісту, а не самого вмісту.
У звіті створюється 5 початкових шматків:
chunk1 (0x200)
chunk2 (0x50)
chunk5 (0x68)
chunk3 (0x1f8)
chunk4 (0xf0)
chunk defense (0x400), щоб уникнути консолідації з top chunk.
Потім шматки 1, 5 і 3 звільняються, тому:
[ 0x200 Chunk 1 (free) ] [ 0x50 Chunk 2 ] [ 0x68 Chunk 5 (free) ] [ 0x1f8 Chunk 3 (free) ] [ 0xf0 Chunk 4 ] [ 0x400 Chunk defense ]
[ 0x200 Chunk 1 (free) ] [ 0x50 Chunk 2 ] [ 0x68 Chunk 5 (free) ] [ 0x1f8 Chunk 3 (free) ] [ 0xf0 Chunk 4 ] [ 0x400 Chunk defense ]