Условия состязания и безопасные операции файла

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

Предотвращение условий состязания

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

OS X, как все современные операционные системы, является многозадачный OS; т.е. это позволяет многократным процессам работать или, казаться, работать одновременно путем быстрого переключения среди них на каждом процессоре. Преимущества для пользователя - многие и главным образом очевидный; недостаток, однако, то, что нет никакой гарантии, что две последовательных операции в данном процессе выполняются без любых других операций выполнения процесса между ними. Фактически, когда два процесса используют тот же ресурс (такой как тот же файл), нет никакой гарантии, что они получат доступ к тому ресурсу в любом определенном порядке, если оба процесса явно не предпримут шаги для обеспечения его.

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

Существует два основных типа состояния состязания, которое может быть использовано: время разового проверкой из использования (TOCTOU) и сигнальная обработка.

Время проверки по сравнению со временем использования

Приложению довольно свойственно должно проверить некоторое условие прежде, чем предпринять действие. Например, это могло бы проверить, чтобы видеть, существует ли файл прежде, чем записать в него, или есть ли у пользователя права доступа для чтения файла прежде, чем открыть его для чтения. Поскольку существует разрыв времени между проверкой и использованием (даже при том, что это могла бы быть часть секунды), атакующий может иногда использовать тот разрыв для предпринятия атаки. Таким образом это упоминается как время времени проверки проблемы использования.

Временные файлы

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

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

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

Файл атакующего мог бы иметь различные права доступа, чем временный файл приложения, таким образом, атакующий может тогда считать содержание. Также у атакующего мог бы быть файл, уже открываются. Атакующий мог заменить файл жесткой ссылкой или символьной ссылкой на некоторый другой файл (или один принадлежавший атакующим или существующий системный файл). Например, атакующий мог заменить файл символьной ссылкой на файл системного пароля, так, чтобы после атаки, системные пароли были повреждены до такой степени, что никто, включая системного администратора, не может войти в систему.

Для реального примера, в уязвимости в сервере каталогов, сценарий сервера записал закрытые и открытые ключи во временные файлы, затем считайте те ключи и поместите их в базу данных. Поскольку временные файлы были в публично перезаписываемом каталоге, атакующий, возможно, создал состояние состязания путем замены собственными файлами атакующего (или жесткие ссылки или символьные ссылки на файлы атакующего), прежде чем ключи были перечитаны, таким образом заставив сценарий вставить закрытые и открытые ключи атакующего вместо этого. После этого что-либо зашифровало или аутентифицировало использование тех ключей, будет находиться под контролем атакующего. Также атакующий, возможно, считал закрытые ключи, которые могут использоваться для дешифрования зашифрованных данных. [CVE-2005-2519]

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

Для узнавания больше о создании временных файлов надежно читайте, Создают Временные Файлы Правильно.

Межпроцессное взаимодействие

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

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

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

  1. Серверный процесс A получает запрос от логического элемента A.

  2. Серверный процесс B получает запрос от логического элемента B.

  3. Серверный процесс чтения число 1000 от базы данных.

  4. Серверный процесс B читает число 1000 от базы данных.

  5. Серверный процесс инкременты количество логического элемента 1 так, чтобы Gate == 1001.

  6. Серверный процесс B постепенно увеличивает количество логического элемента 1 так, чтобы Gate == 1001.

  7. Серверный процесс записи 1001 как новое количество логического элемента.

  8. Серверный процесс B записи 1001 как новое количество логического элемента.

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

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

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

Решение условий состязания, включающих совместно используемые данные, состоит в том, чтобы использовать механизм блокировки, чтобы препятствовать тому, чтобы один процесс заменил, пока другой не закончен с ним. Существуют проблемы и опасности, связанные с такими механизмами, однако, и они должны быть реализованы тщательно. И, конечно, блокировка механизмов только применяется к процессам, участвующим в схеме блокировки. Они не могут препятствовать тому, чтобы ненадежное приложение изменило данные злонамеренно. Для полного обсуждения посмотрите Уилера, Безопасное Программирование для Linux и Unix HOWTO, в http://www .dwheeler.com/secure-programs/.

