it-swarm.asia

تم اكتشاف قيمة Request.Form يحتمل أن تكون خطرة من العميل

في كل مرة ينشر فيها المستخدم شيئًا ما يحتوي على < أو > في صفحة في تطبيق الويب الخاص بي ، أحصل على هذا الاستثناء.

لا أريد الخوض في مناقشة حول ذكاء طرح استثناء أو تعطل تطبيق ويب بأكمله لأن شخصًا ما أدخل شخصية في مربع نص ، لكنني أبحث عن طريقة أنيقة للتعامل مع هذا.

تعويض اللون الاستثناء والعرض

لقد حدث خطأ ، يرجى العودة وإعادة كتابة النموذج بالكامل مرة أخرى ، لكن هذه المرة ، يرجى عدم استخدام <

لا يبدو المهنية بما فيه الكفاية بالنسبة لي.

سيؤدي تعطيل التحقق من الصحة للنشر (validateRequest="false") بالتأكيد إلى تجنب هذا الخطأ ، ولكنه سيترك الصفحة عرضة لعدد من الهجمات.

من الناحية المثالية: عند حدوث إعادة نشر تحتوي على أحرف مقيدة بتنسيق HTML ، سيتم تلقائيًا تشفير تلك القيمة المنشورة في مجموعة النماذج. وبالتالي فإن خاصية .Text الخاصة بمربع النص الخاص بي ستكون something & lt; html & gt;

هل هناك طريقة يمكنني القيام بذلك من معالج؟

1394
Radu094

أعتقد أنك تهاجمها من الزاوية الخطأ بمحاولة تشفير جميع البيانات المنشورة.

لاحظ أن "<" قد يأتي أيضًا من مصادر خارجية أخرى ، مثل حقل قاعدة البيانات ، والتكوين ، وملف ، وموجز وما إلى ذلك.

علاوة على ذلك ، "<" ليست خطيرة بطبيعتها. إنه أمر خطير فقط في سياق محدد: عند كتابة السلاسل التي لم يتم تشفيرها لإخراج HTML (بسبب XSS).

في سياقات أخرى ، تكون السلاسل الفرعية المختلفة خطيرة ، على سبيل المثال ، إذا كتبت عنوان URL مقدم من المستخدم في رابط ، فقد تكون السلسلة الفرعية "javascript:" خطيرة. حرف الاقتباس الفردي من ناحية أخرى أمر خطير عند تقريب السلاسل في استعلامات SQL ، ولكنه آمن تمامًا إذا كان جزءًا من اسم مقدم من نموذج أو تمت قراءته من حقل قاعدة بيانات.

خلاصة القول هي: لا يمكنك تصفية الإدخال العشوائي للأحرف الخطرة ، لأن أي حرف قد يكون خطيرًا في الظروف المناسبة. يجب أن تشفر عند النقطة التي قد تصبح فيها بعض الشخصيات المحددة خطرة لأنها تعبر إلى لغة فرعية مختلفة يكون لها فيها معنى خاص. عند كتابة سلسلة إلى HTML ، يجب عليك ترميز الأحرف التي لها معنى خاص في HTML ، باستخدام Server.HtmlEncode. إذا قمت بتمرير سلسلة إلى عبارة SQL ديناميكية ، فيجب عليك ترميز أحرف مختلفة (أو الأفضل ، دع إطار العمل يقوم بذلك نيابة عنك باستخدام عبارات معدة أو ما شابه) ..

عندما أنت متأكد من أنك تقوم بترميز HTML في كل مكان تقوم بتمرير سلاسل إلى HTML ، ثم قم بتعيين validateRequest="false" في توجيه <%@ Page ... %> في ملف (ملفات) .aspx الخاص بك.

في .NET 4 ، قد تحتاج إلى عمل المزيد. في بعض الأحيان يكون من الضروري أيضًا إضافة <httpRuntime requestValidationMode="2.0" /> إلى web.config ( reference ).

1039
JacquesB

يوجد حل مختلف لهذا الخطأ إذا كنت تستخدم ASP.NET MVC:

ج # عينة:

[HttpPost, ValidateInput(false)]
public ActionResult Edit(FormCollection collection)
{
    // ...
}

نموذج Visual Basic:

<AcceptVerbs(HttpVerbs.Post), ValidateInput(False)> _
Function Edit(ByVal collection As FormCollection) As ActionResult
    ...
End Function
488
Zack Peterson

في ASP.NET MVC (يبدأ في الإصدار 3) ، يمكنك إضافة AllowHtml السمة إلى خاصية على النموذج الخاص بك.

يسمح طلب بتضمين علامة HTML أثناء ربط النموذج عن طريق تخطي التحقق من صحة الطلب للخاصية.

[AllowHtml]
public string Description { get; set; }
390
Anthony Johnston

إذا كنت على .NET 4.0 ، فتأكد من إضافة هذا في web.config ملف داخل علامات <system.web>:

<httpRuntime requestValidationMode="2.0" />

في .NET 2.0 ، طلب التحقق من الصحة المطبق فقط على طلبات aspx. في. NET 4.0 تم توسيع هذا ليشمل جميع الطلبات. يمكنك الرجوع إلى فقط إجراء التحقق من صحة XSS عند معالجة .aspx عن طريق تحديد:

