Про які ризики / вразливості безпеки повинен знати кожен програміст C? [зачинено]


13

Існує багато ризиків для безпеки, пов’язаних із тісним контактом з обладнанням, на відміну від використання добре перевірених та перевірених API з мов програмування високого рівня. Набагато простіше викликати переповнення буфера в C, ніж на такій мові, як Java.

Які ризики чи вразливості (наприклад, переповнення буфера), про які повинен знати кожен програміст C (вразливості IE, що стосуються програмістів на C)? До яких проблем це може призвести? Як їх уникнути, і які поширені помилки призводять до того, що вони виникають у програмах?


Що з цим списком: owasp.org/index.php/Category:OWASP_Top_Ten_Project Що ще потрібно для цього?
S.Lott

2
@ S.Lott: Здається, дуже багато стосується проблем безпеки в веб-розробці. Здається, загалом на це є більше ресурсів, ніж те, що я насправді прошу, здається.
Анто

@Anto: оновіть питання, щоб розрізняти всі ресурси щодо безпеки та безпеку, про яку ви питаєте.
S.Lott

@ S.Lott: Я не впевнений, що ти маєш на увазі. Я прошу безпеки, яка має важливе значення для більшості програмістів на C, тобто такі речі, як переповнення буфера та інші речі, можливі в C.
Анто,

@Anto: "Здається, що в цьому [веб-безпеці?] Взагалі є більше ресурсів, ніж те, про що я насправді прошу" Здається, ви говорите, що ви питаєте про якусь безпеку, яка не є безпекою в Інтернеті. Правда? Якщо це так, оновіть питання, щоб пояснити, що ви шукаєте. Помилковий? Потім будуть просити про веб - безпеки, в цьому випадку, чому не список OWASP згадується в вашому питанні?
S.Lott

Відповіді:


13

Переливи буфера - великі. Ніщо в 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, але вони можуть спричинити проблеми із безпекою.


Не потрібно використовувати printf("%s", str)для голої струни, коли puts(str)буде робити ту саму роботу.
Blrfl

@Blrfl, але putsдодає символ нового рядка, поки printfнемає.
праворуч

Може також зробити fputs(str, stdout), що ні.
Blrfl

Щодо цілого переповнення: Використання підписаних вводів не є рішенням, оскільки переповнення їх спричинить UB. Єдине (болісне) рішення - це або формально довести, що ви ніколи не будете переповнювати, або перевірити під час виконання (але перевірити правильно, що також складно, не переповнюючи чек).
sleske

@DavidThornley: C11 & C ++ 14 стандарт видалено отримує () функцію зі стандартної бібліотеки через її небезпеку.
Деструктор

5

Деякі з специфічних для С ризиків включають: переповнення буфера , форматування рядкових атак та цілих переповнення .


1
Щодо переповнення буфера немає нічого специфічного для C - це може мати будь-яка мова з покажчиками. Переповнення цілих чисел застосовуються майже до будь-якої мови, і це може легко траплятися і в керованому коді.
Стів

1
@Steve, його насправді не вказівники, які викликають цю проблему, але те, як мова не виконує межі масиву.
Дуг Т.

2
@Steve питання не в питанні про речі, які стосуються лише C, а про те, що слід знати C програмістам.
AttackingHobo

1
@Steve: C незвичайно сприйнятливий до переповнення буфера, частково через відсутність підтримки для перевірки діапазону та кількість функцій бібліотеки, які з радістю переповнюють буфери для вас.
Девід Торнлі

Я розумію, що питання стосується питання C зокрема, але я вважаю, що варто уточнити, якщо відповідь буде прочитана поза контекстом, що ці ризики є загальнішими. Зокрема, розробники керованого коду (IMHO) надто поступаються над безпекою, і цілі переповнення зокрема впливають на більшість мов.
Стів

4

Тут легко пропустити ризик, який може спричинити проблеми, які потребуватимуть години.

Розглянемо наступний код, який складе без проблем.

if(lpstr_current_state = CONST_EMERGENCY_STATE_HOLY_CRAP)
{
    do_warn_joint_chiefs_of_staff_of_nuclear_attack();
}

Коли ви перевіряєте, чи lpstr_current_stateнемає, CONST_EMERGENCY_STATE_HOLY_CRAPви насправді призначаєте. Краще завжди ставити постійну змінну зліва. Якщо ви ставите константу зліва, компілятор не вдасться, оскільки ви не можете призначити значення змінній.

if(CONST_EMERGENCY_STATE_HOLY_CRAP = lpstr_current_state)
{
    do_warn_joint_chiefs_of_staff_of_nuclear_attack();
}

Тоді ви можете легко сказати собі: "Святе дерьмо, що могло бути погано", фіксуючи код для читання ...

if(CONST_EMERGENCY_STATE_HOLY_CRAP == lpstr_current_state)
{
    do_warn_joint_chiefs_of_staff_of_nuclear_attack();
}

7
Компілятору це легко зрозуміти як попередження, на відміну від деяких інших проблем. На жаль, не всі компілятори спрощують це.
Девід Торнлі

2
Це може статися і в інших мовах , відмінних від C, будь-яку мову , який використовує =і ==.
FrustratedWithFormsDesigner

3
Це теж насправді не вразливість безпеки, це помилка.
Кріс Пітман

1
Вони називаються умовами Йоди.

2
@ Kristofer Hoch: Якщо ми збираємося назвати будь-яку ймовірну помилку C, і розглянемо це тут, нам знадобиться набагато більший форум.
Девід Торнлі

0

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

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

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


Хоча я погодився б із абзацом другим та третім, я покладу всю провину на зловмисника на мої очі. Для успішної атаки завжди потрібно два: програміст, який накручується, і зловмисник, який ловить програміста в акті. Однак вразливість безпеки є ще до того, як зловмисник може її використати. І в цьому винен програміст.
cmaster - відновити моніку
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.