Время времени проверки уязвимостей использования может быть предотвращено по-разному, завися в основном от домена проблемы. При работе с совместно используемыми данными необходимо использовать блокировку для защиты тех данных от других экземпляров кода. При работе с данными в публично перезаписываемых каталогах необходимо также принять меры предосторожности, описанные в Файлах в Публично Перезаписываемых Каталогах, Опасны.

Сигнальная обработка

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

Обеспечение сигнальных обработчиков

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

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

Например, в 1997, об уязвимости сообщили во многих реализациях протокола FTP, в котором пользователь мог вызвать состояние состязания путем закрытия соединения FTP. Закрытие соединения привело к почти одновременной передаче двух сигналов к Ftp-серверу: один для прерывания текущей работы, и один, чтобы выйти из системы пользователь. Когда сигнал выхода из системы поступил как раз перед сигналом аварийного прекращения работы, состояние состязания произошло.

Когда пользователь вошел в систему Ftp-сервер как анонимный пользователь, сервер временно понизит свои полномочия от корня ни до кого так, чтобы у зарегистрированного пользователя не было полномочий записать файлы. Когда пользователь вышел из системы, однако, сервер повторно принял полномочия пользователя root. Если бы сигнал аварийного прекращения работы достиг только правильного времени, то он прервал бы процедуру выхода из системы после того, как сервер принял полномочия пользователя root, но прежде чем он вышел из системы пользователь. Пользователь тогда был бы зарегистрирован с полномочиями пользователя root и мог продолжиться для записи файлов по желанию. Атакующий мог использовать эту уязвимость с графическим клиентом FTP просто путем повторного нажимания кнопки «Cancel». [CVE-1999-0035]

Для краткого введения для сигнализации обработчиков обратитесь на сайт Little Unix Programmers Group в http://users .actcom.co.il/~choo/lupg/tutorials/signals/signals-programming.html. Для дискурса о том, как сигнальные условия состязания обработчика могут быть использованы, см. статью Михала Залевского в http://www .bindview.com/Services/razor/Papers/2001/signals.cfm.

Обеспечение операций файла

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

В этом разделе рассматриваются то, что необходимо сделать для создания операций файла более безопасными.

Проверьте коды результата

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

Некоторые частые ошибки упоминаются ниже.

При записи в файлы или изменении полномочий файла

Отказ, когда полномочия изменения на файле или открыть файл для записи могут быть вызваны многими вещами, включая:

  • Недостаточные полномочия на файле или каталог включения.

  • Неизменный флаг (набор с chflags утилита или chflags системный вызов).

  • Сетевой том, становящийся недоступным.

  • Отключаемый внешний диск.

  • Сбой диска.

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

См. страницы руководства для chflags, chown, и chgrp команды и chflags и chown функции для получения дополнительной информации.

При удалении файлов

Несмотря на то, что rm если Вы передаете, команда может часто игнорировать полномочия -f флаг, это может все еще перестать работать.

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

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

Не упустите жесткие ссылки

Жесткая ссылка является вторым именем для файла — файл, кажется, находится в двух различных расположениях с двумя различными именами.

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

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

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

Не упустите символьные ссылки

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

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

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

В целом необходимо избежать функций, такой как chown и stat, это идет по символьным ссылкам (см. Таблицу 4-1 для альтернатив). Как с жесткими ссылками, Ваша программа должна оценить, приемлема ли символьная ссылка, и в противном случае должна обработать ситуацию корректно.

Нечувствительные к регистру файловые системы могут мешать Вашей модели обеспечения безопасности

В OS X любой раздел (включая загрузочный том) может быть или чувствительным к регистру, нечувствительным к регистру, но сохранить случай, или, для незагрузочных томов, может быть нечувствительным к регистру. Например, HFS + может быть или чувствительным к регистру или нечувствительным к регистру, но сохранить случай. FAT32 нечувствителен к регистру, но сохраняет случай. FAT12, FAT16 и ISO 9660 (без расширений) нечувствительны к регистру.

