.NET MVC 3种场景绕过Razor引擎防护

0x01 HTML.Raw

在.NET MVC视图引擎默认情况下会对内容进行HTML编码,如果ViewBag中包含HTML标签或其他特殊字符,这些字符会被编码成HTML实体,例如<会被编码为<。如果确实某些场景需要在视图中显示原始HTML内容,而不进行HTML编码,可以使用Html.Raw方法。Html.Raw标签用于将字符串内容作为原始HTML内容输出到视图中,而不进行HTML编码。它是一种特殊的助手方法,可以用于在视图中显示包含HTML标签的文本或动态生成的HTML代码。语法定义很简单 @Html.Raw(content),使用Html.Raw方法的主要目的是避免对HTML内容进行编码,以便在视图中正确地呈现HTML标签和其他原始HTML代码。因为在默认情况下.NET MVC视图引擎会对视图中的内容进行HTML编码,防止XSS跨站脚本攻击等安全问题。但有时我们需要在视图中显示包含HTML标签的文本,这时就可以使用Html.Raw方法,如定义在cshtml代码.

@{    string htmlContent = "<script>alert(2)</script>";}<h2>Raw HTML Content</h2>@Html.Raw(htmlContent)

在上述示例中我们定义了一个字符串变量htmlContent,其中包含一个带有<script>标签的HTML段落。然后我们使用Html.Raw将该字符串内容作为原始HTML内容输出到视图中造成XSS跨站攻击,如图

.NET MVC 3种场景绕过Razor引擎防护

0x02 JsonValueProvider

模型绑定是一种将操作方法参数与请求数据实体进行映射的机制,是 .NET MVC 最流行的请求响应交互功能之一。默认模型绑定器从不同的值提供者获取数据,这些值提供程序包括 FormValueProvider、QueryStringValueProvider、RouteDataValueProvider 和 HttpFileCollectionValueProvider、ChildActionValueProvider和JsonValueProvider。JsonValueProvider可以非常轻松地将您的操作方法参数与传入的 Json 数据进行建模绑定,但容易引发XSS安全问题。在本小节将展示有关JsonValueProvider的安全问题,并并且普及如何防范这种安全威胁。

先让我们创建一个示例 .NET MVC 5 应用程序设计出一篇带评论的博客文章,所以需要创建一个Comment实体类,声明两个类成员Name和UserComment,如下代码

namespace WebMVC.Models{    public class Comment    {        [Required]        public string Name { get; set; }
        [Required]        public string UserComment { get; set; }    }}

再创建Blog了,实例化一个List类型用来存储显示用户评论的数据,如下代码

namespace WebMVC.Models{    public static class Blog    {        public static List<Comment> Comments = new List<Comment>();    }}

最后写声明两个控制器方法Contact,[HttpGet]注解用来显示用户评论,[HttpPost]注解用来提交用户评论,如下代码

[HttpGet]        public ActionResult Contact()        {            ViewBag.Message = "Your contact page.";            ViewData["Comments"] = Blog.Comments;            return View();        }
        [HttpPost]        public ActionResult Contact(Comment c)        {            Blog.Comments.Add(new Comment { UserComment = c.UserComment, Name = c.Name });            ViewData["Comments"] = Blog.Comments;            return View();        }最后在View目录下的Contact.cshtml视图文件里添加如下代码        foreach (var item in ViewData["Comments"] as List<WebMVC.Models.Comment>)        {            Response.Write(item.UserComment);        }

此时只需将 POST请求更改为 JSON 请求,即可轻松绕过 HTTPRequestValidation 以执行存储型 XSS 攻击。大多数用 .NET MVC及更高版本编写的站点都可能容易受到这种攻击。如图

.NET MVC 3种场景绕过Razor引擎防护

.NET MVC 3种场景绕过Razor引擎防护

使用BurpSuite扩展插件POST2JSONBurpExtender,让渗透测试人员轻松地将 POST 请求转换为 JSON 消息,如图

.NET MVC 3种场景绕过Razor引擎防护

0x03 Deserialize

如果在反序列化过程中攻击者可以利用这个特性绕过Razor引擎的HTML编码,注入恶意脚本或其他危险代码。这种情况通常发生在反序列化操作未对输入进行适当的验证和过滤,直接将客户端数据转换为对象。如下代码

<h3>    @{        if (Request.InputStream.Length > 0)        {            Request.InputStream.Position = 0;            var input = new System.IO.StreamReader(Request.InputStream).ReadToEnd();            System.Web.Script.Serialization.JavaScriptSerializer serializer = new System.Web.Script.Serialization.JavaScriptSerializer();            dynamic data = serializer.Deserialize<dynamic>(input);            Response.Write(data["UserComment"]);        }    }</h3>

上述代码中笔者在视图引入.NET内置的序列化JavaScriptSerializer类Deserialize方法解析PostBody传递的Json请求,解析后输出UserComment参数的值,可见MVC框架并没有做HTML编码处理,如图

.NET MVC 3种场景绕过Razor引擎防护

0x04 结语

在代码审计时可关注一下这几类.NET常见的XSS漏洞场景,后续笔者会继续补充其他的触发方式请大伙继续关注文章。涉及的PDF和Demo已打包发布在星球,请大伙关注dotNet安全矩阵公众号,欢迎对.NET安全关注和关心的同学加入我们,在这里能遇到有情有义的小伙伴,大家聚在一起做一件有意义的事。