Избегайте состояния гонки при утверждении прав доступа к файлам в Python

StackOverflow https://stackoverflow.com/questions/2258257

Вопрос

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

Немного подумав, вы понимаете, что этот исходный код имеет состояние гонки, которое делает схему безопасности неэффективной:

import os

class ExecutionError (Exception):
    pass

def execute_file(filepath):
    """Execute serialized command inside @filepath

    The file must be executable (comparable to a shell script)
    >>> execute_file(__file__)  # doctest: +ELLIPSIS
    Traceback (most recent call last):
        ...
    ExecutionError: ... (not executable)
    """
    if not os.path.exists(filepath):
        raise IOError('"%s" does not exist' % (filepath, ))
    if not os.access(filepath, os.X_OK):
        raise ExecutionError('No permission to run "%s" (not executable)' %
                filepath)

    data = open(filepath).read()

    print '"Dummy execute"'
    print data

Условие гонки существует между

os.access(filepath, os.X_OK)

и

data = open(filepath).read()

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

Первое решение, которое у меня есть, - это изменить порядок критических вызовов (и пропустить теперь избыточную проверку существования):

fobj = open(filepath, "rb")
if not os.access(filepath, os.X_OK):
    raise ExecutionError('No permission to run "%s" (not executable)' %
            filepath)

data = fobj.read()

Решает ли это проблему гонки?Как я могу решить это правильно?

Краткое обоснование схемы безопасности (как мне показалось)

Файл сможет выполнять произвольные команды внутри своей среды , поэтому он сравним со сценарием оболочки.

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

Это было решено, потребовав, чтобы файлы .desktop имели исполняемый бит set, в противном случае они не будут отображаться с именем / значком, и бесплатный рабочий стол спросит пользователя, хочет ли он запустить программу перед началом работы.

Сравните это с очень хорошим дизайном Mac OS X:"Эта программа была загружена из Интернета, вы уверены, что хотите ее открыть?".

Итак, в аллегории с этим и с тем фактом, что вы должны chmod +x оболочка скрипты, которые вы загружаете, я думал о дизайне в вопросе выше.

Заключительные слова

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

Это было полезно?

Решение

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

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

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

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

Другие советы

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

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

Кстати, мне не ясно, как эта схема, даже если бы ее можно было заставить работать, на самом деле добавила бы какой-либо безопасности - конечно, если плохие парни могут поместить отравленный контент в файл, это не выходит за их рамки chmod +x это тоже?

Лучшее, что вы можете сделать, это :

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

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

Вы должны изменить владельца файла таким образом, чтобы злоумышленник не мог получить к нему доступ "chown root:root file_name".Введите "chmod 700 file_name", чтобы никакие другие учетные записи не могли прочитать / записать / выполнить файл.Это позволяет избежать проблемы с TOCTOU в целом, и именно так люди предотвращают изменение файлов злоумышленником, у которого есть учетная запись пользователя в вашей системе.

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

Конечно, это очень тяжелый процесс.

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top