اندازهی قلم متن
تخمین مدت زمان مطالعهی مطلب:
چهار دقیقه
ASP.NET به صورت پیش فرض در مقابل ارسال هر نوع تگی عکس العمل نشان میدهد و پیغام خطای یافتن خطری بالقوه را گوشزد میکند. اما بین خودمان باشد، همه این قابلیت را خاموش میکنند! چون در یک برنامه واقعی نیاز است تا مثلا کاربران تگ html هم ارسال کنند. برای نمونه یک ادیتور متنی پیشرفته را درنظر بگیرید. خاموش کردن این قابلیت هم مساوی است با فراهم کردن امکان ارسال تگهای مجاز و در کنار آن بی دفاع گذاشتن برنامه در مقابل حملات XSS.
توصیه هم این است که همه جا از توابع مثلا HtmlEncode و موارد مشابه حتما استفاده کنید. ولی باز هم خودمونیم ... چند نفر از شماها اینکار را میکنید؟!
بهترین کار در این موارد وارد شدن به pipe line پردازشی ASP.NET و دستکاری آن است! اینکار هم توسط HttpModules میسر است. به عبارتی در ادامه میخواهیم ماژولی را بنویسیم که کلیه تگهای ارسالی کوئری استرینگها را پاک کرده و همچنین تگهای خطرناک موجود در مقادیر ارسالی فرمهای برنامه را هم به صورت خودکار حذف کند. اما هنوز اجازه بدهد تا کاربران بتوانند تگ HTML هم ارسال کنند.
مشکل! در ASP.NET مقادیر ارسالی کوئری استرینگها و همچنین فرمها به صورت NameValueCollection در اختیار برنامه قرار میگیرند و ... خاصیت IsReadOnly این مجموعهها در حین ارسال، به صورت پیش فرض true است و همچنین غیرعمومی! یعنی به همین سادگی نمیتوان عملیات تمیزکاری را روی مقادیر ارسالی، پیش از مهیا شدن آن جهت استفاده در برنامه اعمال کرد. بنابراین در ابتدای کار نیاز است با استفاده از قابلیت Reflection ، اندکی در سازوکار داخلی ASP.NET دست برد، این خاصیت فقط خواندنی غیرعمومی را برای مدت کوتاهی false کرد و سپس مقصود نهایی را اعمال نمود. پیاده سازی آن را در ادامه مشاهده میکنید:
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 } } }
در این کلاس از کتابخانه AntiXSS مایکروسافت استفاده شده است. آخرین نگارش آنرا از اینجا دریافت نمائید. نکته مهم آن متد Sanitizer.GetSafeHtml است. به کمک آن با خیال راحت میتوان در یک سایت، از یک ادیتور متنی پیشرفته استفاده کرد. کاربران هنوز میتوانند تگهای HTML را ارسال کنند؛ اما در این بین هرگونه سعی در ارسال عبارات و تگهای حاوی حملات XSS پاکسازی میشود.
و یک وب کانفیگ نمونه برای استفاده از آن به صورت زیر میتواند باشد (تنظیم شده برای IIS6 و 7):
<?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>
برای مثال به تصویر زیر دقت کنید. ماژول فوق، فقط تگهای سبز رنگ را (حین ارسال به سرور) مجاز دانسته، اسکریپت ذیل لینک را کلا حذف کرده و تگهای موجود در کوئری استرینگ را هم نهایتا (زمانیکه در اختیار برنامه قرار میگیرد) حذف خواهد کرد.
دریافت نسخه جدید و نهایی این مثال