Как предотвратить переполнение буфера
Возможность обнаружения уязвимостей переполнения буфера в исходном коде, безусловно, ценна. Однако устранение их из базы кода требует последовательного обнаружения, а также знакомства с безопасными методами обработки буферов. Самый простой способ предотвратить эти уязвимости - просто использовать язык, который их не допускает. Язык «C» допускает эти уязвимости благодаря прямому доступу к памяти и отсутствию строгой типизации объектов. Языки, которые не разделяют эти аспекты, обычно невосприимчивы. Java, Python и .NET, наряду с другими языками и платформами, не требуют специальных проверок или изменений для смягчения уязвимостей переполнения. Конечно, полностью изменить язык развития не всегда возможно. В этом случае используйте безопасные методы для обработки буферов. В случае функций обработки строк было много дискуссий о том, какие методы доступны, какие из них безопасны для использования, а каких следует избегать. Функции strcopy и strcat копируют строку в буфер и добавляют содержимое одного буфера в другой, соответственно. См. Рис.2. Эти двое демонстрируют небезопасное поведение, не проверяя никаких границ целевого буфера, и будут записывать за пределы буфера, если им будет предоставлено достаточно байтов для этого. Одной из часто предлагаемых альтернатив им являются связанные с ними strn-версии. Эти версии записывают только максимальный размер целевого буфера. На первый взгляд это кажется идеальным решением. К сожалению, есть небольшой нюанс с этими функциями, который все еще может вызвать проблемы. При достижении предела буфера, если завершающий символ не помещается в последний байт буфера, могут возникнуть серьезные проблемы при последующем чтении буфера:
Рис.
2. Функции strcopy и strcat, демонстрируют не
безопасное поведение.
В
этом упрощенном примере мы видим
опасность ненулевых строк. См. Таб. 3.
Когда “foo" помещается в normal_buffer, он
завершается null, потому что в буфере есть
дополнительное пространство. Это не
относится к full_buffer. Когда это
выполняется, результаты выглядят
следующим образом:
Рис.
3. Опасность ненулевых строк.
Значение в normal_buffer было напечатано правильно, но full_buffer напечатал дополнительный символ. Это своего рода наилучший сценарий развития событий. Если бы следующие байты в стеке были другим символьным буфером или другой печатаемой строкой, функция печати продолжала бы чтение до тех пор, пока не будет достигнут завершающий символ этой строки. Плохая новость заключается в том, что «C» не предоставляет стандартную, безопасную альтернативу этим функциям. Хорошей новостью является то, что существует несколько специфичных для платформы реализаций. OpenBSD предоставляет strlcpy и strlcat, которые работают аналогично strn- функции, за исключением того, что они усекают строку на один символ раньше, чтобы освободить место для нулевого Терминатора. Кроме того, Microsoft предоставляет свои собственные безопасные реализации часто используемых функций обработки строк: strcpy_s, strcat_s и sprintf_s. Ниже приведена таблица, содержащая более безопасные альтернативы наилучшим образом избегаемым функциям:
Таблица
1. Обработки строк, более безопасные
альтернативы.
Предпочтительнее использовать безопасные альтернативы, перечисленные выше. Когда это невозможно, необходимо выполнить ручную проверку границ и нулевое завершение при обработке строковых буферов.
