Существует множество угроз безопасности, возникающих из-за тесного контакта с оборудованием, а не с использованием хорошо проверенных и проверенных API-интерфейсов из языков программирования высокого уровня. Гораздо проще вызвать переполнение буфера в C, чем в языке, таком как Java.
Каковы риски или уязвимости (например, переполнение буфера), о которых должен знать каждый программист C (уязвимости IE, относящиеся к программистам C)? К каким проблемам это может привести? Как их избежать и каковы распространенные ошибки, вызывающие их появление в программах?
Ответы:
Переполнение буфера является большим. По умолчанию в C ничего не проверяется по диапазону, поэтому очень просто перезаписать буфер. Существует стандартная библиотечная функция,
gets()
которую нельзя остановить от переполнения буфера, и ее почти никогда не следует использовать.Существуют некоторые методы уровня реализации, препятствующие эксплуатации, такие как скремблирование блоков кучи, но это не остановит переполнения буфера в локальных буферах, что часто может делать интересные вещи, такие как изменение адреса, к которому будет возвращаться функция.
В Си нет хорошего общего решения. Многие библиотечные функции имеют версии, которые будут ограничивать объем, который они будут писать. хотя подсчитывать это может быть неуклюже. Есть программное обеспечение, которое может обнаружить переполнение буфера динамической памяти в тесте, если выполняется соответствующий тест, и переполнение стека часто будет отображаться как сбой в тестировании. Помимо этого, это вопрос тщательного кодирования и проверки кода.
С этим связана проблема записи в буфер, слишком маленький на один символ, забывая, что строка C длиной n символов требует n + 1 символов в памяти из-за
'\0'
ограничителя. Если злоумышленнику удастся сохранить строку без терминатора, любая функция C, ожидающая строку, продолжит обработку до тех пор, пока не достигнет нулевого байта, что может привести к копированию или выводу большего количества информации, чем необходимо (или попаданию в защищенную память для атаки DOS). ). Решением, опять же, является осознание, забота и проверка кода.Есть еще один риск с
printf()
семьей. Если вы когда-либо пишетеchar * str; ... printf(str);
, вы настраиваете себя на проблемы, еслиstr
в распечатке содержится символ «%».%n
Директива формат позволяетprintf()
записать в память. Решениеprintf("%s", str);
илиputs(str);
. (Кроме того, используйте C99snprintf()
вместоsprintf()
.)Использование целых чисел без знака, особенно в качестве индексов цикла, может вызвать проблемы. Если вы назначите небольшое отрицательное значение без знака, вы получите большое положительное значение. Это может подорвать такие вещи, как обработка только N экземпляров чего-либо или ограниченные функции, например
strncpy()
. Изучите все целые числа без знака. Возможно, вы захотите избежатьunsigned short
, так как большое значение в одном из них преобразуется в большое положительное значение вint
.Не забывайте, что символьная константа в C на самом деле является
int
. Написание чего-то подобногоchar c; while((c = getchar()) != EOF) ...
может легко потерпеть неудачу, такEOF
как не будет представимо вchar
.Я могу придумать гораздо больше характерных ошибок С, но они могут вызвать проблемы с безопасностью.
источник
printf("%s", str)
для голой строки, когдаputs(str)
будет делать ту же работу.puts
добавляет символ новой строки, покаprintf
нет.fputs(str, stdout)
, чего нет.Некоторые из специфических для C рисков включают: переполнение буфера , форматирование строковых атак и целочисленные переполнения .
источник
Здесь легко упустить риск, который может вызвать проблемы, на решение которых потребуются часы.
Рассмотрим следующий код, который будет компилироваться без проблем.
Когда вы проверяете, если
lpstr_current_state
вCONST_EMERGENCY_STATE_HOLY_CRAP
самом деле вы назначая. Лучше всегда ставить постоянную переменную слева. Если вы поместите константу слева, то компилятор потерпит неудачу, потому что вы не можете присвоить значение переменной.Тогда вы можете легко сказать себе: «Черт возьми, это могло быть плохо», исправляя код для чтения ...
источник
=
и==
.Существует только одна угроза безопасности: тот факт, что снаружи есть люди, которые приложат все усилия, чтобы поймать любую уязвимость в вашем программном обеспечении и использовать ее в своих интересах. Все остальное следует оттуда.
Поэтому, когда вы думаете, что «никто в здравом уме не будет ...», вам нужно немедленно подумать «за исключением того, кто хочет взломать компьютеры других людей, сделает именно это».
Самым большим последствием является то, что всякий раз, когда вы реагируете на внешние события (например, путем обработки данных, доставляемых извне), вы должны предполагать, что эти данные находились под контролем вашего злейшего врага.
источник