有人能继承一个Windows控件时解释的LinkDemand警告?人能、控件、Windows、LinkDemand

2023-09-03 07:30:08 作者:花开亦不离

我有这个HeaderlessTabControl,其子类经典的TabControl。

  //从http://social.msdn.microsoft.com/forums/en-US/winforms/thread/c290832f-3b84-4200-aa4a-7a5dc4b8b5bb/
//作者:汉斯帕桑特(nobugz)
公共类HeaderlessTabControl:TabControl的{
    保护覆盖无效的WndProc(参考消息M){
        //隐藏标签通过捕获TCM_ADJUSTRECT消息
        如果(m.Msg == 0x1328和放大器;&安培;!的designMode){
            m.Result =(IntPtr的)1;
        } 其他 {
            base.WndProc(REF米);
        }
    }
}
 

当我运行我的项目code分析,我得到这样的警告:

  

警告1 CA2122:Microsoft.Security:   HeaderlessTabControl.WndProc(参考消息)'调用到   'Message.Msg.get()'具有的LinkDemand。通过这个电话,   Message.Msg.get()'是间接接触到用户的code。查看   可能暴露的方式来规避安全以下调用堆栈   保护: - >HeaderlessTabControl.WndProc(参考消息)    - >HeaderlessTabControl.WndProc(参考消息)

...以及有关 Message.Msg.set()两个类似的警告 TabControl.WndProc()。我明白,我做这暴露了一些code。有人能解释什么样的安全漏洞,我可能已经打开了这里,和可能的方式来解决这个问题?

解决方案   

我想什么,我问的是,什么可能的安全漏洞,我应该找谁?

让我给你的传统。NET code接入安全的5分钟概述。 (我们应当使用新的code较新的,简化的安全模型,但潜在的安全模型的理解是有帮助的。)

这个想法是的组装的提供的的证据的 - 比如它们的位置,谁写了他们,等等。 策略的消耗的的证据的,并产生的批设置的权限的与该集关联的。

win10中如何找windows控件

当需要特定权限的操作 - 例如,创建一个对话框或访问打印机或写入文件 - 尝试,在运行时发出的需求的该许可。需求检查code当前的堆栈,确定所有的code,它的名为的的present code,直接或间接的影响。 (*)

的需求说的在堆栈上的每个来电者必须已被授予所需的权限。的这prevents中的引诱攻击的,即敌意低信任code呼吁良性的高信任度code和诱惑它变成做一些危险动作代表其伤害用户。由于全部需求支票的的直接和间接来电的的引诱攻击,从而击败了。

这是断言的允许高度信任的code修改需求语义。断言说:我是良性的高度信任code和我断言,我不能用一个低信任恶意来电者诱骗到代表其执行一项危险的操作。断言通常搭配需求减弱;也就是说,高信任度的code声称我可以叫非托管code安全,即使调用者不能,然后要求,但来电者最好有权限访问打印机,因为这是我打算如何处理我的非托管code许可。

与需求的问题是,他们的价格昂贵的。你必须做一个完整的堆栈散步,看看每个人的权限集。如果操作很便宜 - 也就是说,在一个位图调整像素 - 你不希望每次都做了充分的需求,因为你会花所有的时间都在做重复的安全检查。

因此​​,链接要求的。链接要求进行的一次每个受保护的方法的,对调用者的首次code调用受保护方法是使用的,它只是检查的受保护的方法的直接调用方的,而不是做一个完整的堆栈步行路程。在此之后,链接要求code的操作与没有安全检查的为该呼叫者的执行。 (它真的应该被称为JIT需求,而不是链接要求,因为使用的机制是的的需求时,主叫方即时编译检查。的)

显然,这是方式更便宜 - 每个来电者的支票,只能看一个程序集的价格比一张支票的每次通话的自己看的的每个组件上的堆栈的 - - 和办法更危险的

链接的需求基本上是相互推诿。该链接请求说:来电,传递我的链接要求检查,你给我打电话便宜,从现在开始,但是的我现在转向安全系统关闭的,因此的您现在负责确保的您的来电的不能成功地攻击采取的事实,我给予你给我打电话,而不在未来的安全检查权优势的用户。

