1) Ищите подпрограммы, которые не проверяют диапазоны или параметры ввода. Например: семья подпрограмм gets, позволяющая перезаписывать границы буферов (sprintf()?, gets () и т.д.). А также strcpy (), вмонтированная в большинство src: #define SCYPYN((a)(b)) strcpy(a, b, sizeof(a)) 2) SUID/SGID подпрограммы, написанные в одной из оболочек вместо C или PERL. 3) SUID/SGID подпрограммы, написанные в PERL и не использующие программу taintperl. 4) SUID/SGID подпрограммы, использующие system(), popen(), execlp() или execvp() при выполнении заданий. 5) Любая программа, которая использует относительные имена пути. 6) Использование относительных имен путей для определения динамически связанных библиотек. 7) Подпрограммы, не проверяющие ошибки в кодах возврата при системных вызовах. (Например: fork(2), suid(2), setuid() как в знаменитой ошибке rcp). 8) Дефекты часто могут быть обнаружены в коде, который: а) импортирован в новую среду; б) получил несанкционированный ввод; в) взаимодействует с другим локальным программным обеспечением; г) обращается к системным файлам, подобным passwd, L.sys и т.д.; д) считывает входные данные из свободно перезаписываемого файла/каталога; е) представляет собой одну из программ диагностики, которые чаще всего не позволяют пользователю защищать информацию. 9) Тестирование кода на предмет несанкционированного доступа. Средства для этого, включая различные утилиты, вполне доступны. 10) В man-страницах и в различных руководствах просмотрите параграфы с предупреждениями против выполнения того-то и изменения сего-то. Обратите внимание на разделы “Ошибки”. 11) Поищите редко используемые или необычные функции или команды — например, чтение в обратном направлении. В частности, интересные результаты может дать поиск не нашедших отражение в инструкциях флагов/аргументов. Проверьте флаги, работающие в более ранних выпусках вашей операционки или в других OS-версиях. Проверите опции, которые могут быть использованы другими программами. Например, telnet использует опцию -h для входа в систему... ладно, пропишите в login.c: if((getuid()) && hflag){ syslog() exit() } 12) Просмотрите условия маршрутизации. 13) Отключите часть софта, и тем самым вы проверите, действительно ли она, эта часть, связана с предполагаемым вами программным обеспечением или аппаратным модулем. 14) Отладьте процесс обнаружения ошибок так, чтобы он не отражался на системе безопасности. 15) Недостаточная отлаженность, приводящая, например, к созданию неверных условий проверки кодов. 16) Имплицитное доверие: подпрограмма B принимает параметры подпрограммы А, потому что подпрограмма А является системным процессом. 17) Память системы — это данные или ссылка на параметры пользователя в адресном пространстве пользователей. 18) Интерсвязь во время процессов: возвращение условий (passwd OK, illegal parameter, segment error и т.д.) может стать источником серьезных проблем, особенно вкупе с п.17. 19) Параметры пользователя не поддаются адекватной проверке. 20) Адреса, перекрывающие друг друга или обращающиеся к другим областям системы. 21) Пропуск проверки. 22) Сбой системы предупреждения о необычных параметрах. 23) Найдите уровни системы, в которых ряд модулей был написан различными программистами или группами программистов — обязательно обнаружатся “дырки”. 24) Регистраторы, указывающие на месторасположение значений параметра вместо того, чтобы передать это значение непосредственно. 25) Любая программа, функционирующая с системными привилегиями. (Слишком много программ имеют UID 0, что облегчает доступ кнекоторым таблицам и проч.) 26) Группа свободночитаемых временных файлов, буферов и т.д. 27) Неотлаженность пороговых значений и регистрации. 28) Изменение параметров особо важных областей системы до их выполнения одновременно запущенным процессом (условия маршрутизации). 29) Неадекватная проверка границы при компиляции, например, в случае, когда пользователь может запустить машинный код, оформленный как общие данные в области данных (если текстовая область и область данных разделены). 30) Неправильное прерывание пользователем работы компьютера. Большинство пользователей сначала или прерывают выполняемый процесс или доводят его до конца, а уже потом выключают компьютер, в то время как другие, не закончив корректно свою работу, оставляют систему фактически в незащищенном состоянии, оставляя открытыми файлы, в которых велась запись. 31) Код, использующий fopen(3) без установки umask. (Например: at(1) и др.) Вообще любой код, не перезапускающий UID перед началом параллельного действия. 32) Trace — ваш хороший помощник (или truss в SVR4). Он выясняет, какие системные вызовы используются программой. 33) Тщательно проверьте /usr/local. Многие администраторы устанавливают программное обеспечение из сети. Часто вы найдете здесь tcpdump, top, nfswatch... они запросто могут использовать корневой suid. 34) Проверьте программы под suid и убедитесь, что они являются именно теми самыми продуктами, которые были установлены сначала. Администраторы иногда меняют пароли, что менее безопасно, чем дистрибутивная версия. 35) Найти программы, устанавливающие программное обеспечение или загружаемые модули ядра. 36) Вообще динамически связанные программы. Вспомните LD_PRELOAD, думаем, что это еще не предел. 37) Программирование канала I/O — вот, что сейчас главное. Ищите логические ошибки, противоречия и удаления. 38) Если возможно, отследите в I/O программе наличие возможности самостоятельного модифицирования и запуска циклов (pre-load может помочь это осуществить это). 39) Если каналы I/O действуют как независимые процессоры, то они могут иметь неограниченный доступ к памяти, и таким образом системный код может быть изменяться в памяти еще до своего выполнения. 40) Найдите ошибки, существующие во многих частях программного обеспечения. К примеру, скажем, программа А может быть использована для изменения файла конфигурации /etc/a, программа В принимает эту информацию без проверки, и все это может привести кнепредвиденным результатам (только посмотрите, сколько программ доверяют /etc/utmp). 41) Любые программы, особенно допускающие выход из оболочки и идущие под suid/sgid.
|