requestValidationMode="2.0"

يمكنك تعطيل طلب التحقق من الصحة بالكامل عن طريق تحديد:

validateRequest="false"
209
JordanC

بالنسبة لـ ASP.NET 4.0 ، يمكنك السماح بالعلامة كمدخلات لصفحات محددة بدلاً من الموقع بأكمله من خلال وضعه كله في عنصر <location>. سيضمن هذا أن تكون جميع صفحاتك الأخرى آمنة. لا تحتاج إلى وضع ValidateRequest="false" في صفحة .aspx الخاصة بك.

<configuration>
...
  <location path="MyFolder/.aspx">
    <system.web>
      <pages validateRequest="false" />
      <httpRuntime requestValidationMode="2.0" />
    </system.web>
  </location>
...
</configuration>

يمكنك التحكم في هذا داخل web.config ، لأنه يمكنك أن ترى على مستوى الموقع الصفحات التي تسمح بالترميز كمدخلات.

لا تزال بحاجة إلى التحقق من صحة الإدخال على الصفحات التي يتم فيها تعطيل التحقق من صحة الطلب.

109
Carter Medlin

الإجابات السابقة رائعة ، ولكن لم يقل أي أحد كيفية استبعاد حقل واحد من أن يتم التحقق من صحة لحقن HTML/JavaScript. لا أعرف الإصدارات السابقة ، ولكن في MVC3 Beta يمكنك القيام بذلك:

[HttpPost, ValidateInput(true, Exclude = "YourFieldName")]
public virtual ActionResult Edit(int id, FormCollection collection)
{
    ...
}

لا يزال هذا يتحقق من صحة جميع الحقول باستثناء الحقل المستبعد. الشيء الجميل في هذا الأمر هو أن سمات التحقق من الصحة ما زالت تتحقق من الحقل ، لكنك لا تحصل على استثناءات "طلب خطير محتمل. تم اكتشاف قيمة من العميل".

لقد استخدمت هذا للتحقق من صحة التعبير العادي. لقد صنعت ValidationAttribute الخاص بي لمعرفة ما إذا كان التعبير العادي صالحًا أم لا. نظرًا لأن التعبيرات العادية يمكن أن تحتوي على شيء يشبه البرنامج النصي ، قمت بتطبيق الرمز أعلاه - لا يزال يتم التحقق من التعبير العادي إذا كان صحيحًا أم لا ، ولكن ليس إذا كان يحتوي على برامج نصية أو HTML.

70
gligoran

في ASP.NET MVC تحتاج إلى تعيين requestValidationMode = "2.0" و validateRequest = "false" في web.config ، وتطبيق سمة ValidateInput على إجراء وحدة التحكم الخاصة بك:

<httpRuntime requestValidationMode="2.0"/>

<configuration>
    <system.web>
        <pages validateRequest="false" />
    </system.web>
</configuration>

و

[Post, ValidateInput(false)]
public ActionResult Edit(string message) {
    ...
}
48
ranthonissen

يمكنك تشفير HTML مربع نص المحتوى ، ولكن للأسف لن يمنع هذا الاستثناء من الحدوث. في تجربتي لا توجد طريقة للتغلب عليها ، وعليك تعطيل التحقق من صحة الصفحة. من خلال القيام بذلك ، فأنت تقول: "سأكون حذرًا ، وأعدكم".

45
Pavel Chuchuva

بالنسبة إلى MVC ، تجاهل التحقق من صحة الإدخال عن طريق الإضافة

[ValidateInput (كاذبة)]

فوق كل عمل في المراقب المالي.

42
A.Dara

يمكنك التقاط هذا الخطأ في Global.asax. ما زلت أرغب في التحقق من الصحة ، ولكنني أعرض رسالة مناسبة. على المدونة المدرجة أدناه ، كانت عينة مثل هذه متاحة.

    void Application_Error(object sender, EventArgs e)
    {
        Exception ex = Server.GetLastError();

        if (ex is HttpRequestValidationException)
        {
            Response.Clear();
            Response.StatusCode = 200;
            Response.Write(@"[html]");
            Response.End();
        }
    }

يبدو أن إعادة التوجيه إلى صفحة أخرى استجابة معقولة للاستثناء.

http://www.romsteady.net/blog/2007/06/how-to-catch-httprequestvalidationexcep.html

41
BenMaddox

يرجى الأخذ في الاعتبار أن بعض عناصر تحكم .NET ستعمل تلقائيًا على ترميز HTML للإخراج. على سبيل المثال ، سيؤدي تعيين الخاصية Text. في عنصر تحكم TextBox إلى ترميزها تلقائيًا. هذا يعني بالتحديد تحويل < إلى &lt; و > إلى &gt; و & إلى &amp;. لذلك كن حذرا من القيام بذلك ...

myTextBox.Text = Server.HtmlEncode(myStringFromDatabase); // Pseudo code

ومع ذلك ، فإن خاصية .Text الخاصة بـ HyperLink و Literal و Label لن تقوم بتشفير HTML ، لذا فإن التفاف Server.HtmlEncode ()؛ حول أي شيء يتم تعيينه على هذه الخصائص أمر لا بد منه إذا كنت ترغب في منع <script> window.location = "http://www.google.com"; </script> من الإخراج إلى صفحتك وتنفيذها فيما بعد.

