Как предотвратить уязвимость выполнения произвольного кода в наших программах?

Вы всегда читаете в журналах изменений, когда ваша система, браузер или какая-либо программа обновляется, что в них исправлена ​​ошибка, которая позволила злоумышленнику выполнить любой код на вашем компьютере с помощью поддельного веб-сайта или атаковать ваш компьютер с помощью тщательно подделанных пакетов и т. Д.

Поскольку вы читаете это так часто, это означает, что любая программа может иметь похожие уязвимости ... Что вызывает это? как разработать наши программы, чтобы предотвратить подобные проблемы?


person Calmarius    schedule 02.04.2010    source источник


Ответы (4)


Один из примеров того, как ошибка может создать возможность для использования:

Допустим, у вас есть подпрограмма в программе, которая изменяет данные в массиве символов. Допустим, он также содержит ошибку, заключающуюся в том, что, когда массив имеет определенный размер или массив содержит определенные символы, подпрограмма непреднамеренно выполняет запись за концом массива символов.

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

В традиционном программировании (C, C ++) символьные массивы (буферы) часто хранятся в программном стеке. Стек - это очень быстрое и простое выделение памяти для небольших временных данных.

Еще одна вещь, которая хранится в стеке, - это адрес возврата вызова функции - адрес кода, на который нужно вернуться при выходе из этой функции.

Теперь у вас есть все необходимое для создания катастрофы: если вы можете передать только правильные данные в эту подпрограмму, чтобы она перезаписала стек, и перезаписать ее достаточно, чтобы перезаписать адрес возврата функции, который также находится в стеке недалеко от данных buffer, тогда у вас есть возможность изменить место, куда вернется выполнение программы после выхода из функции. Вместо того, чтобы возвращаться к вызывающему, его можно заставить «вернуться» (на самом деле, перейти) к Halt (), Format () или PhoneHome (). В этот момент доступна любая функция в любой библиотеке или DLL, на которую ссылается текущий процесс.

Это всего лишь один пример эксплойта произвольного выполнения. Таких выкроек десятки.

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

person dthorpe    schedule 02.04.2010

Первое и самое важное правило - никому не доверять.

  • Не доверяйте описанию данных пользователем (количество записей, длина массивов и т. Д.).
  • Не извергайте ничего, что дает вам клиент, не предварительно внимательно изучив это и не обезвредив (избегая непечатаемых символов, проверяя соответствие границам и типам структуры и т. Д.).
  • Всегда предполагайте, что когда вам предоставляют информацию, она будет повреждена. Строки не будут прерваны. Размер массивов будет неправильным. Структуры будут отсутствовать части. Пакеты будут негабаритными или неполными.

Ключ - «защитное программирование». Всегда проверяйте наиболее злонамеренный, искаженный способ получения ваших функций своими параметрами, а затем планируйте его решение. Никогда не предполагайте, что только потому, что вы написали код на другом конце, вы можете доверять его описанию того, что он вам передает. Это вдвойне верно для любого кода, который находится в руках конечного пользователя. Клиент находится в руках врага.

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

person Dan Story    schedule 02.04.2010

Существует книга The Shellcoder's Handbook: Discovering and Exploiting Security Holes, ISBN 978-0470080238 , который подробно описывает различные типы атак (переполнение стека, переполнение кучи, внедрение sql и т. д.).

person hlovdal    schedule 02.04.2010

Для решения этой проблемы есть хорошие источники "google", но, короче говоря, вам нужно сделать все ваши вызовы (вызовы функций, вызовы методов и т. Д.) Безопасными. Безопасный означает, что они усекают входящие данные до нужного размера, не оценивают их и т. Д.

Количество возможных атак очень велико. Вы можете прочитать Bugtraq, чтобы быть в курсе событий.

Надеюсь это поможет!

person Etamar Laron    schedule 02.04.2010