![]() |
Модераторы: Daevaorn |
![]() ![]() ![]() |
|
Thunderbolt |
|
||||||
![]() DevRel ![]() Профиль Группа: Участник Сообщений: 122 Регистрация: 7.11.2007 Где: Тула Репутация: 10 Всего: 16 |
В коде программ нет мест, где нельзя допустить ошибку. Ошибка может быть в самом простом месте. Если алгоритмы, механизмы обмена данными и интерфейсы люди привыкли тестировать, то с безопасностью всё обстоит гораздо хуже. Часто она реализуется по остаточному принципу. Программист думает, вот сейчас пару строк напишу, и всё будет хорошо. И даже тестировать не надо. Код слишком прост, чтобы допустить в нем ошибку! А вот и нет. Раз занимаетесь безопасностью и пишите какой-то код для этого, то тестируйте его не менее тщательно!
Где важна безопасность? Во многих приложениях. Но не будем рассуждать абстрактно. Давайте возьмём, например, исходные коды приложения Tor. Это свободное программное обеспечение для реализации второго поколения так называемой "луковой маршрутизации". Это система, позволяющая устанавливать анонимное сетевое соединение, защищённое от прослушивания. Подробнее что это такое и для чего используется, можно узнать, открыв статью в Википедии. Казалось бы, в таком приложении надо быть максимально внимательным к безопасности данных. И не просто внимательным! Скажем так, такое приложение стоит разрабатывать, только находясь в состоянии паранойи и мании преследования. И действительно, в программе TOR много чего делается, чтобы скрыть и защитить информацию. Но когда изучаешь код, то становится грустно. Из-за банальных ошибок и опечаток многие механизмы защиты просто непросто бездействуют. Одним из механизмов страховки является обнуление буферов, которые больше не используются. В таких буферах могут содержаться пароли, ip-адреса и другие пользовательские данные. Если эти данные не уничтожать, то они в виде мусора потом могут быть отправлены в интернет. И это не сказки, а реалии жизни. О том, как такое может произойти, можно почитать в статье "Перезаписывать память - зачем?". Разработчики TOR знают об этой опасности. И пытаются затирать содержимое буферов, используя функцию memset(). Это Epic Fail. Компилятор вправе убрать из кода вызов функции memset(), если заполняемый ею буфер более нигде не используется. Рассмотрим фрагмент кода, взятый из TOR:
Смотрите. На стеке создается буфер 'digest'. Далее он используется. Не важно, как. Главное что в конце мы хотим его обнулить. Для этого написан вызов функции memset(). Однако, после этого буфер 'digest' более в функции никак не используется. При оптимизации компилятор заметит это и удалит вызов функции. Это не изменит логику работы программы. Но это сделает её опасной с точки зрения приватности данных. Те, кого интересуют подробности, могут заглянуть сюда. Здесь приведён ассемблерный листинг, где показано как исчезает вызов функции memset(). В качестве компилятора используется Visual C++ 2010 и ключ "/O2". Чтобы гарантированно затереть память следует использовать такие функции, как RtlSecureZeroMemory(). Они специально созданы для таких случаев и не могут быть удалены компилятором. Вы скажете, что из мухи я делаю слона. И что никакие важные данные никуда не попадут. Возможно. Но кто даст гарантию? Раз разработчики сделали обнуление массива, то значит, они чего-то опасались. И делали они это не в одном, и не в двух местах. Много где. Жаль только, что усилия часто потрачены впустую. Чтобы не быть голословным, приведу список мест с ошибками. Список файлов и строк, где анализатор PVS-Studio выдал предупреждение "V597 The compiler could delete the 'memset' function call, which is used to flush '...' buffer. The RtlSecureZeroMemory() function should be used to erase the private data":
Я сознательно привел такой длинный список. Я хочу, чтобы вы осознали всю глубину проблемы отсутствия проверок кода, который должен позаботиться о безопасности. Кажется, ну как можно ошибиться, используя memset()!? Оказывается, ещё как можно. И это проблема не только TOR. Это вообще проблема многих приложений и библиотек. Далеко ходить не надо. Какие библиотеки использует TOR? Например, он использует OpenSSL. Это криптографический пакет с открытым исходным кодом для работы с SSL/TLS. Давайте посмотрим, как очищают память разработчики OpenSSL. Разработчики OpenSSL знают, что нельзя использовать memset() для обнуления буферов памяти. Поэтому, они написали свою функцию. Вот она:
Отличный параноидальный код. К нему претензий нет. Он затрет память. Причем не просто нулями, а случайными числами. Вот только из-за ошибок, эта функция не спасает, и приватные данные останутся на своём месте. Посмотрим вот на этот код:
Столько усилий было потрачено для написания функции OPENSSL_cleanse(). И всё мимо. Присмотритесь. Не замечаете ничего плохого? Выражения sizeof(buf) и sizeof(obuf) вычисляют размер указателя, а вовсе не размер буфера. В результате, в 32-битной программе в буфере будут затерты только первые 4 байта. Все остальные приватные данные стерты не будут. Можно найти в OpenSSL и другие идентичные ошибки (см. V597):
Выводы:
--------------------
Карпов Андрей, DevRel в PVS-Studio. |
||||||
|
|||||||
volatile |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 2107 Регистрация: 7.1.2011 Репутация: 37 Всего: 85 |
Thunderbolt, спасибо что продолжаете нас баловать интересными статьями.
Ща посмотрел на RtlSecureZeroMemory Единственно что она делает такого, чего не делает memset, это приводит указатель к (volatile*) Так что тем кто не в венде, (да и тем кто в ней) вероятно в таких случаях достаточно объявить (привести) указатель к (volatile type*) Ибо зачем юзать какой-то blackbox. т.е непонятную "волшебную" функцию, да еще с таки длинным и некрасивым назаванием ? =) А здесь, стандартные сишные средства, переносимость, кроссплатформенность, и т.д. и т.п. Вот код мелкомягких:
|
|||
|
||||
Thunderbolt |
|
||||
![]() DevRel ![]() Профиль Группа: Участник Сообщений: 122 Регистрация: 7.11.2007 Где: Тула Репутация: 10 Всего: 16 |
Я думаю лучше использовать RtlSecureZeroMemory() или иную функцию, которую предоставляют библиотеки для данного компилятора. Они созданы именно для этого. Создав самодельное, легко что-то не учесть. Кстати, вот ещё на эту тему и способах исправления кода: https://www.securecoding.cert.org/confluenc...64F87ACF13E0DE5 --------------------
Карпов Андрей, DevRel в PVS-Studio. |
||||
|
|||||
Alca |
|
|||
Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 3993 Регистрация: 14.6.2006 Репутация: 7 Всего: 50 |
развеселил ![]() ты бы еще туда strlen втюхал!! Это сообщение отредактировал(а) Alca - 8.11.2012, 15:19 |
|||
|
||||
bsa |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Модератор Сообщений: 9185 Регистрация: 6.4.2006 Где: Москва, Россия Репутация: 63 Всего: 196 |
Alca, ты к кому обращаешься? К разработчикам OpenSSL или к Thunderbolt. Если второе, то твой пост имеет смысл: "не читал, но осуждаю".
|
|||
|
||||
![]() ![]() ![]() |
Правила форума "С++:Общие вопросы" | |
|
Добро пожаловать!
Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Earnest Daevaorn |
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей) | |
0 Пользователей: | |
« Предыдущая тема | C/C++: Общие вопросы | Следующая тема » |
|
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности Powered by Invision Power Board(R) 1.3 © 2003 IPS, Inc. |