قم بإجراء بعض التجارب لمعرفة ما الذي يتم ترميزه وما لا يتم ترميزه.

33
Dominic Pettifer

والجواب على هذا السؤال بسيط:

var varname = Request.Unvalidated["parameter_name"];

هذا من شأنه تعطيل التحقق من الصحة لطلب معين.

32
flakomalo

في ملف web.config ، ضمن العلامات ، أدخل عنصر httpRuntime مع السمة requestValidationMode = "2.0". إضافة السمة validateRequest = "false" أيضًا في عنصر الصفحات.

مثال:

<configuration>
  <system.web>
   <httpRuntime requestValidationMode="2.0" />
  </system.web>
  <pages validateRequest="false">
  </pages>
</configuration>
27
Mahdi jokar

إذا كنت لا ترغب في تعطيل ValidateRequest ، فستحتاج إلى تنفيذ وظيفة JavaScript لتجنب الاستثناء. إنه ليس الخيار الأفضل ، لكنه يعمل.

function AlphanumericValidation(evt)
{
    var charCode = (evt.charCode) ? evt.charCode : ((evt.keyCode) ? evt.keyCode :
        ((evt.which) ? evt.which : 0));

    // User type Enter key
    if (charCode == 13)
    {
        // Do something, set controls focus or do anything
        return false;
    }

    // User can not type non alphanumeric characters
    if ( (charCode <  48)                     ||
         (charCode > 122)                     ||
         ((charCode > 57) && (charCode < 65)) ||
         ((charCode > 90) && (charCode < 97))
       )
    {
        // Show a message or do something
        return false;
    }
}

ثم في التعليمات البرمجية الخلفية ، في حدث PageLoad ، أضف السمة إلى عنصر التحكم الخاص بك مع الكود التالي:

Me.TextBox1.Attributes.Add("OnKeyPress", "return AlphanumericValidation(event);")
23
YORENGOY

يبدو أن أحداً لم يذكر ما يلي أدناه ، ولكنه يعمل على حل المشكلة بالنسبة لي. وقبل أن يقول أي شخص نعم ، إنه Visual Basic ... يوك.

<%@ Page Language="vb" AutoEventWireup="false" CodeBehind="Example.aspx.vb" Inherits="Example.Example" **ValidateRequest="false"** %>

لا أعرف إذا كان هناك أي سلبيات ، لكن بالنسبة لي كان هذا رائعًا.

20
Piercy

حل آخر هو:

protected void Application_Start()
{
    ...
    RequestValidator.Current = new MyRequestValidator();
}

public class MyRequestValidator: RequestValidator
{
    protected override bool IsValidRequestString(HttpContext context, string value, RequestValidationSource requestValidationSource, string collectionKey, out int validationFailureIndex)
    {
        bool result = base.IsValidRequestString(context, value, requestValidationSource, collectionKey, out validationFailureIndex);

        if (!result)
        {
            // Write your validation here
            if (requestValidationSource == RequestValidationSource.Form ||
                requestValidationSource == RequestValidationSource.QueryString)

                return true; // Suppress error message
        }
        return result;
    }
}
18
Sel

إذا كنت تستخدم Framework 4.0 ، فسيكون الإدخال في web.config (<pages validateRequest = "false" />)

<configuration>
    <system.web>
        <pages validateRequest="false" />
    </system.web>
</configuration>

إذا كنت تستخدم Framework 4.5 ، فقم بإدخال الإدخال في web.config (requestValidationMode = "2.0")

<system.web>
    <compilation debug="true" targetFramework="4.5" />
    <httpRuntime targetFramework="4.5" requestValidationMode="2.0"/>
</system.web>

إذا كنت تريد صفحة واحدة فقط بعد ذلك ، في ملف aspx ، يجب أن تضع السطر الأول كما يلي:

<%@ Page EnableEventValidation="false" %>

إذا كان لديك بالفعل شيء مثل <٪ @ Page ، فقم فقط بإضافة الباقي => EnableEventValidation="false"٪>

أوصي بعدم القيام بذلك.

14
Durgesh Pandey

في ASP.NET ، يمكنك التقاط الاستثناء والقيام بشيء حيال ذلك ، مثل عرض رسالة مألوفة أو إعادة توجيه إلى صفحة أخرى ... هناك أيضًا إمكانية أن تتمكن من معالجة التحقق من صحة نفسك ...

عرض رسالة ودية:

protected override void OnError(EventArgs e)
{
    base.OnError(e);
    var ex = Server.GetLastError().GetBaseException();
    if (ex is System.Web.HttpRequestValidationException)
    {
        Response.Clear();
        Response.Write("Invalid characters."); //  Response.Write(HttpUtility.HtmlEncode(ex.Message));
        Response.StatusCode = 200;
        Response.End();
    }
}
13
Jaider

