配置与静态属性,安全性问题

时间:2012-01-18 19:33:04

标签: c# .net security configuration

我正在开发一个类库,我需要提供一种设置配置参数的方法。我可以创建一个配置部分,或者我可以公开静态属性。我对静态属性的关注是安全性。是什么阻止恶意组件在运行时进行更改?例如,在ASP.NET MVC中,您使用静态属性配置路由。这样安全吗?恶意组件可以添加/删除路由吗?

<小时/> “不受信任的组件”如何首先进入我的应用程序?以NuGet为例。我们不知道那里有什么,谁做了,以及它是否包含一些不希望的状态变化。

“不受信任的组件”如何运行?在ASP.NET中,您只需要PreApplicationStartMethodAttribute在应用程序启动时运行一些代码。

5 个答案:

答案 0 :(得分:10)

当您将某些事情视为安全威胁时,您还应该考虑您要保护的对象。

为了让“恶意代码”更改static属性的值,需要将此代码加载到AppDomain并运行。现在认为恶意攻击者设法让他的代码在您的AppDomain中运行 - 您的static属性真的是您的主要关注点吗?这样的攻击者可能做得最糟糕。

除非您有需要加载源自外部不受信任来源的程序集/代码的情况,否则我认为您并不需要防止您的用户访问您的属性(不是从安全角度来看 - 可用性是另一回事)。

编辑 - 关于外部不受信任的代码

我仍然认为这不是你真正关心的问题。如果我理解正确,您正在开发并提供一个库,供其应用程序中的某些第三方使用。

如果应用程序所有者决定使用一些他不信任的外部库,将其添加到他的应用程序中并允许它运行,那么这不是您关注的问题,而是应用程序所有者的关注。

在这种情况下,我上面说的一切仍然适用。恶意代码可以比设置属性更糟糕。它可能会破坏内存,损坏数据,泛滥线程池,甚至容易导致AppDomain崩溃。

关键是,如果您不拥有该应用程序,因为您只提供了一个类库,那么您无需为运行里面的代码保护AppDomain课程已加载。

注意:Re。 NuGet,我不会太担心。 NuGet是一种静态工具。如果我理解正确,它不会在运行时执行任务,例如下载代码并运行它。它仅在设计时中用于下载二进制文件,添加引用以及可能添加代码。我认为假设使用NuGet下载软件包的应用程序所有者将尽职尽责以确保软件包是安全的,这是完全合理的。在开发过程中,他只需要做一次。

答案 1 :(得分:2)

正如之前的答案所指出的,这里并没有太大的区别。

