19 смертных грехов, угрожающих безопасности программ
Шрифт:
Еще один родственный грех – пренебрежение принципом наименьших привилегий. Если процесс работает от имени root или LocalSystem, то даже самый лучший механизм управления доступом не защитит операционную систему от ваших ошибок – приложению разрешено все, никакой контроль его не остановит.
Где искать ошибку
Чтобы обнаружить ошибки управления доступом, ищите в коде места, где:
□ устанавливаются элементы управления доступом;
□ разрешение на запись дается низко привилегированным пользователям; или
□ создается объект, без явного
□ этот объект создается в месте, к которому имеют разрешение на запись низкопривилегированные пользователи;
или
□ конфигурационные данные записываются в разделяемую область памяти; или
□ секретная информация сохраняется в области, которую разрешено читать низкопривилегированным пользователям.
Чтобы найти грех «зашивания», проанализируйте те места программы, где производится шифрование или создаются исходящие аутентифицированные соединения, и определите, откуда берется пароль или ключ. Если он «зашит» в код, имеет место ошибка, которую необходимо исправить (см. следующий раздел).
Выявление ошибки на этапе анализа кода
С точки зрения управления доступом все довольно просто: ищите места, где задаются права на доступ к объекту. Тщательно анализируйте те участки кода, где устанавливаются элементы управления доступом или разрешения. Далее проверьте те места, где создаются файлы или другие объекты без явного задания прав доступа к ним. Спросите себя, достаточно ли устанавливаемых по умолчанию прав с учетом места, где создается объект, и уровня секретности информации.
В поисках греха «зашивания» автор этой главы любит искать некоторые ключевые слова, позволяющие заподозрить код в греховности. Вот эти слова:
□ Secret;
□ Private (разумеется, вы получите много ложных срабатываний от закрытых членов класса);
□ Password;
□ Pwd;
□ Key;
□ Passphrase;
□ Crypt;
□ Cipher и cypher (так тоже пишут!).
Обнаружив любое из этих слов, посмотрите, не связаны ли с ним какие–то «зашитые» в код секретные данные.Тестирование
Инсталлируйте приложение и проверьте, какие элементы управления доступом заданы для созданных объектов. А еще лучше подключиться к функциям, которые создают объекты, и запротоколировать задаваемые права (если приложение предоставляет такую возможность). Тем самым вы сможете увидеть несохраняемые объекты, например временные файлы, события и участки разделяемой памяти.
Что касается «зашитых» секретов, то проще всего проанализировать двоичный файл с помощью, например, такого инструмента, как strings (www.sysinternals.com/ ntw2k/source/misc.shtml#strings). Эта программа выводит все текстовые строки, встречающиеся в приложении, и смотрит, нет ли среди них чего–то похожего на пароль или набор случайных символов (быть может, это ключ?).
На рис. 12.1 приведен результат работы для небольшого двоичного файла. Взгляните на строку под Welcome to the Foo application. Похоже на неудачную попытку скрыть пароль или ключ!
Рис. 12.1 .
Для приложений, написанных на .NET–совместимом языке, например VB.NET, ]# или С#, можете воспользоваться программой ildasm.exe, поставляемой в составе .NET Framework SDK. Она позволяет выполнить тщательный анализ кода. Если вызвать ее, как показано ниже, то она выведет все строки. Посмотрите, нет ли среди встроенных паролей.
ildasm /adv /metadata /text myapp.exe | findstr ldstr
На рис. 12.2 непристойное проявление греха бросается в глаза!
Вторая строка очень напоминает случайный ключ, но это еще не все. В третьей строке мы видим строку соединения с SQL Server от имени пользователя sa, содержащую встроенный пароль. Но и этим дело не заканчивается. Последняя строка – это, скорее всего, часть SQL–запроса, который во время исполнения будет с чем–то конкатенирован. Возможно, вы нашли приложение, в которое не только «зашита» секретная информация, но еще и подверженное греху 4 – внедрению SQL–команд.
Рис. 12.2. Отыскание «зашитых» секретов в .NET–приложениях
Еще один инструмент, полезный для анализа .NET–приложений, – это программа Reflector Лутца Редера (Lutz Roeder), которую можно загрузить со страницы www.aisto.com/roeder/dotnet.
Наконец, для Java можно воспользоваться дизассемблером dis (www.es. princeton.edu/~benjasik/dis). На рис. 12.3 показан пример его работы для Linux.
Как и в примере .NET–приложения, мы видим некоторые интересные данные. Константа в строке #15 – это, очевидно, строка соединения с базой данных, а в строках 17 и 19 мы, по–видимому, имеем имя и пароль пользователя.
Рис. 12.3. Отыскание «зашитых» секретов в программах на языке Java
Наконец, в строке 21 находится SQL–запрос, который будет конкатенирован с какой–то строкой во время выполнения. Похоже, что эксплойт для этой программы будет иметь катастрофические последствия. Взгляните на SQL–запрос, он же извлекает информацию о кредитных карточках! Еще один популярный дизассемблер для Java называется Jad, для него существует графический интерфейс под названием FrontEndPlus.
Примеры из реальной жизни
Следующие примеры взяты из базы данных CVE .
CVE–2000–0100
Цитата из бюллетеня CVE: «Программа SMS Remote Control устанавливается с небезопасными правами, позволяющими локальному пользователю расширить свои привилегии путем модификации или замены исполняемого файла».
Исполняемая программа, которую запускает сервис Short Message Service (SMS) Remote Control, помещается в каталог, право на запись в который есть у любого локального пользователя. Если дистанционное управление разрешено, то любой пользователь может запустить произвольную программу от имени учетной записи LocalSystem. (См. www.microsoft.com/technet/security/Bulletin/MSOO–012.mspx.)