Безопасность в Silverlight 2 - Прозрачность в CoreCLR

ОГЛАВЛЕНИЕ


Прозрачность в CoreCLR

Несмотря на то, что механизм прозрачности помогает оценить степень безопасности сборки, он не является единственным средством обеспечения безопасности в .NET Framework. У разных областей приложений могут быть разные «песочницы» с разными наборами прав — загруженная из Интернета программа не должна иметь такие же полномочия, как и приложение из корпоративной интрасети. Таким образом, в коде необходимо проверять и подтверждать разрешения.

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

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

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

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

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

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

Раньше я отмечал, что ключевой API, помеченный как TreatAsSafe, может быть вызван из прозрачного кода. Я также отмечал, что поскольку в инфраструктуре настольных систем прозрачность применяется только в пределах сборки, всему общедоступному ключевому неявно назначен атрибут TreatAsSafe. В CoreCLR создан новый атрибут, SafeCritical (который по-настоящему называется SecuritySafeCritical), для описания ключевого кода, который можно вызывать из прозрачного. Модель прозрачности не только внутри, но и между сборками, в результате чего любой ключевой код не может быть вызван из прозрачного кода.

С помощью атрибута SafeCritical можно решить задачу видимости ключевого кода из прозрачного. Во-первых, весь ключевой код ограничен — для общедоступного кода исключений нет, так что объявление кода ключевым означает, что его нельзя вызвать из прозрачного кода. Кроме того, атрибут TreatAsSafe имеет смысл только в том случае, если атрибут «Critical» уже установлен — требование двух атрибутов сразу может весть к ошибкам, потому что присвоить атрибут TreatAsSafe можно прозрачному методу, хотя этот атрибут и не будет ни на что влиять. Наконец, имея только одним способ задать уровень безопасности, наличие ключевого кода еще больше упрощает модель.

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