Осторожно - разделяемая память!

Разделяемая память (shared memory) - очень удобный и популярный механизм обмена данными между процессами. Простота использования и скорость - основные причины этой популярности. Простота использования играет роль, когда объем передаваемой информации мал. Например, описатель глобального хука (см. SetWindowsHookEx) обычно передаётся через секцию разделяемой памяти. Скорость важна, когда остальные методы межпроцессового взаимодействия слишком медленны, ненадежны либо вносят большую чем надо задержку. Хороший пример - микшер, смешивающий аудио потоки из разных приложений.

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

В Windows существует два способа создания разделяемой секции памяти. Программист может поместить часть глобальных переменных приложения в отдельную секцию данных и установить атрибут “shared” для неё. Для этого используются директива “#pragma section” или параметр командной строки сборщика “/SECTION”. В результате единственная копия помеченных переменных будут использоваться всеми процессами, загрузившими .exe или .dll. Второй способ предполагает использование функций CreateFileMapping, MapViewOfFileEx и прочих.

Оба способа уязвимы для атак, если разработчик не предусмотрел такую возможность и не принял меры заранее. В чём же проблема? Проблема с первым способом в том, что любое приложение, способное загрузить .exe или .dll, автоматически получает доступ к разделяемой секции и, таким образом, может повлиять на целевое приложение. Не следует думать, что такая уязвимость характерна только для разделяемых секций размещенных в .dll. Никто не мешает злоумышленнику загрузить .exe с помощью функции LoadLibrary и сделать свое грязное дело. Фактически доступ к секции контролируется ACL на исполняемом файле, содержащим разделяемую секцию. Учитывая, что все исполняемые файлы, как правило, доступны для чтения даже из под учётной записи гостя, такая разделяемая секция доступна на запись кому угодно.

Разделяемые секции, создаваемые с помощью CreateFileMapping, имеют собственный ACL. В этом плане, они несколько более надежны, чем первые. Однако и это не обеспечивает высокого уровня безопасности. Например, в случае глобального хука, все GUI приложения должны иметь доступ к его описателю. Иначе говоря, любое приложение, запущенное от имени интерактивного пользователя, будет иметь доступ к секции.

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

comments powered by Disqus