正在调用的链接需求的方法。所以,你所面临的问题是:您愿意承担这个责任您获得调用该方法便宜。你是否愿意为保障不低信任恶意调用者可以使用的事实,你要调用该方法,无需安全检查,以损害用户?

如果你是不是愿意或能够保证做到这一点,那么问题你自己的需求的的链接请求的权限;这将随后要求所有来电者符合要求。或者,推卸责任给的您的来电:发出链接请求来的您的来电,使的这些的做的工作

(*)作为我乐于指出的,调用栈实际上并没有告诉你的谁给你打电话的,它会告诉你的进行控制的地方去下一个的。由于这些都是的一般的同样的事情,一切工作顺利。它可以结束了在情况下谁给你打电话?已成为脱离你要去哪儿下?;在这些环境中,您可以选择使用传统风格的code访问安全性要非常小心。较新的沙箱安全模式更适合于那些场景。

I have this HeaderlessTabControl, which subclasses the classic 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);
        }
    }
}

When I run Code Analysis on my project, I get this warning:

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)'

...as well as two similar warnings relating to Message.Msg.set() and TabControl.WndProc(). I understand that I've exposed some code by doing this. Can someone explain what kind of security holes I might have opened up here, and possible ways to fix it?

解决方案

I guess what I am asking is, what possible security holes should I be looking for?

Let me give you the five minute overview of "traditional" .NET code access security. (We have a newer, simplified security model that should be used for new code, but an understanding of the underlying security model is helpful.)

The idea is that assemblies provide evidence -- things like where they are located, who wrote them, and so on. Policy consumes evidence and produces a grant set of permissions associated with that assembly.

When an action that requires a particular permission -- say, creating a dialog box or accessing a printer or writing to a file -- is attempted, the runtime issues a demand for that permission. The demand examines the code currently "on the stack" to determine all the code that called the present code, directly or indirectly. (*)

The demand says that every caller on the stack must have been granted the required permission. That prevents the luring attack, whereby hostile low-trust code calls benign high-trust code and "lures" it into doing some dangerous operation on its behalf, to harm the user. Since the full demand checks direct and indirect callers the luring attack is thereby defeated.

An assert allows high-trust code to modify the demand semantics. An assert says "I am benign high trust code and I assert that I cannot be lured by a low-trust hostile caller into performing a dangerous operation on its behalf." An assert is typically paired with a weaker demand; that is, high-trust code asserts "I can call unmanaged code safely even if the caller cannot", and then demands "but the caller had better have permission to access the printer, because that's what I'm going to do with my unmanaged code permission".

The problem with demands is that they are expensive. You have to do a full stack walk and look at everyone's permission set. If the operation is cheap -- say, tweaking a pixel in a bitmap -- you don't want to do a full demand every time because you'd spend all your time doing redundant security checks.

Thus the link demand. A link demand is performed once per caller of the protected method, the first time the code that calls the protected method is used, and it only checks the immediate caller of the protected method, rather than doing a full stack walk. After that, the link-demanded code operations are performed with no security checks for that caller. (It really should be called a "jit demand", not a "link demand" because the mechanism used is that the demand is checked when the caller is jitted.)

Obviously that is way cheaper -- one check per caller that only looks at one assembly is cheaper than one check per call that looks at every assembly on the stack -- and way more dangerous.

The link demand is basically buck-passing. The link demand says "Caller, by passing my link demand check, you get to call me for cheap from now on. But I am turning the security system off now, and therefore you are now responsible for ensuring that your caller cannot successfully attack the user by taking advantage of the fact that I am granting you the right to call me without security checks in the future."

You are calling a method with a link demand. So the question you face is: are you willing to take that responsibility? You get to call that method for cheap. Are you willing to guarantee that no low-trust hostile caller can use the fact that you get to call that method without security checks to harm the user?

If you are not willing or able to make that guarantee, then issue your own demand for the link-demanded permission; that will then require all your callers to meet the requirements. Or, pass the buck to your caller: issue a link demand to your caller and make them do the work.

(*) As I am fond of pointing out, the call stack does not actually tell you who called you, it tells you where control is going next. Since those are usually the same thing, everything works out fine. It is possible to end up in situations where "who called you?" has become divorced from "where are you going next?"; in those environments you have to be very careful using traditional-style code access security. The newer "sandboxed" security model is better suited for those scenarios.