有人在子类化Windows控件时可以解释此LinkDemand警告吗?

时间:2012-02-05 18:21:14

标签: 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 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 个答案:

答案 0 :(得分:22)

  

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

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

这个想法是程序集提供证据 - 诸如它们所在的位置,编写它们的人等等。 策略使用证据并生成与该程序集关联的权限 grant set

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

需求说堆栈中的每个调用者都必须被授予所需的权限。这可以防止引诱攻击,从而使敌对的低信任代码调用良性高信任代码并“诱使”它代表它做一些危险的操作,以伤害用户。由于全部需求检查直接和间接呼叫者,因此引诱攻击被击败。

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

要求的问题是它们昂贵。你必须做一个完整的堆栈步行并查看每个人的权限集。如果操作很便宜 - 例如,调整位图中的像素 - 您不希望每次都完全满足需求,因为您将花费所有时间进行冗余安全检查。

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

显然这样便宜 - 每个调用者只检查一个程序集比每次调用的 查看堆栈中的每个程序集更便宜 - - 并且方式更危险

链接需求基本上是推卸责任。链接需求说“来电,通过我的链接需求检查,你可以从现在开始打电话给我。但是我现在关闭安全系统,因此现在负责确保您的呼叫者无法成功攻击用户,因为我将授予您在未经安全检查的情况下给我打电话的权利。“

您正在调用具有链接需求的方法。所以你面临的问题是:你愿意承担这个责任吗?你可以廉价地称这种方法。您是否愿意保证没有低信任的恶意调用者可以使用您在没有安全检查的情况下调用该方法来伤害用户的事实?

如果您不愿意或无法做出这种保证,那么就链接要求的许可发出您自己的要求;然后,这将要求所有呼叫者满足要求。或者,将负责人转移到您的来电者:向您的来电者发出链接要求并让他们完成工作。


(*)正如我喜欢指出的那样,调用堆栈实际上并没有告诉你谁给你打电话,它告诉你下一步控制的地方。由于那些通常是相同的东西,所以一切都很好。在“谁打电话给你?”的情况下,最终可能会出现这种情况。已经脱离了“你下一步去哪儿?”;在这些环境中,您必须非常小心地使用传统风格的代码访问安全性。较新的“沙盒”安全模型更适合这些场景。

答案 1 :(得分:5)

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就足够了。您可以放心地忽略此警告。