Переповнення буфера: причини, ефективні методи вирішення проблеми і необхідний захист

Простий вектор використання буфера

При роботі з вихідним кодом потрібно звернути особливу увагу, де використовуються буфери і модифікуються. Особливо слід відзначити функції, що відносяться до висновку, наданого користувачем або іншим зовнішнім джерелом, оскільки вони забезпечують простий вектор для використання, коли виявлено переповнення стека буфера. Наприклад, коли юзер ставить запитання «так» або «ні», доцільно зберегти рядкові дані користувача в невеликому buffer для рядка «так», як показано в наступному прикладі.

Дивлячись на код, видно, що перевірка кордонів не виконується. Якщо користувач вводить «можливо», то програма аварійно завершувати роботу, а не запитувати у нього відповідь, який записується в buffer незалежно від його довжини. У цьому прикладі, оскільки user answer є єдиною оголошеної змінної, значення в стеку будуть значенням зворотної адреси або місцем в пам’яті, куди програма повернеться після виконання функції ask Question.

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

Якщо першим кроком для виявлення переповнення буфера у вихідному коді є розуміння того, як вони працюють, другим етапом є вивчення зовнішнього введення і маніпуляцій з буфером, то третім кроком буде необхідність дізнатися, які функції схильні до цієї проблеми і які можуть діяти як «червоні прапори». Функція gets відмінно підходить для запису за межами наданого їй buffer. Насправді це якість поширюється на все сімейство пов’язаних можливостей, включаючи strcpy, strcmp і printf/sprintf, скрізь, де використовується одна з цих функцій уразливості переповнення.