Переливи буфера - великі. Ніщо в C не перевірено діапазон за замовчуванням, тому дуже просто перезаписати буфер. Існує стандартна функція бібліотеки gets()
, яку не можна зупинити від переповнення буфера, і її майже ніколи не можна використовувати.
Існують деякі методи на рівні реалізації, що перешкоджають експлуатації, такі як скремблювання блоків купи, але це не зупинить переповнення буфера в локальні буфери, які часто можуть робити цікаві речі, такі як зміна адреси, до якої повернеться функція.
Немає хорошого загального рішення в C. Багато функцій бібліотеки мають версії, які обмежують кількість запису. хоча розрахувати це може бути незграбно. Існує програмне забезпечення, яке може виявити переповнення буфера купи в тесті, доки запускається відповідний тест, і переповнення стека часто виявляється як збій у тестуванні. Крім цього, це питання ретельного кодування та перегляду коду.
Пов'язане питання - це проблема запису в буфер, занадто малий одним символом, забуваючи, що для рядка C, який має довгих n символів, потрібно n + 1 символів через '\0'
термінатор. Якщо зловмиснику вдасться зберегти рядок без термінатора, будь-яка функція C, що очікує на рядок, буде продовжувати обробку, поки не потрапить на нульовий байт, що може призвести до копіювання або виведення більше інформації, ніж бажано (або потрапляння на захищену пам'ять для атаки DOS ). Знову ж таки, рішення - це огляд обізнаності, турботи та коду.
З printf()
сім'єю є ще один ризик . Якщо ви коли-небудь пишете char * str; ... printf(str);
, ви налаштовуєте себе на проблеми, якщо він str
містить "%" під час друку. %n
Директива формат дозволяє printf()
записати в пам'ять. Рішенням є printf("%s", str);
або puts(str);
. (Також використовуйте C99 snprintf()
замість sprintf()
.)
Використання непідписаних цілих чисел, зокрема в якості індексів циклу, може спричинити проблеми. Якщо призначити невелике негативне значення неподписаному, ви отримаєте велике додатне значення. Це може підірвати такі речі, як обробка лише N примірників чогось, або обмежених функцій на кшталт strncpy()
. Вивчіть усі непідписані цілі числа. Ви можете уникнути unsigned short
, оскільки велике значення одного з них перетвориться на велике позитивне значення у int
.
Не забувайте, що константа символів у С насправді є int
. Написати щось на кшталт char c; while((c = getchar()) != EOF) ...
може легко не вдатися, оскільки EOF
не буде представницьким в char
.
Я можу придумати набагато більш характерні помилки C, але вони можуть спричинити проблеми із безпекою.