Приложение, не знающее о различиях в поведении между этими форматами объема, может вызвать серьезные дыры в системе безопасности, если Вы не осторожны. В частности:

  • Если Ваша программа использует свою собственную модель разрешения, чтобы обеспечить или запретить доступа (например, веб-сервер, предоставляющий доступ только к файлам в определенном каталоге), необходимо или осуществить это с a chroot тюрьма или быть бдительным в отношении обеспечения, чтобы Вы правильно идентифицировали пути даже в нечувствительном к регистру мире.

    Среди прочего это означает, что необходимо идеально использовать схему белого списка, а не схему помещения в черный список (с поведением по умолчанию, которое быть «отклоняет»). Если это не возможно для правильности, необходимо сравнить каждую часть отдельного тракта с черным списком с помощью чувствительных к регистру или нечувствительных к регистру сравнений, в зависимости от того, на каком объеме файл находится.

    Например, если Ваша программа имеет черный список, препятствующий тому, чтобы пользователи загрузили или загрузили файл /etc/ssh_host_key, если Ваше программное обеспечение установлено на нечувствительном к регистру объеме, необходимо также отклонить кого-то, кто выполняет запрос для /etc/SSH_host_key, /ETC/SSH_HOST_KEY, или даже /ETC/ssh_host_key.

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

    Если кто-то создаст такой файл, то Ваше приложение покорно загрузит данные из неправильного файла. Если содержание того файла влияет на поведение Вашего приложения некоторым важным способом, это представляет вектор потенциальной атаки.

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

Создайте временные файлы правильно

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

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

Сделать это:

  • В приложении какао вызвать NSTemporaryDirectory.

  • На уровне POSIX вызвать confstr и передайте константу _CS_DARWIN_USER_TEMP_DIR как name параметр.

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

Уровень POSIX

Используйте mkstemp функция для создания временных файлов на уровне POSIX. mkstemp функционируйте гарантирует уникальное имя файла и возвращает дескриптор файла, таким образом разрешение Вас пропускает шаг проверки open функционируйте результат для ошибки, которая могла бы потребовать, чтобы Вы изменили имя файла и вызов open снова.

Если необходимо создать временный файл в общедоступном каталоге вручную, можно использовать open функция с O_CREAT и O_EXCL набор флагов, чтобы создать файл и получить дескриптор файла. O_EXCL отметьте заставляет эту функцию возвращать ошибку, если уже существует файл. Обязательно проверьте на ошибки перед продолжением.

После того, как Вы открыли файл и получили дескриптор файла, можно безопасно использовать функции, берущие дескрипторы файлов, такие как стандарт C функции write и read, столько, сколько Вы сохраняете файл открытым. См. страницы руководства для open(2), mkstemp(3), write(2), и read(2) для больше на этих функциях, и посмотрите Уилера, Безопасное Программирование для Linux и Unix HOWTO для преимуществ и недостатков к использованию этих функций.

Какао

Нет никаких методов Какао, создающих файл и возвращающих дескриптор файла. Однако можно вызвать стандарт C open функция из программы Objective C для получения дескриптора файла (см. Работу с Публично Перезаписываемыми Файлами Используя Вызовы POSIX). Или можно вызвать mkstemp функция, чтобы создать временный файл и получить дескриптор файла. Тогда можно использовать NSFileHandle метод initWithFileDescriptor: инициализировать дескриптор файла и другой NSFileHandle методы, чтобы безопасно записать в или читать из файла. Документация для NSFileHandle класс находится в Ссылке Платформы Основы.

Получить путь к расположению по умолчанию, чтобы хранить временные файлы (сохраненный в $TMPDIR переменная окружения), можно использовать NSTemporaryDirectory функция. Обратите внимание на то, что NSTemporaryDirectory может возвратиться /tmp при определенных обстоятельствах такой, как будто Вы соединяете на прееOS X v10.3 цель разработки. Поэтому, если Вы используете NSTemporaryDirectory, Вы любой должен быть уверен то использование /tmp подходит для Вашей работы или, в противном случае необходимо полагать, что ошибочный случай и создает более безопасный временный каталог, если это происходит.

changeFileAttributes:atPath: метод в NSFileManager класс подобен chmod или chown, в этом это берет путь к файлу, а не дескриптор файла. Если Вы работаете в общедоступном каталоге или корневом каталоге пользователя, Вы не должны использовать этот метод. Вместо этого вызовите fchown или fchmod функция (см. Таблицу 4-1). Можно вызвать NSFileHandle класс fileDescriptor метод для получения дескриптора файла файла в использовании NSFileHandle.