أعتقد أنك يمكن أن تفعل ذلك في وحدة نمطية ؛ لكن هذا يترك بعض الأسئلة مفتوحة ؛ ماذا لو كنت تريد حفظ المدخلات في قاعدة البيانات؟ فجأة لأنك تقوم بحفظ البيانات المشفرة في قاعدة البيانات ، ينتهي بك الأمر إلى الوثوق في المدخلات منه والتي ربما تكون فكرة سيئة. من المثالي أن تقوم بتخزين البيانات غير المشفرة الخام في قاعدة البيانات والتشفير في كل مرة.

يعد تعطيل الحماية على مستوى الصفحة ثم الترميز في كل مرة خيارًا أفضل.

بدلاً من استخدام Server.HtmlEncode ، يجب أن تنظر إلى الأحدث والأكمل مكتبة Anti-XSS من فريق Microsoft ACE.

12
blowdart

الحلول الأخرى هنا لطيفة ، ومع ذلك ، فإنه من الألم الملكي في الجزء الخلفي أن تضطر إلى تطبيق [AllowHtml] على كل خاصية طراز واحد ، خاصة إذا كان لديك أكثر من 100 نموذج في موقع مناسب الحجم.

إذا كنت مثلي ، فأنت تريد إيقاف تشغيل هذه الميزة (بدون جدوى إلى حد كبير من IMHO) خارج الموقع ، ويمكنك تخطي طريقة Execute () في وحدة التحكم الأساسية (إذا لم يكن لديك بالفعل وحدة تحكم أساسية ، أقترح عليك إنشاء واحدة ، يمكن أن تكون مفيدة جدا لتطبيق وظيفة مشتركة).

    protected override void Execute(RequestContext requestContext)
    {
        // Disable requestion validation (security) across the whole site
        ValidateRequest = false;
        base.Execute(requestContext);
    }

