Может кто-нибудь объяснить это предупреждение LinkDemand при создании подкласса элемента управления Windows? - PullRequest
6 голосов
/ 05 февраля 2012

У меня есть этот HeaderlessTabControl, который подклассирует классический TabControl.

// From http://social.msdn.microsoft.com/forums/en-US/winforms/thread/c290832f-3b84-4200-aa4a-7a5dc4b8b5bb/
// Author: Hans Passant (nobugz)
public class HeaderlessTabControl : TabControl {
    protected override void WndProc(ref Message m) {
        // Hide tabs by trapping the TCM_ADJUSTRECT message
        if (m.Msg == 0x1328 && !DesignMode) {
            m.Result = (IntPtr)1;
        } else {
            base.WndProc(ref m);
        }
    }
}

Когда я запускаю Анализ кода в моем проекте, я получаю это предупреждение:

Предупреждение 1 CA2122:Microsoft.Security: «HeaderlessTabControl.WndProc (ref Message)» вызывает функцию «Message.Msg.get ()», которая имеет LinkDemand.При этом вызове Message.Msg.get () косвенно подвергается воздействию пользовательского кода.Просмотрите следующий стек вызовов, который может предоставить способ обойти защиту: -> 'HeaderlessTabControl.WndProc (ref Message)'
-> 'HeaderlessTabControl.WndProc (ref Message)'

.... а также два аналогичных предупреждения, касающихся Message.Msg.set() и TabControl.WndProc().Я понимаю, что выставил некоторый код, делая это.Может кто-нибудь объяснить, какие дыры в безопасности я мог здесь открыть, и возможные способы их устранения?

Ответы [ 2 ]

22 голосов
/ 05 февраля 2012

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

Позвольте мне дать вам пятиминутный обзор «традиционной» безопасности доступа к коду .NET. (У нас есть более новая, упрощенная модель безопасности, которая должна использоваться для нового кода, но полезно понимание базовой модели безопасности.)

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

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

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

assert позволяет коду с высоким уровнем доверия изменять семантику запроса. Утверждающий говорит: «Я добросовестный код с высоким уровнем доверия, и я утверждаю, что враждебный абонент с низким уровнем доверия не может заманить меня в выполнение опасной операции от его имени». Утверждение обычно сопряжено с более слабым спросом; то есть код с высоким уровнем доверия утверждает, что «я могу безопасно вызывать неуправляемый код, даже если вызывающий не может», а затем требует «но вызывающему лучше иметь разрешение на доступ к принтеру, потому что это то, что я собираюсь делать с моим неуправляемым Код разрешения ".

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

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

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

Спрос на ссылку в основном обходной. Требование ссылки говорит: «Вызывающий, пройдя мою проверку спроса на ссылку, вы теперь можете звонить мне по дешевке. Но Я отключаю систему безопасности сейчас , и, следовательно, you теперь мы несем ответственность за то, чтобы ваш абонент не мог успешно атаковать пользователя, воспользовавшись тем, что я предоставляю вам право звонить мне без проверки безопасности в будущем. "

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

Если вы не хотите или не можете предоставить такую ​​гарантию, выдаст ваше собственное требование на разрешение по ссылке;это потребует от всех ваших абонентов соответствия требованиям.Или передайте вашему абоненту: запросите ссылку на вашего абонента и заставьте них выполнить работу.


(*) Как я хотел бы отметить, стек вызовов на самом деле не говорит вам , кто вам звонил , он говорит вам , куда пойдет управление .Так как это обычно одно и то же, все работает отлично.Возможно оказаться в ситуации, когда "кто тебя звал?"развелась с "куда ты идешь дальше?";в этих средах вы должны быть очень осторожны, используя безопасность доступа к коду в традиционном стиле.Более новая модель безопасности в «песочнице» лучше подходит для таких сценариев.

5 голосов
/ 06 февраля 2012

FxCop может быть немного переусердствован своими предупреждениями. Это, безусловно, имеет место, этот код всегда будет соответствовать требованию CAS, потому что он вызывает base.WndProc (). Что в конечном итоге вызывает Control.WndProc (), который выглядит следующим образом:

    [SecurityPermission(SecurityAction.InheritanceDemand, Flags=SecurityPermissionFlag.UnmanagedCode)]
    [SecurityPermission(SecurityAction.LinkDemand, Flags=SecurityPermissionFlag.UnmanagedCode)]
    protected virtual void WndProc(ref Message m) {
        // etc...
    }

InheritanceDemand достаточно. Вы можете спокойно проигнорировать это предупреждение.

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