C# 当子类化Windows控件时,是否有人可以解释此LinkDemand警告?

C# 当子类化Windows控件时,是否有人可以解释此LinkDemand警告?,c#,.net,winforms,security,C#,.net,Winforms,Security,我有一个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 ove

我有一个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。安全性: “HeaderlessTabControl.WndProc(ref Message)”调用到 “Message.Msg.get()”具有LinkDemand。打这个电话,, “Message.Msg.get()”间接暴露于用户代码。回顾 下面的调用堆栈可能会暴露一种规避安全性的方法 保护:->'HeaderlessTabControl.WndProc(参考消息)'
->'HeaderlessTabControl.WndProc(参考消息)'

…以及与
Message.Msg.set()和
TabControl.WndProc()相关的两个类似警告。我知道我通过这样做暴露了一些代码。有人能解释一下我可能在这里打开了什么样的安全漏洞,以及可能的修复方法吗

我想我要问的是,我应该寻找哪些可能的安全漏洞

让我给您介绍一下“传统的.NET代码访问安全性”的五分钟概述。(我们有一个更新、简化的安全模型,应该用于新代码,但了解底层安全模型是有帮助的。)

其思想是程序集提供证据——比如它们的位置、编写者等等。策略使用证据并生成与该程序集关联的权限授予集

当试图执行需要特定权限的操作(例如,创建对话框、访问打印机或写入文件)时,运行时会发出对该权限的请求。需求检查当前“堆栈上”的代码,以确定直接或间接调用当前代码的所有代码。(*)

请求表示堆栈上的每个调用方都必须被授予所需的权限。这防止了诱骗攻击,即恶意低信任代码调用良性高信任代码,并“诱使”它为自己做一些危险的操作,从而伤害用户。由于全需求检查直接和间接呼叫者,因此引诱攻击被击败

断言允许高信任代码修改需求语义。断言表示“我是良性的高信任代码,我断言我不能被低信任恶意调用方引诱为其执行危险操作。”断言通常与较弱的需求配对;也就是说,高信任代码断言“即使调用者不能安全地调用非托管代码,我也可以安全地调用”,然后要求“但是调用者最好有访问打印机的权限,因为这就是我将使用非托管代码权限要做的”

需求的问题在于价格昂贵。您必须进行一次完整的堆栈遍历,并查看每个人的权限集。如果操作很便宜——比如,调整位图中的一个像素——你不希望每次都进行完整的请求,因为你会花费所有的时间进行冗余的安全检查

因此,链接需求增加。在第一次使用调用受保护方法的代码时,对受保护方法的每个调用方执行一次链接请求,它只检查受保护方法的直接调用方,而不是执行完整的堆栈遍历。之后,执行链接所需的代码操作时,不会对该调用方进行安全检查。(它实际上应该称为“jit需求”,而不是“链接需求”,因为所使用的机制是在调用方进行jit时检查需求。)

显然,这要便宜得多——每个调用只检查一个程序集的检查要比每个调用检查堆栈上的每个程序集的检查便宜得多——而且危险得多

链接需求基本上是推卸责任。链接需求说“来电者,通过我的链接需求检查,从现在起,你可以打电话给我,要求便宜。但我现在正在关闭安全系统,因此您现在有责任确保您的来电者不能利用我授予您在未来无需安全检查的情况下呼叫我的权利,成功攻击用户。”

您正在调用一个带有链接需求的方法。因此,您面临的问题是:您愿意承担这一责任吗?您可以廉价调用该方法。您愿意保证没有信任度低的恶意调用方可以利用您可以在没有安全检查的情况下调用该方法的事实来伤害用户吗

如果你不愿意或不能做出保证,那么就发出你自己对链接请求许可的请求;这将要求你的所有呼叫者满足要求。或者,把责任推给你的呼叫者:向你的呼叫者发出链接请求,让他们完成工作



(*)正如我喜欢指出的那样,调用堆栈实际上并没有告诉您是谁给您打电话,而是告诉您下一步控制的方向。因为这些通常都是同一件事,所以一切都很顺利。最终可能会出现“谁给您打电话?”与“您下一步要去哪里”脱节的情况?"; 在这些环境中,使用传统风格的代码访问安全性必须非常小心。较新的“沙盒”安全模型更适合这些场景。

FxCop的警告可能有点过火。这里的情况肯定是这样的,因为此代码调用base.WndProc(),所以它将始终满足CAS要求。最终调用Control.WndProc(),如下所示:

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

这种需求是足够的。您可以安全地忽略此警告。

如何修复此警告?消息告诉您需要在此处查找安全漏洞。你这样做了吗?你发现安全漏洞了吗?如果你找到了,那么修复漏洞。那么我想我要问的是,我应该寻找哪些可能的安全漏洞?你读过这里的信息了吗@乔:不,但我会的。谢谢你的链接。这是我的代码