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

Chr*_*nte 5 .net c# security winforms

我有这个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);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

当我在我的项目上运行代码分析时,我收到此警告:

警告1 CA2122:Microsoft.Security:'HeaderlessTabControl.WndProc(ref Message)'调用具有LinkDemand的'Message.Msg.get()'.通过进行此调用,'Message.Msg.get()'间接暴露给用户代码.查看以下可能暴露出绕过安全保护的方法的调用堆栈: - >'HeaderlessTabControl.WndProc(ref Message)'
- >'HeaderlessTabControl.WndProc(ref Message)'

...以及与两个类似的警告Message.Msg.set()TabControl.WndProc().我知道我通过这样做暴露了一些代码.有人可以解释我可能在这里打开了哪些安全漏洞,以及可能的解决方法吗?

Eri*_*ert 22

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

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

这个想法是装配提供证据 - 例如它们所在的位置,编写它们的人等等.政策消耗的证据,并产生授予集权限与该组件相关联.

当需要特定权限的行为-比如,创建一个对话框,或访问打印机或写入文件-尝试,运行时发出要求该权限.需求检查目前"在栈上"的代码,以确定所有的代码称为直接或间接地在本代码.(*)

需求表明堆栈中的每个调用者都必须获得所需的权限. 这可以防止引诱攻击,即恶意的低信任代码调用良性高信任代码并"诱使"它代表它进行一些危险的操作,从而伤害用户.由于全部需求检查直接和间接呼叫者,因此引诱攻击被击败.

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

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

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

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

链接需求基本上是推卸责任.链接需求说"来电,通过我的链接需求检查,你可以从现在开始打电话给我.但我现在关闭安全系统,因此现在负责确保你的来电者不能成功攻击用户利用这样一个事实,即我将授予你在没有安全检查的情况下给我打电话的权利."

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

如果您不愿意或无法做出这种保证,那么就发出自己对链接要求许可的要求; 然后,这将要求所有呼叫者满足要求.或者,推卸责任给您的来电者:发出链接请求,以您的来电者,让他们做的工作.


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


Han*_*ant 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...
    }
Run Code Online (Sandbox Code Playgroud)

继承需求就足够了.您可以放心地忽略此警告.

  • 是的,这就是你想要做的就是停止抱怨.有点破坏了原始代码的优雅,不是吗?拥有代码,不要让工具拥有你. (3认同)