Кроме того, при работе с временными файлами, необходимо избежать writeToFile:atomically методы NSString и NSData. Они разработаны, чтобы минимизировать риск потери данных при записи в файл, но сделать так в пути, не рекомендующемся для использования в каталогах, которые перезаписываемы другими. Посмотрите Работу с Публично Перезаписываемыми Файлами Используя Какао для подробных данных.

Файлы в публично Перезаписываемых каталогах опасны

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

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

С этой целью необходимо всегда использовать подпрограммы, воздействующие на дескрипторы файлов, а не пути по мере возможности, так, чтобы можно было быть уверены, что Вы всегда имеете дело с тем же файлом. Чтобы сделать это, передайте O_CREAT и O_EXCL флаги к open системный вызов. Если файл уже существует, это создает файл, но перестало работать.

Перед созданием файла, однако, необходимо сначала установить маску создания файла процесса (umask). Маска создания файла является битовой маской, изменяющей полномочия по умолчанию всех новых файлов и каталоги, создаваемые Вашим процессом. Эта битовая маска обычно указывается в восьмеричной нотации, что означает, что это должно начаться с нуля (не 0x).

Например, если Вы устанавливаете маску создания файла в 022, любые новые файлы, создаваемые Вашим процессом, будут иметь rw-r--r-- полномочия, потому что кашируются биты полномочий записи. Точно так же любые новые каталоги будут иметь rw-r-xr-x полномочия.

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

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

Существует несколько способов установить маску создания файла:

В коде C:

В коде C можно установить маску создания файла глобально с помощью umask системный вызов.

Можно также передать маску создания файла open или mkdir системный вызов при создании файла или каталога.

Примечание: Для максимальной мобильности при записи C кода, необходимо всегда создавать маски с помощью констант режима файла, определенных в <sys/stat.h>.

Например:

umask(S_IRWXG|S_IRWXO);

В сценариях оболочки:

В сценариях оболочки Вы устанавливаете маску создания файла при помощи umask встроенная оболочка. Это документируется в страницы руководства для sh или csh.

Например:

umask 0077;

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

Для получения дополнительной информации о маске создания файла см. страницу руководства для umask и Вига и Макгроу, Создавая Безопасное программное обеспечение, Аддисона Уэсли, 2002. Для особенно ясного объяснения использования маски создания файла посмотрите http://web .archive.org/web/20090517063338/http://www.sun.com/bigadmin/content/submitted/umask_permissions.html?.

Перед чтением файла (но после открытия его), удостоверьтесь, что это имеет владельца и полномочия, которые Вы ожидаете (использование fstat). Будьте подготовлены перестать работать корректно (вместо того, чтобы зависнуть), если это не делает.

Вот некоторые инструкции, чтобы помочь Вам избежать времени времени проверки уязвимостей использования при работе с файлами в публично перезаписываемых каталогах. Для более детальных обсуждений, специально для кода C, посмотрите Вигу и Макгроу, Создав Безопасное программное обеспечение, Аддисона Уэсли, 2002, и Уилер, Безопасное Программирование для Linux и Unix HOWTO, доступный в http://www .dwheeler.com/secure-programs/.

  • Если вообще возможный, избегите создавать временные файлы в общем каталоге, такой как /tmp, или в каталогах принадлежит пользователю. Если у кого-либо еще есть доступ к Вашему временному файлу, они могут изменить его содержание, изменить его владение или режим, или заменить его жесткой или символьной ссылкой. Это намного более безопасно любому не, используют временный файл вообще (используйте некоторую другую форму межпроцессного взаимодействия), или сохраните временные файлы в каталоге, который Вы создаете и к которому только Ваш процесс (действующий как Ваш пользователь) имеет доступ.

  • Если Ваш файл должен быть в общем каталоге, дать ему уникальное (и случайным образом сгенерированный) имя файла (можно использовать функцию C mkstemp сделать это), и никогда не закрывают и вновь открывают файл. Если Вы закрываете такой файл, атакующий может потенциально найти его и заменить его перед повторным открытием его.

    Вот некоторые общедоступные каталоги, которые можно использовать:

    • ~/Library/Caches/TemporaryItems

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

    • /var/run

      Этот каталог используется для процесса ID (изодромные с предварением) файлы и другие системные файлы, необходимые только один раз на сеанс запуска. Этот каталог убран каждый раз, когда система запускает.

    • /var/db

      Этот каталог используется для баз данных, доступных для системных процессов.

    • /tmp

      Этот каталог используется для общего совместно используемого временного хранения. Это убрано каждый раз, когда система запускает.

    • /var/tmp

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

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

