"Разработчики OpenBSD говорят, что единственное отличие между
багом
и эксплойтом — интеллект взломщика, и это по большому счету, правда."
Девид Чесснолл

На портале NetSago,
опубликован перевод на русский язык цикла статей Девида Чиснолла — "Writing
Insecure C". Как известно программирование на языке C "часто приводит к
написанию очень опасного кода". Язык C имеет все необходимые "возможности для
написания безопасного кода, но не делает эти вещи сам". Поэтому в данном цикле
статей, исследуются стандартные примеры ошибок в коде, а также, даются
рекомендации того, как их и избежать.

В статьях Девид Чиснолл затрагивает различные виды кода, приводящие к ошибкам
и касающиеся:

  • проверки ошибок;
  • начальных значений;
  • проблем целых;
  • проблем с памятью;
  • буфера и строк.

Рассмотрим ряд примеров из этих статей. Что касается проверки ошибок, то
автор отмечает, что современные языки программирования содержат "некоторый
механизм по обработке исключений", хотя последние представляют собой плохую
идею, т.к. усложняют управление ходом программы и имеют "большинство
недостатков, от которых страдали программы с GOTO".

Еще пример из области проверки ошибок. Всегда необходимо проверять значения,
которые возвращает malloc. Например, в спецификации языка C говориться, что
malloc должна вернуть NULL в случае, если памяти недостаточно. Но в Linux он
возвращает NULL, "если в системе нет достаточного виртуального пространства
адресов, чтобы выполнить выделение памяти", а в случае недостатка памяти
возвращает ошибку, при попытке использовать эту память.

Причиной странного поведения программы может стать хранение значения
указателя в int. На ряде 64-битных платформ это не работает. Поэтому, указатель
необходимо хранить в intptr_t, который определен стандартом C99.

Еще один пример, из раздела проблемы с памятью. Так, например, функция
asprintf() выделяет свой собственный буфер с помощью malloc. Но она ставит новую
проблему — "когда вызывающая функция должна освобождать указатели, которые
возвращает вызываемая функция?". Часто в документацию о функции помещают строку
"вызывающая функция должна освободить возвращаемый указатель", но при этом
становиться сложно взглянуть на часть кода и определить, "валидна" ли она. Автор
предлагает следующее решение: заключать в оболочку каждый указатель —

typedef struct _RefCountedBuffer
{
void *buffer;
int refcount;
void (free*)(struct _RefCountedBuffer*);
} *RefCountedBuffer;

Стоит отметить, что круг проблем затронутый Девидом Чисноллом в его цикле
статей гораздо шире того, что мы здесь обозначили. Мы привели, только, наиболее
понравившиеся примеры. Завершим обзор его словами: "Чтобы избежать проблем,
программист должен основываться на хорошем коде, а не на возможностях языка.".

Ссылки


http://www.informit.com/articles/article.aspx?p=1249297
— Writing Insecure C,
Part 1;


http://www.informit.com/articles/article.aspx?p=1249298
— Writing Insecure C,
Part 2;


http://www.informit.com/articles/article.aspx?p=1249299
— Writing Insecure C,
Part 3;


http://netsago.org/ru/docs/1/14/
— перевод цикла статей.

Оставить мнение

Check Also

Windows 10 против шифровальщиков. Как устроена защита в обновленной Windows 10

Этой осенью Windows 10 обновилась до версии 1709 с кодовым названием Fall Creators Update …