فقط تأكد من قيامك بتشفير HTML لكل شيء يتم ضخه إلى طرق العرض التي تأتي من إدخال المستخدم (إنه السلوك الافتراضي في ASP.NET MVC 3 مع Razor على أي حال ، لذلك ما لم يكن سببًا غريبًا أنك تستخدم Html.Raw () لك لا ينبغي أن تتطلب هذه الميزة.

10
magritte

لقد وجدت حلاً يستخدم JavaScript لتشفير البيانات ، والتي تم فك تشفيرها في .NET (ولا تتطلب jQuery).

  • اجعل مربع النص عنصر HTML (مثل textarea) بدلاً من ASP واحد.
  • إضافة حقل مخفي.
  • أضف وظيفة JavaScript التالية إلى رأسك.

    function boo () {targetText = document.getElementById ("HiddenField1")؛ sourceText = document.getElementById ("userbox")؛ targetText.value = escape (sourceText.innerText)؛ }

في textarea الخاص بك ، قم بتضمين onchange يستدعي boo ():

<textarea id="userbox"  onchange="boo();"></textarea>

أخيرًا ، في .NET ، استخدم

string val = Server.UrlDecode(HiddenField1.Value);

أدرك أن هذا اتجاه واحد - إذا كنت بحاجة إلى اتجاهين ، فسيتعين عليك أن تكون مبدعًا ، ولكن هذا يوفر حلاً إذا لم تتمكن من تحرير web.config

إليكم مثالًا توصلت إليه (MC9000) واستخدمه عبر jQuery:

$(document).ready(function () {

    $("#txtHTML").change(function () {
        var currentText = $("#txtHTML").text();
        currentText = escape(currentText); // Escapes the HTML including quotations, etc
        $("#hidHTML").val(currentText); // Set the hidden field
    });

    // Intercept the postback
    $("#btnMyPostbackButton").click(function () {
        $("#txtHTML").val(""); // Clear the textarea before POSTing
                               // If you don't clear it, it will give you
                               // the error due to the HTML in the textarea.
        return true; // Post back
    });


});

والترميز:

<asp:HiddenField ID="hidHTML" runat="server" />
<textarea id="txtHTML"></textarea>
<asp:Button ID="btnMyPostbackButton" runat="server" Text="Post Form" />

هذا يعمل بشكل رائع. إذا حاول أحد المتطفلين نشر جافا سكريبت عبر تجاوزه ، فسوف يرون الخطأ فقط. يمكنك حفظ كل هذه البيانات المشفرة في قاعدة بيانات أيضًا ، ثم إلغاء تحديدها (من جانب الخادم) ، وتحليلها والتحقق من وجود هجمات قبل عرضها في أي مكان آخر.

10
Jason Shuler

قم بتعطيل التحقق من صحة الصفحة إذا كنت حقًا بحاجة إلى أحرف خاصة مثل > و < ، إلخ. ثم تأكد من أنه عند عرض إدخال المستخدم ، تكون البيانات مشفرة بتنسيق HTML.

هناك ثغرة أمنية في التحقق من صحة الصفحة ، لذلك يمكن تجاوزها. أيضا لا ينبغي الاعتماد على التحقق من صحة الصفحة.

انظر: http://web.archive.org/web/20080913071637/http://www.procheckup.com:80/PDFs/bypassing-dot-NET-ValidateRequest.pdf

9
woany

السبب

يقوم ASP.NET افتراضيًا بالتحقق من صحة جميع عناصر التحكم في الإدخال للمحتويات التي قد تكون غير آمنة والتي يمكن أن تؤدي إلى برمجة نصية عبر المواقع (XSS) و حقن SQL . وبالتالي ، لا يسمح بهذا المحتوى عن طريق طرح الاستثناء أعلاه. بشكل افتراضي ، يوصى بالسماح بهذا الاختيار في كل إعادة النشر.

الحل

في العديد من المناسبات ، تحتاج إلى إرسال محتوى HTML إلى صفحتك من خلال Rich TextBoxes أو Rich Text Editors. في هذه الحالة ، يمكنك تجنب هذا الاستثناء عن طريق تعيين علامة ValidateRequest في توجيه @Page إلى false.

<%@ Page Language="C#" AutoEventWireup="true" ValidateRequest = "false" %>

سيؤدي هذا إلى تعطيل التحقق من صحة طلبات الصفحة التي قمت بتعيين علامة ValidateRequest على "خطأ". إذا كنت ترغب في تعطيل هذا ، تحقق من تطبيق الويب الخاص بك ؛ ستحتاج إلى تعيينه على "خطأ" في قسم web.config <system.web>

<pages validateRequest ="false" />

بالنسبة إلى .NET 4.0 أو الأطر الأعلى ، ستحتاج أيضًا إلى إضافة السطر التالي في قسم <system.web> لجعل العمل أعلاه.

<httpRuntime requestValidationMode = "2.0" />

هذا هو. آمل أن يكون هذا يساعدك في التخلص من القضية المذكورة أعلاه.

المرجع بواسطة: خطأ ASP.Net: تم اكتشاف قيمة Request.Form يحتمل أن تكون خطرة من العميل

9
vakeel

كنت أتلقى هذا الخطأ أيضًا.

في حالتي ، أدخل المستخدم حرفًا مشددًا á في اسم الدور (فيما يتعلق بموفر عضوية ASP.NET).

أقوم بتمرير اسم الدور إلى طريقة لمنح المستخدمين لهذا الدور وكان فشل طلب النشر $.ajax فشلاً ذريعًا ...

فعلت هذا لحل المشكلة:

بدلا من

data: { roleName: '@Model.RoleName', users: users }

افعل هذا

data: { roleName: '@Html.Raw(@Model.RoleName)', users: users }

@Html.Raw فعلت الحيلة.

كنت أحصل على اسم الدور كقيمة HTML roleName="Cadastro b&#225;s". تم حظر هذه القيمة مع كيان HTML &#225; بواسطة ASP.NET MVC. الآن أحصل على قيمة المعلمة roleName بالطريقة التي ينبغي أن تكون: roleName="Cadastro Básico" و ASP.NET MVC Engine لن يمنع الطلب بعد الآن.

9
Leniel Maccaferri

يمكنك أيضًا استخدام دالة JavaScript { Escape (string) لاستبدال الحروف الخاصة. ثم استخدم جانب الخادم Server . URLDecode (string) للتبديل مرة أخرى.

وبهذه الطريقة ، لا يتعين عليك إيقاف تشغيل التحقق من صحة الإدخال ، وسيكون من الواضح أكثر للمبرمجين الآخرين أن السلسلة قد تحتوي على محتوى HTML.

7
Trisped

انتهى بي الأمر باستخدام JavaScript قبل كل إعادة بحث للتحقق من الأحرف التي لا تريدها ، مثل:

<asp:Button runat="server" ID="saveButton" Text="Save" CssClass="saveButton" OnClientClick="return checkFields()" />

function checkFields() {
    var tbs = new Array();
    tbs = document.getElementsByTagName("input");
    var isValid = true;
    for (i=0; i<tbs.length; i++) {
        if (tbs(i).type == 'text') {
            if (tbs(i).value.indexOf('<') != -1 || tbs(i).value.indexOf('>') != -1) {
                alert('<> symbols not allowed.');
                isValid = false;
            }
        }
    }
    return isValid;
}

منحت صفحتي في الغالب إدخال البيانات ، وهناك عدد قليل جدًا من العناصر التي تقوم بإعادة النشر ، ولكن على الأقل يتم الاحتفاظ ببياناتها.

6
Ryan

طالما أن هذه فقط "<" و ">" (وليس الاقتباس المزدوج نفسه) أحرف وتستخدمها في سياق مثل <input value = "this" /> ، أنت آمن (أثناء استخدام <textarea> هذا واحد </textarea> ستكون عرضة بالطبع). قد يؤدي ذلك إلى تبسيط الموقف لديك ، ولكن مع أي شيء استخدم أكثر من أحد الحلول المنشورة الأخرى.

4
Paweł Hajdan

إذا كنت تبحث فقط لإخبار المستخدمين بأن <و> لن يتم استخدامهما ولكن ، لن ترغب في إعادة معالجة النموذج بالكامل/إعادة نشره (وفقدان جميع المدخلات) قبل ذلك ، هل يمكنك ببساطة عدم وضع المدقق في جميع أنحاء الميدان للكشف عن تلك الشخصيات (وربما غيرها من الشخصيات التي يحتمل أن تكون خطرة)؟

4
Captain Toad

يمكنك استخدام شيء مثل:

var nvc = Request.Unvalidated().Form;

في وقت لاحق ، يجب أن تعمل nvc["yourKey"].

4
Ady Levy

لا شيء من الاقتراحات عملت بالنسبة لي. لم أكن أرغب في إيقاف تشغيل هذه الميزة لموقع الويب بالكامل على أي حال لأن 99٪ من الوقت لا أريد للمستخدمين وضع HTML على نماذج الويب. لقد قمت للتو بإنشاء عملي الخاص حول الطريقة لأنني الوحيد الذي يستخدم هذا التطبيق المحدد. أقوم بتحويل الإدخال إلى HTML في الكود الموجود خلفه وأدخله في قاعدة البيانات الخاصة بي.

4
Mike S.

يمكنك تلقائيًا ترميز HTML في حقل Model Binder المخصص. حل بلدي مختلفة ، لقد وضعت خطأ في ModelState وعرض رسالة خطأ بالقرب من الميدان. من السهل تعديل هذا الرمز للتشفير تلقائيًا

 public class AppModelBinder : DefaultModelBinder
    {
        protected override object CreateModel(ControllerContext controllerContext, ModelBindingContext bindingContext, Type modelType)
        {
            try
            {
                return base.CreateModel(controllerContext, bindingContext, modelType);
            }
            catch (HttpRequestValidationException e)
            {
                HandleHttpRequestValidationException(bindingContext, e);
                return null; // Encode here
            }
        }
        protected override object GetPropertyValue(ControllerContext controllerContext, ModelBindingContext bindingContext,
            PropertyDescriptor propertyDescriptor, IModelBinder propertyBinder)
        {
            try
            {
                return base.GetPropertyValue(controllerContext, bindingContext, propertyDescriptor, propertyBinder);
            }
            catch (HttpRequestValidationException e)
            {
                HandleHttpRequestValidationException(bindingContext, e);
                return null; // Encode here
            }
        }

        protected void HandleHttpRequestValidationException(ModelBindingContext bindingContext, HttpRequestValidationException ex)
        {
            var valueProviderCollection = bindingContext.ValueProvider as ValueProviderCollection;
            if (valueProviderCollection != null)
            {
                ValueProviderResult valueProviderResult = valueProviderCollection.GetValue(bindingContext.ModelName, skipValidation: true);
                bindingContext.ModelState.SetModelValue(bindingContext.ModelName, valueProviderResult);
            }

            string errorMessage = string.Format(CultureInfo.CurrentCulture, "{0} contains invalid symbols: <, &",
                     bindingContext.ModelMetadata.DisplayName);

            bindingContext.ModelState.AddModelError(bindingContext.ModelName, errorMessage);
        }
    }

في Application_Start:

ModelBinders.Binders.DefaultBinder = new AppModelBinder();

لاحظ أنه يعمل فقط لحقول النموذج. لا يتم تمرير القيمة الخطرة إلى طراز وحدة التحكم ، ولكن يتم تخزينها في ModelState ويمكن إعادة عرضها على النموذج مع ظهور رسالة خطأ.

قد يتم التعامل مع الأحرف الخطرة في URL بهذه الطريقة:

private void Application_Error(object sender, EventArgs e)
{
    Exception exception = Server.GetLastError();
    HttpContext httpContext = HttpContext.Current;

    HttpException httpException = exception as HttpException;
    if (httpException != null)
    {
        RouteData routeData = new RouteData();
        routeData.Values.Add("controller", "Error");
        var httpCode = httpException.GetHttpCode();
        switch (httpCode)
        {
            case (int)HttpStatusCode.BadRequest /* 400 */:
                if (httpException.Message.Contains("Request.Path"))
                {
                    httpContext.Response.Clear();
                    RequestContext requestContext = new RequestContext(new HttpContextWrapper(Context), routeData);
                    requestContext.RouteData.Values["action"] ="InvalidUrl";
                    requestContext.RouteData.Values["controller"] ="Error";
                    IControllerFactory factory = ControllerBuilder.Current.GetControllerFactory();
                    IController controller = factory.CreateController(requestContext, "Error");
                    controller.Execute(requestContext);
                    httpContext.Server.ClearError();
                    Response.StatusCode = (int)HttpStatusCode.BadRequest /* 400 */;
                }
                break;
        }
    }
}

ErrorController:

public class ErrorController : Controller
 {
   public ActionResult InvalidUrl()
   {
      return View();
   }
}   
3
Sel

كما هو موضح في تعليقي على إجابة Sel ، هذا هو امتدادنا لمدقق الطلب المخصص.

public class SkippableRequestValidator : RequestValidator
{
    protected override bool IsValidRequestString(HttpContext context, string value, RequestValidationSource requestValidationSource, string collectionKey, out int validationFailureIndex)
    {
        if (collectionKey != null && collectionKey.EndsWith("_NoValidation"))
        {
            validationFailureIndex = 0;
            return true;
        }

        return base.IsValidRequestString(context, value, requestValidationSource, collectionKey, out validationFailureIndex);
    }
}
2
Walden Leverich

بالنسبة لأولئك الذين لا يستخدمون ربط النموذج ، والذين يستخرجون كل معلمة من Request.Form ، والذين يتأكدون من أن نص الإدخال لن يسبب أي ضرر ، فهناك طريقة أخرى. ليس حلاً رائعًا ولكنه سيؤدي المهمة.

من جانب العميل ، قم بترميزه كـ uri ثم أرسله.
منها مثلا:

encodeURIComponent($("#MsgBody").val());  

من جانب الخادم ، قم بقبوله وفك تشفيره كـ uri.
منها مثلا:

string temp = !string.IsNullOrEmpty(HttpContext.Current.Request.Form["MsgBody"]) ?
System.Web.HttpUtility.UrlDecode(HttpContext.Current.Request.Form["MsgBody"]) : 
null;  

أو

string temp = !string.IsNullOrEmpty(HttpContext.Current.Request.Form["MsgBody"]) ?
System.Uri.UnescapeDataString(HttpContext.Current.Request.Form["MsgBody"]) : 
null; 

الرجاء البحث عن الاختلافات بين UrlDecode و UnescapeDataString

2
Wahid Masud

يجب عليك استخدام أسلوب Server.HtmlEncode لحماية موقعك من الإدخال الخطير.

مزيد من المعلومات هنا

2
bastos.sergio

في حالتي ، باستخدام asp: عنصر تحكم مربع نص (Asp.net 4.5) ، بدلاً من تعيين الصفحة بالكامل لـ validateRequest="false" التي استخدمتها

<asp:TextBox runat="server" ID="mainTextBox"
            ValidateRequestMode="Disabled"
 ></asp:TextBox>

على مربع النص الذي تسبب في الاستثناء.

1
maozx

أخيرًا وليس آخرًا ، يرجى ملاحظة عناصر تحكم ربط بيانات ASP.NET تلقائيًا ترميز قيم أثناء ربط البيانات. هذا يغير السلوك الافتراضي لجميع عناصر تحكم ASP.NET (TextBox ، Label الخ) الموجودة في ItemTemplate. يوضح النموذج التالي (ValidateRequest معيَّنة إلى false):

aspx

<%@ Page Language="C#" ValidateRequest="false" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="WebApplication17._Default" %> <html> <body>
    <form runat="server">
        <asp:FormView ID="FormView1" runat="server" ItemType="WebApplication17.S" SelectMethod="FormView1_GetItem">
            <ItemTemplate>
                <asp:TextBox ID="TextBox1" runat="server"></asp:TextBox>
                <asp:Button ID="Button1" runat="server" Text="Button" OnClick="Button1_Click" />
                <asp:Label ID="Label1" runat="server" Text="<%#: Item.Text %>"></asp:Label>
                <asp:TextBox ID="TextBox2" runat="server" Text="<%#: Item.Text %>"></asp:TextBox>
            </ItemTemplate>
        </asp:FormView>
    </form> 

الكود خلف

public partial class _Default : Page
{
    S s = new S();

    protected void Button1_Click(object sender, EventArgs e)
    {
        s.Text = ((TextBox)FormView1.FindControl("TextBox1")).Text;
        FormView1.DataBind();
    }

    public S FormView1_GetItem(int? id)
    {
        return s;
    }
}

public class S
{
    public string Text { get; set; }
}
  1. قيمة إرسال الحالة: &#39;

قيمة Label1.Text: &#39;

قيمة TextBox2.Text: &amp;#39;

  1. حالة إرسال القيمة: <script>alert('attack!');</script>

قيمة Label1.Text: <script>alert('attack!');</script>

قيمة TextBox2.Text: &lt;script&gt;alert(&#39;attack!&#39;);&lt;/script&gt;

1
dpant

حل

لا أحب إيقاف تشغيل التحقق من صحة النشر (validateRequest = "false"). من ناحية أخرى ، من غير المقبول أن يتعطل التطبيق لمجرد أن المستخدم البريء يحدث لكتابة <x أو شيء ما.

لذلك كتبت وظيفة جافا سكريبت من جانب العميل (xssCheckValidates) التي تجعل الاختيار الأولي. تسمى هذه الوظيفة عندما تكون هناك محاولة لنشر بيانات النموذج ، مثل هذا:

<form id="form1" runat="server" onsubmit="return xssCheckValidates();">

الوظيفة بسيطة للغاية ويمكن تحسينها ولكنها تقوم بعملها.

يرجى ملاحظة أن الغرض من ذلك ليس حماية النظام من القرصنة ، بل يهدف إلى حماية المستخدمين من تجربة سيئة. لا يزال تشغيل التحقق من صحة الطلب على الخادم ، وهو (جزء من) حماية النظام (إلى الحد الذي يمكنه القيام به).

السبب في أنني أقول "جزء من" هنا هو أنني سمعت أن التحقق من صحة الطلب المدمج قد لا يكون كافياً ، لذلك قد تكون هناك حاجة إلى وسائل تكميلية أخرى للحصول على حماية كاملة. ولكن ، مرة أخرى ، فإن وظيفة javascript التي أقدمها هنا لها لا شيء تتعلق بحماية النظام. إنه فقط يعني التأكد من أن المستخدمين لن يتمتعوا بتجربة سيئة.

يمكنك تجربتها هنا:

    function xssCheckValidates() {
      var valid = true;
      var inp = document.querySelectorAll(
          "input:not(:disabled):not([readonly]):not([type=hidden])" +
          ",textarea:not(:disabled):not([readonly])");
      for (var i = 0; i < inp.length; i++) {
        if (!inp[i].readOnly) {
          if (inp[i].value.indexOf('<') > -1) {
            valid = false;
            break;
          }
          if (inp[i].value.indexOf('&#') > -1) {
            valid = false;
            break;
          }
        }
      }
      if (valid) {
        return true;
      } else {
        alert('In one or more of the text fields, you have typed\r\nthe character "<" or the character sequence "&#".\r\n\r\nThis is unfortunately not allowed since\r\nit can be used in hacking attempts.\r\n\r\nPlease edit the field and try again.');
        return false;
      }
    }
<form onsubmit="return xssCheckValidates();" >
  Try to type < or &# <br/>
  <input type="text" /><br/>
  <textarea></textarea>
  <input type="submit" value="Send" />
</form>
1
Magnus

بالنسبة لأولئك منا الذين ما زالوا عالقين في نماذج الويب ، وجدت الحل التالي الذي يمكنك من تعطيل التحقق من الصحة في حقل واحد فقط! (أكره تعطيله للصفحة بأكملها.)

VB.NET:

Public Class UnvalidatedTextBox
    Inherits TextBox
    Protected Overrides Function LoadPostData(postDataKey As String, postCollection As NameValueCollection) As Boolean
        Return MyBase.LoadPostData(postDataKey, System.Web.HttpContext.Current.Request.Unvalidated.Form)
    End Function
End Class

C #:

public class UnvalidatedTextBox : TextBox
{
    protected override bool LoadPostData(string postDataKey, NameValueCollection postCollection)
    {
        return base.LoadPostData(postDataKey, System.Web.HttpContext.Current.Request.Unvalidated.Form);
    }
}

الآن فقط استخدم <prefix:UnvalidatedTextBox id="test" runat="server" /> بدلاً من <asp:TextBox ، ويجب أن يسمح لجميع الأحرف (هذا مثالي لحقول كلمة المرور!)

1
Peter

أعلم أن هذا السؤال يتعلق بنشر النموذج ، لكنني أود أن أضيف بعض التفاصيل للأشخاص الذين تلقوا هذا الخطأ في ظروف الآخرين. يمكن أن تحدث أيضًا على معالج يستخدم لتنفيذ خدمة ويب.

افترض أن عميل الويب الخاص بك يرسل POST أو طلبات PUT باستخدام ajax ويرسل إما json أو xml نصًا أو بيانات أولية (محتوى ملف) إلى خدمة الويب الخاصة بك. نظرًا لأن خدمة الويب الخاصة بك لا تحتاج إلى الحصول على أي معلومات من رأس Content-Type ، فإن شفرة JavaScript الخاصة بك لم تقم بتعيين هذا الرأس على طلب ajax الخاص بك. ولكن إذا لم تقم بتعيين هذا الرأس على طلب أجاكس POST/PUT ، فقد تضيف Safari هذا العنوان: "Content-Type: application/x-www-form-urlencoded". لاحظت أنه في Safari 6 على iPhone ، ولكن قد تعمل إصدارات Safari الأخرى/OS أو Chrome على نفس الشيء. لذلك ، عند تلقي جزء Content-Type هذا ، يفترض جزء من .NET Framework أن بنية بيانات نص الطلب تتوافق مع نشر نموذج html بينما لا تقوم بذلك وتصدر استثناء HttpRequestValidationException. من الواضح أن أول ما يجب فعله هو تعيين رأس Content-Type دائمًا على أي شيء ما عدا نوع MIME للنموذج على طلب POST/PUT ajax حتى وإن كان غير مفيد لخدمة الويب الخاصة بك.

لقد اكتشفت هذه التفاصيل أيضًا:
في هذه الظروف ، يتم رفع استثناء HttpRequestValidationException عندما تحاول التعليمة البرمجية الوصول إلى مجموعة HttpRequest.Params. ولكن من المستغرب أن هذا الاستثناء لا يتم رفعه عندما يصل إلى مجموعة HttpRequest.ServerVariables. هذا يدل على أنه في حين أن هاتين المجموعتين يبدو أنهما متطابقتان تقريبًا ، يصل أحدهما إلى بيانات الطلب من خلال اختبارات الأمان والآخر لا يقوم بذلك.

1
figolu

في .Net 4.0 وما بعده ، وهو الحالة المعتادة ، ضع الإعداد التالي في system.web

<system.web>
     <httpRuntime requestValidationMode="2.0" />
1
Kiran Chaudhari

استخدم Server.HtmlEncode("yourtext");

0
Voigt

أرى أن هناك الكثير مكتوب حول هذا ... ولم أجد هذا مذكورًا. كان هذا متاحًا منذ .NET Framework 4.5

يعد ValidateRequestMode إعداد عنصر تحكم خيارًا رائعًا. بهذه الطريقة ، لا تزال عناصر التحكم الأخرى في الصفحة محمية. لا web.config التغييرات اللازمة.

 protected void Page_Load(object sender, EventArgs e)
    {
             txtMachKey.ValidateRequestMode = ValidateRequestMode.Disabled;
    }
0
Chris Catignani