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