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跨站攻击,如图
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及更高版本编写的站点都可能容易受到这种攻击。如图
使用BurpSuite扩展插件POST2JSONBurpExtender,让渗透测试人员轻松地将 POST 请求转换为 JSON 消息,如图
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编码处理,如图