恶意代码可能会设置静态属性,恶意代码可能会更改配置文件。后者可能更容易从外部弄清楚,并且无论代码运行的方式如何都可以完成(它不必是.NET,也不必在您的应用程序域中运行,并且确实不需要是代码,如果有人获得手动更改文件的能力,那么在静态属性的使用中有一点安全优势,尽管考虑到我们可能只有一个相当虚假的属性因为调用代码很可能正在使用配置本身来决定将属性设置为什么来推动这个问题!

还有第三种可能性,即你有一个实例成员设置属性的实例,它是使该实例静态的调用代码。这可能与您正在做的事情完全无关,但值得考虑的情况是有人可能希望您的代码在同一应用程序域中使用两组配置参数运行。作为安全问题,它与静态成员的问题大致相同,只是它可能会影响序列化问题。

所以,到目前为止,配置文件的缺点在于,它们可能会受到与您完全分开的代码的攻击,但需要注意的是,无论如何,信息可能会在其他地方的配置文件中结束。

无论采用哪种方法,访问的安全性都取决于您加载部分受信任的代码的方式。

应将代码加载到自己的应用程序域中,并在该应用程序域上的安全性设置为可信任的程度。如果可能的话,它不应该是您的库,而是由调用代码决定由其加载的任何部分受信任的代码设置的策略。当然,如果它是您的库固有的它在部分受信任的代码中加载的目的,然后它必须这样做,但通常它应该保持不知道代码是完全或部分信任,除非在适当时要求某些权限。如果由您的库加载此代码,则需要确定适当的权限以授予应用程序域。实际上,这应该是允许执行加载的工作的最低权限数量。这可能不包括FileIOPermission,因此阻止它写入配置文件。

现在,无论您的库或调用代码是否已加载部分受信任的代码,您都需要考虑对您公开的类及其成员所需的权限。这涵盖了静态setter属性,但如果您采用配置文件方法仍然是必要的,因为您的方案仍然涉及访问您的库的部分受信任的代码。

在某些情况下,这些方法不需要任何更多的保护,因为它们本身就是由于它们的作用而拥有它。例如,如果您尝试访问文件但调用代码没有这样做的权限,那么您的代码将失败并出现一个安全异常,该异常将传递给调用代码。实际上,您可能必须采取相反的措施并采取措施允许部分受信任的代码调用您的方法(如果您以安全的方式访问文件,因为调用者不能影响访问哪个文件或者您可能想要的方式此时获得Assert文件访问权限。)

在其他情况下,您可能需要添加保护,因为调用代码不会执行任何立即尝试安全限制操作但可能导致受信任代码以不适当方式运行的操作。例如,如果您的代码存储了稍后操作使用的路径,那么基本上调用该代码允许以特定方式进行文件访问。 E.g:

public string TempFilePath{get;set;}
public void WriteTempData(string data)
{
  using(sw = new StreamWriter(TempFilePath, true))
    sw.Write(data);
}

如果恶意代码设置为TempDirPath,则可能会导致受信任代码稍后调用WriteTempData通过覆盖它来破坏重要文件。这里一个明显的方法是在适当的Demand对象上调用FileIOPermission,这样唯一可以设置它的代码就是已经信任写入任意位置的代码(当然这可能是两者结合起来限制TempDirPath的可能值,并要求能够在允许的位置集内写入。

您还可以要求某些权限的同意,当然也可以创建自己的权限,但使用框架定义的联盟可以更好地适应现有代码。

答案 2 :(得分:1)

  

是什么阻止恶意组件在运行时进行更改?

这取决于“恶意组件”的定义。配置实际上是为了允许在运行时进行更改。

如果您通过代码(无论是静态属性还是实例属性等)处理此问题,您可以直接控制允许的设置,因为您的属性设置器可以根据您的需要控制它。如果您的应用程序需要,您还可以添加某种形式的安全性,因为您可以控制它的设置方式。

使用配置部分,您唯一的控制就是读取值 - 您无法控制写入,而是必须验证读取时的设置。

答案 3 :(得分:1)

当然,即使被定义为私有成员,也可以通过提供这些抽象的基础类进行更改。

考虑一个安全拦截器,它根据已验证或匿名用户的已定义权限提供每个请求。

答案 4 :(得分:0)

我通常一起使用Config文件和静态变量。我将静态变量定义为私有,并且我只使用“get”方法来公开值。所以它不能在课外改变。

我创建了一个类来处理实现“IConfigurationSectionHandler”接口的配置。我的实现是针对ASP.NET Web应用程序的。

步骤1:在web.config文件中创建一个部分以便稍后处理。

<configuration>
    <configSections>
        <section name="XXXConfiguration" type="Company.XXXConfiguration, Company"/>
        ...
    </configSections>

    <XXXConfiguration>
        <Variable>Value to set static variable</Variable>
    </XXXConfiguration>

    ...

<configuration>

步骤2:创建一个类来处理先前的配置部分。

using System;
using System.Collections;
using System.Collections.Specialized;
using System.Xml;
using System.Configuration;
namespace Company{
    public class XXXConfiguration : IConfigurationSectionHandler
    {
        /// <summary>
        /// Initializes a new instance of LoggingConfiguration class.
        /// </summary>
        public XXXConfiguration() {}

        private static string _variable;

        public static string Variable
        {
            get {return XXXConfiguration._variable; }
        }

        public object Create(object parent, object configContext, XmlNode section)
        {
            // process config section node
            XXXConfiguration._variable = section.SelectSingleNode("./Variable").InnerText;

            return null;
        }

    }
}

步骤3:在启动应用程序时使用System.Configuration.ConfigurationManager的GetSection方法。在Global.asax

void Application_Start(object sender, EventArgs e) 
{
      // Code that runs on application startup
      System.Configuration.ConfigurationManager.GetSection("LoggingConfiguration");
      ...
}