Переполнение буфера является большим. По умолчанию в C ничего не проверяется по диапазону, поэтому очень просто перезаписать буфер. Существует стандартная библиотечная функция, gets()
которую нельзя остановить от переполнения буфера, и ее почти никогда не следует использовать.
Существуют некоторые методы уровня реализации, препятствующие эксплуатации, такие как скремблирование блоков кучи, но это не остановит переполнения буфера в локальных буферах, что часто может делать интересные вещи, такие как изменение адреса, к которому будет возвращаться функция.
В Си нет хорошего общего решения. Многие библиотечные функции имеют версии, которые будут ограничивать объем, который они будут писать. хотя подсчитывать это может быть неуклюже. Есть программное обеспечение, которое может обнаружить переполнение буфера динамической памяти в тесте, если выполняется соответствующий тест, и переполнение стека часто будет отображаться как сбой в тестировании. Помимо этого, это вопрос тщательного кодирования и проверки кода.
С этим связана проблема записи в буфер, слишком маленький на один символ, забывая, что строка 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
.
Не забывайте, что символьная константа в C на самом деле является int
. Написание чего-то подобного char c; while((c = getchar()) != EOF) ...
может легко потерпеть неудачу, так EOF
как не будет представимо в char
.
Я могу придумать гораздо больше характерных ошибок С, но они могут вызвать проблемы с безопасностью.