有人在子类化Windows控件时可以解释此LinkDemand警告吗?
我有这个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)’调用具有LinkDemand的’Message.Msg.get()’。 通过进行此调用,’Message.Msg.get()’间接地暴露给用户代码。 查看以下可能揭示绕过安全保护的方法的调用堆栈: – >’HeaderlessTabControl.WndProc(ref Message)’
– >’HeaderlessTabControl.WndProc(ref Message)’
…以及与Message.Msg.set()
和TabControl.WndProc()
相关的两个类似警告。 我知道我通过这样做暴露了一些代码。 有人可以解释一下我可能在这里打开了哪些安全漏洞,以及可能的解决方法吗?
我想我要问的是,我应该寻找哪些可能的安全漏洞?
让我给你五分钟的“传统”.NET代码访问安全性概述。 (我们有一个更新的,简化的安全模型,应该用于新代码,但了解底层安全模型是有帮助的。)
这个想法是程序集提供证据 – 比如它们所在的位置,编写它们的人等等。 策略使用 证据并生成与该程序集关联的授权 权限集。
当尝试需要特定权限的操作(例如,创建对话框或访问打印机或写入文件)时,运行时会发出对该权限的请求。 需求检查当前“在堆栈上”的代码,以确定直接或间接调用当前代码的所有代码。 (*)
需求表明堆栈中的每个调用者都必须获得所需的权限。 这可以防止引诱攻击 ,即恶意低信任代码调用良性高信任代码并“诱使”它代表它进行一些危险的操作,从而伤害用户。 由于全部需求检查直接和间接呼叫者,因此引诱攻击被击败。
断言允许高信任度代码修改需求语义。 一个断言说“我是良性高信任代码,我断言我不能被一个低信任的恶意调用者诱骗代表它执行危险的操作。” 断言通常与较弱的需求配对; 也就是说,高可信代码断言“我可以安全地调用非托管代码,即使调用者不能”,然后要求“但调用者最好有权访问打印机,因为这就是我要对我的非托管操作代码许可“。
需求的问题是它们很昂贵 。 你必须做一个完整的堆栈步行并查看每个人的权限集。 如果操作很便宜 – 例如,调整位图中的像素 – 您不希望每次都完全满足要求,因为您将花费所有时间进行冗余安全检查。
因此链接需求 。 每个调用者对受保护方法执行一次链接请求 , 第一次使用调用受保护方法的代码 ,并且它仅检查受保护方法的直接调用方 ,而不是执行完整堆栈遍历。 之后,执行链接所需的代码操作,而不对该调用者进行安全检查。 (它实际上应该被称为“jit demand”,而不是“链接需求”,因为使用的机制是在调用者被jitted时检查需求。 )
显然这样便宜 – 每个调用者只检查一个程序集比每次调用查看堆栈中的每个程序集一个检查更便宜 – 而且更危险 。
链接需求基本上是推卸责任。 链接需求说“来电,通过我的链接需求检查,你可以从现在开始打电话给我便宜。但我现在关闭安全系统 ,因此你现在负责确保你的来电者无法成功攻击用户利用这样一个事实,我将授予你将来没有安全检查给我打电话的权利。“
您正在调用具有链接需求的方法。 所以你面临的问题是: 你愿意承担这个责任吗? 你可以廉价地称这种方法。 您是否愿意保证 ,没有低信任的恶意调用者可以使用您在没有安全检查的情况下调用该方法来伤害用户的事实?
如果您不愿意或无法做出这种保证,那么就发出自己对链接要求许可的要求; 然后,这将要求所有呼叫者满足要求。 或者,将降压传递给调用者:向调用者发出链接请求并让他们完成工作。
(*)正如我喜欢指出的那样,调用堆栈实际上并没有告诉你谁给你打电话 ,它会告诉你下一步控制权在哪里 。 因为那些通常都是一样的,所以一切都很好。 在“谁打电话给你?”的情况下,最终可能会出现这种情况。 已经脱离了“你下一步去哪儿?”; 在这些环境中,您必须非常小心地使用传统风格的代码访问安全性。 较新的“沙盒”安全模型更适合这些场景。
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就足够了。 您可以放心地忽略此警告。