Следующие разделы дают некоторые дополнительные подсказки, как следовать за этими принципами, когда Вы используете код уровня POSIX C, Углерод и вызовы Какао.

Работа с публично Перезаписываемыми файлами Используя вызовы POSIX

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

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

  1. Вызовите open функционируйте и сохраните дескриптор файла. Передайте O_NOFOLLOW гарантировать, что это не идет по символьным ссылкам.

  2. Используя дескриптор файла, вызовите fstat функция для получения stat структура для файла Вы просто открылись.

  3. Проверьте идентификатор пользователя (UID) и группа ID (GID) файла, чтобы удостовериться, что они корректны.

  4. Проверьте флаги режима файла, чтобы удостовериться, что это - нормальный файл, не FIFO, файл устройств или другой специальный файл. В частности, если называют структуру статистики st, тогда значение (st.st_mode & S_IFMT) должно быть равно S_IFREG.

  5. Проверьте чтение, запишите и выполните полномочия для файла, чтобы удостовериться, что они - то, что Вы ожидаете.

  6. Проверьте, что существует только одна жесткая ссылка на файл.

  7. Раздайте открытый дескриптор файла для более позднего использования вместо того, чтобы передать путь.

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

Таблица 4-1 показывает некоторые функции для предотвращения — и более безопасные эквивалентные функции для использования — во избежание условий состязания при создании файлов в общедоступном каталоге.

Табличный 4-1 C  файл функционирует, чтобы избежать и использовать

Функции для предотвращения

Функции для использования вместо этого

fopen возвращает указатель файла; автоматически создает файл, если он не существует, но не возвращает ошибки, если действительно существует файл

open возвращает дескриптор файла; если файл уже существует когда, создает файл и возвращает ошибку O_CREAT и O_EXCL опции используются

chmod берет путь к файлу

fchmod берет дескриптор файла

chown берет путь к файлу и идет по символьным ссылкам

fchown берет дескриптор файла и не идет по символьным ссылкам

stat берет путь к файлу и идет по символьным ссылкам

lstat берет путь к файлу, но не идет по символьным ссылкам;

fstat берет дескриптор файла и возвращает информацию об открытом файле

mktemp создает временный файл с уникальным именем и возвращает путь к файлу; необходимо открыть файл в другом вызове

mkstemp создает временный файл с уникальным именем, открывает его для чтения и записи, и возвращает дескриптор файла

Работа с публично Перезаписываемыми файлами Используя углерод

При использовании Файлового менеджера Углерода, чтобы создать и открыть файлы, необходимо знать как файлы доступов Файлового менеджера.

  • Спецификатор файла FSSpec структура использует путь для определения местоположения файлов, не дескриптора файла. Функции, использующие FSSpec спецификатор файла осуждается и не должен использоваться в любом случае.

  • Ссылка на файл FSRef структура использует путь для определения местоположения файлов и должна использоваться, только если файлы находятся в безопасном каталоге, не в публично доступном каталоге. Эти функции включают FSGetCatalogInfo, FSSetCatalogInfo, FSCreateFork, и другие.

  • Файловый менеджер создает и открывает файлы в отдельных операциях. Если файл уже существует, создать работа перестала работать. Однако ни одна из функций создания файла не возвращает дескриптор файла.

Если Вы получили ссылку на файл каталога (от FSFindFolder функция, например), можно использовать FSRefMakePath функция для получения пути каталога. Однако обязательно проверьте функциональный результат, потому что если FSFindFolder функционируйте сбои, это возвращает пустую строку. Если Вы не проверяете функциональный результат, Вы могли бы закончить тем, что пытались создать временный файл с путем, сформированным путем добавления имени файла к пустой строке.

Работа с публично Перезаписываемыми файлами Используя какао

