【问题标题】:RazorEngine for user templates - Security?用于用户模板的 RazorEngine - 安全性?
【发布时间】:2014-05-28 09:09:57
【问题描述】:

这是对THIS 问题的更新,因为 V3 现已推出一段时间:

我也在考虑将RazorEngine 用于邮件模板(甚至更多)。
现在是否有“足够的安全模式”可供用户定义模板?

使用IsolatedTemplateService,我可以避免用户访问我的域对象,但是在旧问题中也讨论过的其他内容(例如编辑/删除文件)呢?

还有什么关于“手动”访问数据库(如果文件访问是可能的,或者在最坏的情况下是简单的暴力破解,则通过从配置文件中读取连接字符串)和例如将用户添加为管理员?

有没有办法为IsolatedTemplateService/为IsolatedTemplateService创建的自定义AppDomain“禁用”所有这些东西?

【问题讨论】:

  • 正如对该问题的公认答案所说:“一个 cshtml Razor 文件能够在站点上下文中执行任何 .NET 代码,所以是的,允许提供它们存在安全风险由用户。”您的服务器上的代码注入攻击等待发生。
  • @KrisVandermotten:是的,但是使用自定义AppDomain,您应该能够将访问限制为仅“执行代码”,而不是“文件系统访问”或“网络访问”。我目前正在尝试不同的东西,但RazorEngine 似乎没有在PermissionState.Unrestricted AppDomain 中运行...
  • 在过去,您可以创建一个具有非常有限的代码访问安全权限的 AppDomain。其中很多已经被简化,并且现在不那么强大了。但即便如此,如果有人写 while (true) ; 怎么办?我称之为拒绝服务攻击。我想这真的可以归结为:这些“用户”是谁,你信任他们吗?

标签: c# security razor razorengine


【解决方案1】:

我能够通过不使用RazorEngine 来解决这个问题,而是自己实现(基于那里的一些代码)。

RazorEngine 的主要问题如下:
对于编译剃须刀模板所需的CodeDomProvider,您需要“完全信任”AppDomain,但IsolatedTemplateService 确实在新的AppDomain 中执行“一切”,因此编译模板失败。

我通过将它分成两部分来解决这个问题:

  1. 编译模板
  2. 渲染模板

我在“主要AppDomain”中执行第一步,而在“受限AppDomain”中只执行第2步。

还有一个额外的问题:
如果您“在内存中”编译模板(=> 而不生成 *.dll 文件),这是由 RazorEngine 完成的,它会直接加载到当前的 AppDomain 中,因为它“继承”了我不想要的然后是域权限。
因此,我禁用了它并在“通用模板文件夹”中生成了一个 *.dll
所以编译后我有一个*.dll 文件,其中包含尚未在任何地方加载的模板。

第二个AppDomain 是使用以下权限集创建的:

PermissionSet permSet = new PermissionSet(PermissionState.None);
permSet.AddPermission(new SecurityPermission(SecurityPermissionFlag.Execution));
permSet.AddPermission(new FileIOPermission(FileIOPermissionAccess.Read, templatePath));
permSet.AddPermission(new ReflectionPermission(ReflectionPermissionFlag.RestrictedMemberAccess));

第一个权限需要执行任何代码,第二个是允许AppDomain从我的公共模板文件夹中加载生成的程序集,第三个是对反射的有限支持(仅在加载的程序集中,但不是即在System.*) 中支持dynamic,所以我可以使用ViewBag
其他一切都是禁止的:

  • templatePath 之外没有文件访问权限
  • 没有网络访问权限
  • 没有 SQL Server 访问权限

然后我在这个受限域中调用Render 方法,该方法加载适当的程序集并呈现模板。此方法还支持超时,然后终止渲染,以避免像 Kris 建议的 while (true) ; DOS 攻击。

到目前为止,这似乎工作正常。我现在确实将其发布为IsolatedRazor,包括NuGet package。 May RazorEngine 可以将其合并为例如RestrictedIsolatedTemplateService 左右...

【讨论】:

  • 非常好,但您仍在服务器上执行来自不受信任来源的代码,因此请务必小心。我没试过,但是Task.Run(() => while (true) ;);呢?问题是,你打开一扇巨大的门,然后尽可能地关闭它。只打开你需要的小窗口怎么样?诚然,这还有很多工作要做,因为您需要解析输入并根据允许的语法验证它们。但它本质上会更安全。
  • Task.Run(() => while (true) ;); - 没想到 - 需要检查,谢谢。但总的来说,是的,你是对的,但这并不适用于“每个人”——我使用它的模板只在我的页面后端定义,你“通常”没有用户试图关闭服务器......
  • 这就是我很久以前说的原因:“我想这真的可以归结为:这些'用户'是谁,你信任他们吗?”。如果他们没有恶意,那么保护您的服务器免受意外错误的东西可能就足够了。这可能已经足够好了。另一方面,如果您确实验证了输入,您可能能够在他们出错时提供更好的错误消息,并且您可以避免当前解决方案的开销。
  • @KrisVandermotten:最新版本现在还可以防止使用 TaskThread - 我确信仍然不是“100%”,但现在对我来说足够安全......
猜你喜欢
  • 2022-08-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-03-06
  • 2016-11-30
  • 1970-01-01
  • 2015-04-20
  • 1970-01-01
相关资源
最近更新 更多