مقابله با XSS ؛ یکبار برای همیشه!
نویسنده: وحید نصیری
تاریخ: ۱۳۹۰/۰۲/۳۰ ۰۱:۱۹:۰۰
آدرس: www.dntips.ir
| مطالب | ۳۶۹۴ |
| نویسندگان | ۲۷۶ |
| گروههای مطالب | ۱۰۲۴ |
| نقشههای راه | ۱۱۹ |
| دورهها | ۱۴ |
| اشتراکها | ۱۷۹۱۴ |
using System; using System.Collections.Specialized; using System.Reflection; using System.Text.RegularExpressions; using System.Web; using Microsoft.Security.Application;
namespace AntiXssMdl { public class AntiXssModule : IHttpModule { private static readonly Regex _cleanAllTags = new Regex("<[^>]+>", RegexOptions.Compiled); public void Init(HttpApplication context) { context.BeginRequest += CleanUpInput; }
public void Dispose() { }
private static void CleanUpInput(object sender, EventArgs e) { HttpRequest request = ((HttpApplication)sender).Request; if (request.QueryString.Count > 0) { //تمیزکاری مقادیر کلیه کوئری استرینگها پیش از استفاده در برنامه CleanUpAndEncode(request.QueryString, allowHtmltags: false); }
if (request.HttpMethod == "POST") { //تمیزکاری کلیه مقادیر ارسالی به سرور if (request.Form.Count > 0) { CleanUpAndEncode(request.Form, allowHtmltags: true); } } }
private static void CleanUpAndEncode(NameValueCollection collection, bool allowHtmltags) { //اندکی دستکاری در سیستم داخلی دات نت PropertyInfo readonlyProperty = collection .GetType() .GetProperty("IsReadOnly", BindingFlags.Instance | BindingFlags.NonPublic); readonlyProperty.SetValue(collection, false, null);//IsReadOnly=false
for (int i = 0; i < collection.Count; i++) { if (string.IsNullOrWhiteSpace(collection[i])) continue;
if (!allowHtmltags) { //در حالت کوئری استرینگ دلیلی برای ارسال هیچ نوع تگی وجود ندارد collection[collection.Keys[i]] = AntiXss.HtmlEncode(_cleanAllTags.Replace(collection[i], string.Empty)); } else { //قصد تمیز سازی ویوو استیت را نداریم چون در این حالت وب فرمها از کار میافتند if (collection.Keys[i].StartsWith("__VIEWSTATE")) continue; //در سایر موارد کاربران مجازند فقط تگهای سالم را ارسال کنند و مابقی حذف میشود collection[collection.Keys[i]] = Sanitizer.GetSafeHtml(collection[i]); } }
readonlyProperty.SetValue(collection, true, null);//IsReadOnly=true } } }
<?xml version="1.0"?>
<configuration>
<system.web>
<pages validateRequest="false" enableEventValidation="false" />
<httpRuntime requestValidationMode="2.0" />
<compilation debug="true" targetFramework="4.0" />
<httpModules>
<add name="AntiXssModule" type="AntiXssMdl.AntiXssModule"/>
</httpModules>
</system.web>
<system.webServer>
<validation validateIntegratedModeConfiguration="false"/>
<modules>
<add name="AntiXssModule" type="AntiXssMdl.AntiXssModule"/>
</modules>
</system.webServer>
</configuration>
private HttpApplication _context = null;
public void Init(HttpApplication context)
{
_context = context;
_context.BeginRequest += CleanUpInput;
}
public void Dispose()
{
_context.BeginRequest -= CleanUpInput;
}
<%@ Page
Language="C#"
AutoEventWireup="true"
CodeBehind="editpage.aspx.cs"
validateRequest="false"
Inherits="MyProject.UI.editpage" %>
<system.web>
<pages validateRequest="false" enableEventValidation="true" />
<httpRuntime requestValidationMode="2.0" />
</system.web>
<httpRuntime executionTimeout="180" encoderType="Microsoft.Security.Application.AntiXssEncoder, AntiXssLibrary" />
public class Contact
{
public int Id { get; set; }
[AllowHtml]
public string Name { get; set; }
public string Address { get; set; }
} [HttpGet]
public ActionResult ContactUs()
{
return View();
}
[HttpPost]
public ActionResult ContactUs(Contact con)
{
ViewBag.Name = con.Name.ToSafeHtml();
ViewBag.MyAddress = con.Address;
return View();
} A potentially dangerous Request.Form value was detected from the client (Name="<script>alert("aaa")..."). public class Post
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int PostId { get; set; }
[Required(ErrorMessage = "فیلد عنوان الزامی است")]
[Display(Name = "عنوان پست")]
public string PostTitle { get; set; }
[Display(Name = "محتوا")]
[AllowHtml]
public string Content { get; set; }
[DataType(DataType.Date)]
[Display(Name = "تاریخ نشر")]
public DateTime PublishDate { get; set; }
} [HttpPost]
public ActionResult CreateNewPost(Post post)
{
if (ModelState.IsValid)
{
post.Content = post.Content.ToSafeHtml();
PostData.AddNewPost(post);
return RedirectToAction("Index", "Home", new { area = "" });
}
return View(post);
}