NSString и NSData классы имеют writeToFile:atomically: методы, разработанные для минимизации риска потери данных при записи в файл. Эти методы пишут сначала во временный файл, и затем, когда они уверены, что запись успешна, они заменяют записанное - к файлу с временным файлом. Это - не всегда надлежащая вещь сделать при работе в общедоступном каталоге или корневом каталоге пользователя, потому что существует много находящихся на пути включенных операций файла. Вместо этого инициализируйте NSFileHandle объект с существующим дескриптором файла и использованием NSFileHandle методы для записи в файл, как упомянуто выше. Следующий код, например, использует mkstemp функция, чтобы создать временный файл и получить дескриптор файла, который это тогда использует для инициализации NSFileHandle:

fd = mkstemp(tmpfile); // check return for -1, which indicates an error
NSFileHandle *myhandle = [[NSFileHandle alloc] initWithFileDescriptor:fd];

Работа с публично Перезаписываемыми файлами в сценариях оболочки

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

Во-первых, при записи сценария, устанавливает временный каталог ($TMPDIR) переменная окружения к безопасному каталогу. Даже если Ваш сценарий непосредственно не создает временных файлов, один или больше подпрограмм, которые Вы вызываете, мог бы создать один, который может быть уязвимостью системы обеспечения безопасности, если он создается в небезопасном каталоге. См. страницы руководства для setenv и setenv для получения информации об изменении временной переменной окружения каталога. По той же причине, устанавливает маска создания кода файла Вашего процесса (umask) для ограничения доступа к любым файлам, которые могли бы быть созданы подпрограммами, выполненными сценарием (см. Операции Файла Обеспечения для получения дополнительной информации о umask).

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

Не перенаправляйте вывод с помощью операторов > или >> к публично перезаписываемому расположению. Эти операторы не проверяют, чтобы видеть, существует ли файл уже, и они идут по символьным ссылкам.

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

Не используйте test команда (или ее левая скобка ([) эквивалентный) для проверки на существование файла или другой информации о статусе для файла прежде, чем записать в него. Выполнение поэтому всегда приводит к состоянию состязания; т.е. для атакующего возможно создать, записать в, измениться или заменить файл, прежде чем Вы начнете писать. См. страницу руководства для test для получения дополнительной информации.

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

Другие подсказки

Вот несколько дополнительных вещей знать при работе с файлами:

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

  • Просто, потому что можно записать в файл, не означающий, что необходимо записать в него. Например, факт, что каталог существует, не означает создание его, и факт, что можно добавить к файлу, не означает владение файлом, или никто больше не может записать в него.

  • OS X может выполнить операции файла на файлах в нескольких различных файловых системах. Некоторые операции могут быть сделаны только в определенных системах. Например, определенная честь файловых систем setuid файлы, когда выполняется от них и некоторые не делают. Убедитесь, что Вы знаете, с какой файловой системой Вы работаете и какие операции могут быть выполнены в той системе.

  • Локальные пути могут указать на удаленные файлы. Например, путь /volumes/foo мог бы фактически быть чей-то Ftp-сервер, а не локально смонтированный объем. Просто, потому что Вы получаете доступ к чему-то путем, не гарантирующим, что это локально или что к этому нужно получить доступ.

  • Пользователь может смонтировать файловую систему где угодно, они имеют доступ для записи и владеют каталогом. Другими словами, почти где угодно пользователь может создать каталог, они могут смонтировать файловую систему поверх него. Поскольку это может быть сделано удаленно, атакующий, работающий, поскольку корень в удаленной системе мог смонтировать файловую систему в Ваш корневой каталог. Файлы в той файловой системе, казалось бы, были бы файлами в Вашем корневом каталоге, принадлежавшем корню. Например, /tmp/foo мог бы быть локальный каталог, или это могла бы быть корневая точка монтирования удаленно смонтированной файловой системы. Точно так же /tmp/foo/bar мог бы быть локальный файл, или он, возможно, был создан на другой машине и принадлежать корню там. Поэтому Вы не можете доверять файлам, базируемым только на владении, и Вы не можете предположить, что установка UID к 0 была сделана кем-то, кому Вы доверяете. Чтобы сказать, смонтирован ли файл локально, используйте fstat вызовите для проверки устройства ID. Если устройство, ID отличается от того из файлов, которые Вы знаете для локальной переменной, то Вы пересекли границу устройств.

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

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