19 смертных грехов, угрожающих безопасности программ - страница 14

Шрифт
Интервал


const size_t MAX_BUF = 256;

void LessBadCode(char* input)

{

size_t len;

char buf[MAX_BUF];

len = strlen(input);

// конечно, мы можем использовать strcpy безопасно

if(len < MAX_BUF)

strcpy(buf, input);

}

Родственные грехи

С этим грехом тесно связано переполнение целых чисел. Если вы пытаетесь устранить ошибки переполнения буфера путем использования функций работы со строками семейства strn… или вычисляете размер выделяемого из кучи буфера, то очень важно не допускать арифметических ошибок.

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

Вариантом переполнения буфера является запись в массив без контроля выхода за границы. Если противник сумеет прямо или косвенно подсунуть индекс массива и вы не проверите, что он принадлежит допустимому диапазону, то возможна запись по произвольному адресу в памяти. При этом не только изменяется поток выполнения программы, но могут быть затерты несмежные области памяти, а это сводит на нет все меры противодействия переполнению буфера.

Где искать ошибку

Вот на что нужно обращать внимание в первую очередь:

□ любые входные данные, будь то из сети, из файла или из командной строки;

□ передача данных из вышеупомянутых источников входных данных во внутренние структуры;

□ использование небезопасных функций работы со строками;

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

Выявление ошибки на этапе анализа кода

Обнаружить присутствие этого греха во время анализа кода может быть как совсем легко, так и очень сложно. Проще всего проанализировать все случаи употребления функций работы со строками. Надо иметь в виду, что вы можете найти много мест, где функции вызываются безопасно, но наш опыт показывает, что ошибки могут скрываться даже в правильных вызовах. Коэффициент регрессии, характерный для модификации кода с целью перехода исключительно на безопасные функции, обычно очень мал (от одной десятой до одной сотой величины, типичной для исправления ошибки), зато это позволит устранить возможность некоторых видов эксплойтов.

Добиться этого можно, например, поручив выполнение задачи компилятору. Если вы исключите объявления функций strcpy, strcat, sprintf и им подобных из заголовочных файлов, то компилятор укажет все места в коде, где они встречаются. Но имейте в виду, что некоторые приложения полностью или частично переопределяют библиотеку времени исполнения для языка С.