我正在尝试构建MVC应用程序,并被告知这不是检索数据的好方法,并且容易受到跨站点脚本的影响。我从来没有做过安全性,也一直在尝试学习,但是我无法解决这个问题。
我猜这里有几个缺陷。我可以使用任何特定的编码吗?
我没有在此处粘贴整个代码,而是试图找出可以阻止XSS攻击的位置。
模型和视图模型
namespace ThePeopleSearchApplication.Models
{
public class UserViewModel
{
public string UID{ get; set; }
public string FName{ get; set; }
public string LName{ get; set; }
public string Email { get; set; }
public string Status{ get; set; }
}
public class UserModel
{
public string UID{ get; set; }
public string FName{ get; set; }
public string LName{ get; set; }
public string Email { get; set; }
public string Status{ get; set; }
}
}
控制器
namespace ThePeopleSearchApplication.Controllers
{
public class MyController : Controller
{
// GET: My
public ActionResult Index()
{
return View();
}
[ValidateInput(false)] //has been added to understand XSS better
public ActionResult SearchUserAjax(string userId)
{
UserModel myUser = fetchUserFromLdap(userId);
return Content("{\"message\": \"search for userId: " +
userId + " result\", \"result\": " + convertToJson(myUser) + " }");
}
private string convertToJson(UserModel myUser)
{
return "{ \"userId\": \"" + myUser.UserId + "\", \"FirstName\": \"" +
myUser.FirstName + "\", \"LastName\": \"" + myUser.LastName + "\", \"Email\": \"" +
myUser.Email + "\", \"Status\": \"" + myUser.Status + "\"}";
}
[ValidateInput(false)] //has been added to understand XSS better
public ActionResult SearchUser(string userId)
{
UserModel myUser = fetchUserFromLdap(userId);
var viewModel = new UserViewModel
{
UID = userId,
FName = myUser.FirstName,
LName = myUser.LastName,
Email = myUser.Email,
Status = myUser.Status,
};
return this.View(viewModel);
}
private UserModel fetchUserFromLdap(string userId)
{
var retVal = new UserModel();
if (String.IsNullOrEmpty(userId))
{
retVal.UID = "N/A";
retVal.FName = "N/A";
retVal.LName = "N/A";
retVal.Email = "N/A";
retVal.Status = "N/A";
}
else
{
retVal.UID = userId;
retVal.FName = "FirstName";
retVal.LName = "LastName";
retVal.Email = "email@example.com";
retVal.Status = "<div style=background-color:#F00800>My Status</div>";
}
return retVal;
}
}
}
查看
@model ThePeopleSearchApplication.Models.UserViewModel
@{
ViewBag.Title = "Search result for user: " + Model.UserId;
var ulId = "ul-id" + Model.UserId;
var formId = "form" + Model.UserId;
}
<html>
<head>
@Scripts.Render("~/bundles/jquery")
@Scripts.Render("~/bundles/bootstrap")
</head>
<body>
<h1>Search result for user: @Model.UserId</h1>
<ul id="@Html.Raw(ulId)">
<li>@Model.FirstName</li>
<li>@Model.LastName</li>
<li>@Model.Email</li>
<li>@Html.Raw(Model.Status)</li>
</ul>
<form id=@formId name=@formId action=/My/SearchUser enctype="multipart/form-data">
<input type="text" name="userId" />
<input type="submit" />
</form>
<script type="text/javascript">
var theForm = document.@formId;
$(theForm).submit(function() {
alert('Valid form');
return true;
});
// just to demonstrate potential usage $(theForm).submit();
</script>
<div>
Ajax search:
<form id="ajax-search" name="ajax-search">
<input type="text" name="userId" />
<input type="submit" />
</form>
<script>
$("#ajax-search").submit(function() {
var url = "/My/SearchUserAjax"; // the script where you handle the form input.
$.ajax({
type: "POST",
url: url,
data: $("#ajax-search").serialize(), // serializes the form's elements.
success: function(data)
{
var obj = JSON.parse(data);
$('#ajax-search').append('<hr/>');
$('#ajax-search').append(obj.message); // show response from the php script.
$('#ajax-search').append('<hr/>');
$('#ajax-search').append(obj.result.userId);
$('#ajax-search').append('<hr/>');
$('#ajax-search').append(obj.result.FirstName);
$('#ajax-search').append('<hr/>');
$('#ajax-search').append(obj.result.LastName);
$('#ajax-search').append('<hr/>');
$('#ajax-search').append(obj.result.Status);
$('#ajax-search').append('<hr/>');
}
});
return false; // avoid to execute the actual submit of the form.
});
</script>
</div>
</body>
</html>
答案 0 :(得分:0)
主要问题是用户是否以不安全的方式控制了呈现给页面的某些数据。无论是他们的名字(我的名字是<script>function() { nasty stuff is happening here... }</script>
)还是其他任何内容。
我采用以下方法,查看您的输出(或更好地考虑一下),看看在每个阶段是否有问题:
IHtmlString
,因此请避免使用此Type
(或将其返回的方法
Html.Raw()
),因此@("<script>nastyThings()</script>")
是string
,因此将被编码,脚本将无法运行string
都是由用户"<element onclick="javascript:alert('trouble')"></element>"
使用模板@Html.Raw(Model.UserBadString)
<element onclick="mySafeJsFunction()">@Model.UserSafeString</element>
”,这将使JS函数的控制权脱离了用户,并为它们提供了Razor编码的参数,而他们无法使用XSS @Html.Raw(sanitizer.Sanitize(Model.UserBadString))
,但是您可能想做得比这更好,编码实践也要好。主要要点是string
已被清除顺便说一句,请确保对JS中.innerHTML
之类的属性(或调用.html()
的可怕jQuery eval()
)的使用情况保持密切关注,就像这些接受用户控制的内容,您将遇到完全相同的问题。但是可以应用相同的步骤,(1)改为使用.innerText
,或者(3)在将其提供给JS(https://github.com/cure53/DOMPurify)之前,在字符串上使用类似DOMPurify的纯化库。不幸的是,在这种情况下,不建议使用选项(2),因为您或我必须保证剩下的一切安全,所以我宁愿相信DOMPurify可以这样做:)