筛选器将在 finally 语句之前运行,这样,如果可以执行其他代码,则造成状态更改的任何操作都可以带来安全问题。例如:
try { Alter_Security_State(); // This means changing anything (state variables, // switching unmanaged context, impersonation, and so on) // that could be exploitable if malicious code ran before state is restored. Do_some_work(); } finally { Restore_Security_State(); // This simply restores the state change above. }该伪代码允许筛选器备份堆栈以运行任意代码。具有类似效果的其他操作示例是对另一个标识的临时模拟,这样会设置一个避开某个安全检查的内部标志,并更改与线程关联的区域性等等。
建议的解决方案是引入异常处理程序,将代码的线程状态更改与调用方的筛选器块隔离开。但重要的是,要正确引入异常处理程序,否则将无法解决该问题。下面的 Microsoft Visual Basic(R) 示例将切换 UI 区域性,但可以类似地公开任何线程状态更改。
YourObject.YourMethod() { CultureInfo saveCulture = Thread.CurrentThread.CurrentUICulture; try { Thread.CurrentThread.CurrentUICulture = new CultureInfo("de-DE"); // Do something that throws an exception. } finally { Thread.CurrentThread.CurrentUICulture = saveCulture; } } Public Class UserCode Public Shared Sub Main() Try Dim obj As YourObject = new YourObject obj.YourMethod() Catch e As Exception When FilterFunc Console.WriteLine("An error occurred: '{0}'", e) Console.WriteLine("Current Culture: {0}", Thread.CurrentThread.CurrentUICulture) End Try End Sub Public Function FilterFunc As Boolean Console.WriteLine("Current Culture: {0}", Thread.CurrentThread.CurrentUICulture) Return True End Sub End Class在此例中,正确的修复措施是在 try/catch 块中包装现有的 try/finally 块。只将 catch-throw 子句引入现有的 try/finally 块中将无法解决问题:
YourObject.YourMethod() { CultureInfo saveCulture = Thread.CurrentThread.CurrentUICulture; try { Thread.CurrentThread.CurrentUICulture = new CultureInfo("de-DE"); // Do something that throws an exception. } catch { throw; } finally { Thread.CurrentThread.CurrentUICulture = saveCulture; } }这不会解决问题,因为在 FilterFunc 获得控制权之前尚未运行 finally 语句。
以下代码通过确保在根据调用方的异常筛选块提供异常之前执行 finally 子句,来解决该问题。
YourObject.YourMethod() { CultureInfo saveCulture = Thread.CurrentThread.CurrentUICulture; try { try { Thread.CurrentThread.CurrentUICulture = new CultureInfo("de-DE"); // Do something that throws an exception. } finally { Thread.CurrentThread.CurrentUICulture = saveCulture; } } catch { throw; } } 非托管代码某些库代码需要调用非托管代码(例如,本机代码 API,如 Win32)。因为这意味着脱离托管代码的安全边界,所以应十分谨慎。如果您的代码是安全中立的(请参阅本文的安全中立代码部分),则您的代码和任何调用它的代码都必须拥有非托管代码权限 (SecurityPermission.UnmanagedCode)。
但是,要求您的调用方拥有这么大的权限通常是不合理的。在这种情况下,您的受信任代码可以是“调解者”,类似于先前描述的托管包装程序或库代码。如果基础非托管代码的功能是完全安全的,则可以直接公开它;否则,需要先进行适当的权限检查 (demand)。
当您的代码调用非托管代码、但您不想让调用方拥有该权限时,必须断言您的权利。断言会在您的帧处阻塞堆栈审核。您必须谨慎小心,不要在该过程中创建安全漏洞。通常,这意味着您必须请求适当的调用方权限,然后只使用非托管代码来执行该权限允许的操作,但不能再执行其他操作。在某些情况下(例如,获得一天中的时间),非托管代码可以直接公开给调用方,而不需要进行任何安全检查。在任何情况下,作出断言的任何代码都必须为安全性负责。
文章来源于领测软件测试网 https://www.ltesting.net/