it-swarm-id.com

Nilai Request.Form yang berpotensi berbahaya terdeteksi dari klien

Setiap kali pengguna memposting sesuatu yang mengandung < atau > di halaman dalam aplikasi web saya, saya mendapatkan pengecualian ini.

Saya tidak ingin membahas tentang kepintaran melempar pengecualian atau menabrak seluruh aplikasi web karena seseorang memasukkan karakter dalam kotak teks, tetapi saya mencari cara yang elegan untuk menangani hal ini.

Menjebak pengecualian dan tampil

Terjadi kesalahan, silakan kembali dan ketik ulang seluruh formulir Anda lagi, tapi kali ini jangan gunakan <

bagi saya sepertinya tidak cukup profesional.

Menonaktifkan validasi pos (validateRequest="false") pasti akan menghindari kesalahan ini, tetapi itu akan membuat halaman ini rentan terhadap sejumlah serangan.

Idealnya: Ketika sebuah posting kembali terjadi yang berisi karakter-karakter terbatas HTML, nilai yang diposkan dalam koleksi Formulir akan secara otomatis disandikan HTML . Jadi properti .Text dari kotak teks saya akan menjadi something & lt; html & gt;

Apakah ada cara saya bisa melakukan ini dari seorang pawang?

1379
Radu094

Saya pikir Anda menyerang dari sudut yang salah dengan mencoba menyandikan semua data yang diposting.

Perhatikan bahwa "<" juga dapat berasal dari sumber luar lainnya, seperti bidang basis data, konfigurasi, file, umpan, dan sebagainya. 

Lebih lanjut, "<" tidak inheren berbahaya. Ini hanya berbahaya dalam konteks tertentu: ketika menulis string yang belum dikodekan ke output HTML (karena XSS).

Dalam konteks lain, berbagai sub-string berbahaya, misalnya, jika Anda menulis URL yang disediakan pengguna ke dalam tautan, sub-string "javascript:" mungkin berbahaya. Karakter kutip tunggal di sisi lain berbahaya ketika interpolasi string dalam query SQL, tetapi sangat aman jika itu adalah bagian dari nama yang dikirimkan dari formulir atau dibaca dari bidang database.

Intinya adalah: Anda tidak dapat memfilter input acak untuk karakter berbahaya, karena karakter apa pun mungkin berbahaya dalam keadaan yang tepat. Anda harus menyandikan pada titik di mana beberapa karakter tertentu dapat menjadi berbahaya karena mereka masuk ke sub-bahasa yang berbeda di mana mereka memiliki makna khusus. Saat Anda menulis string ke HTML, Anda harus menyandikan karakter yang memiliki arti khusus dalam HTML, menggunakan Server.HtmlEncode. Jika Anda meneruskan string ke pernyataan SQL dinamis, Anda harus menyandikan karakter yang berbeda (atau lebih baik, biarkan kerangka melakukannya untuk Anda dengan menggunakan pernyataan yang disiapkan atau sejenisnya) ..

Ketika Anda yakin Anda meng-encode HTML di mana pun Anda mengirimkan string ke HTML, lalu atur validateRequest="false" dalam direktif <%@ Page ... %> dalam file .aspx Anda.

Di .NET 4 Anda mungkin perlu melakukan sedikit lagi. Terkadang perlu juga untuk menambahkan <httpRuntime requestValidationMode="2.0" /> ke web.config ( reference ).

1028
JacquesB

Ada solusi berbeda untuk kesalahan ini jika Anda menggunakan ASP.NET MVC:

C # sampel:

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

Sampel Visual Basic:

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

Dalam ASP.NET MVC (mulai dalam versi 3), Anda dapat menambahkan atribut AllowHtml ke properti pada model Anda.

Ini memungkinkan permintaan untuk memasukkan markup HTML selama pengikatan model dengan melewatkan validasi permintaan untuk properti.

[AllowHtml]
public string Description { get; set; }
384

Jika Anda menggunakan .NET 4.0 pastikan Anda menambahkan ini di file web.config Anda di dalam tag <system.web>:

<httpRuntime requestValidationMode="2.0" />

Di .NET 2.0, validasi permintaan hanya berlaku untuk permintaan aspx. Di .NET 4.0 ini diperluas untuk mencakup semua permintaan. Anda dapat kembali ke only melakukan validasi XSS saat memproses .aspx dengan menetapkan:

requestValidationMode="2.0"

Anda dapat menonaktifkan permintaan validasi seluruhnya dengan menetapkan:

validateRequest="false"
206
JordanC

Untuk ASP.NET 4.0, Anda dapat mengizinkan markup sebagai input untuk halaman tertentu dan bukan seluruh situs dengan meletakkan semuanya dalam elemen <location>. Ini akan memastikan semua halaman Anda lainnya aman. Anda TIDAK perlu memasukkan ValidateRequest="false" di halaman .aspx Anda.

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

Lebih aman untuk mengontrol ini di dalam web.config Anda, karena Anda bisa melihat di tingkat situs mana halaman memungkinkan markup sebagai input.

Anda masih perlu memvalidasi input pada halaman di mana validasi permintaan dinonaktifkan.

108
Carter Medlin

Jawaban sebelumnya sangat bagus, tetapi tidak ada yang mengatakan bagaimana mengecualikan satu bidang dari divalidasi untuk injeksi HTML/JavaScript. Saya tidak tahu tentang versi sebelumnya, tetapi dalam MVC3 Beta Anda dapat melakukan ini:

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

Ini masih memvalidasi semua bidang kecuali untuk yang dikecualikan. Yang menyenangkan tentang ini adalah bahwa atribut validasi Anda masih memvalidasi bidang, tetapi Anda hanya tidak mendapatkan "Permintaan yang berpotensi berbahaya. Nilai form terdeteksi dari klien" pengecualian.

Saya telah menggunakan ini untuk memvalidasi ekspresi reguler. Saya telah membuat ValidationAttribute saya sendiri untuk melihat apakah ekspresi reguler itu valid atau tidak. Karena ekspresi reguler dapat berisi sesuatu yang terlihat seperti skrip, saya menerapkan kode di atas - ekspresi reguler masih diperiksa apakah valid atau tidak, tetapi tidak jika itu berisi skrip atau HTML.

70
gligoran

Di ASP.NET MVC Anda perlu mengatur requestValidationMode = "2.0" dan validateRequest = "false" di web.config, dan menerapkan atribut ValidateInput ke tindakan controller Anda:

<httpRuntime requestValidationMode="2.0"/>

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

dan

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

Anda dapat menyandikan HTML isi kotak teks, tetapi sayangnya itu tidak akan menghentikan pengecualian terjadi. Dalam pengalaman saya tidak ada jalan keluar, dan Anda harus menonaktifkan validasi halaman. Dengan melakukan itu Anda berkata: "Aku akan berhati-hati, aku janji."

45
Pavel Chuchuva

Untuk MVC, abaikan validasi input dengan menambahkan 

[ValidateInput (false)]

di atas setiap Aksi di Controller.

42
A.Dara

Anda dapat menangkap kesalahan itu di Global.asax. Saya masih ingin memvalidasi, tetapi menunjukkan pesan yang sesuai. Di blog yang tercantum di bawah ini, sampel seperti ini tersedia. 

    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();
        }
    }

Mengarahkan kembali ke halaman lain juga sepertinya merupakan respons yang masuk akal terhadap pengecualian.

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

41
BenMaddox

Harap diingat bahwa beberapa kontrol .NET akan secara otomatis menyandikan output HTML. Misalnya, mengatur properti .Text pada kontrol TextBox akan secara otomatis menyandikannya. Itu secara khusus berarti mengubah < menjadi &lt;, > menjadi &gt; dan & menjadi &amp;. Jadi berhati-hatilah dalam melakukan ini ...

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

Namun, properti .Text untuk HyperLink, Literal dan Label tidak akan menyandikan hal-hal HTML, jadi bungkus Server.HtmlEncode (); sekitar apa pun yang diatur pada properti ini adalah suatu keharusan jika Anda ingin mencegah <script> window.location = "http://www.google.com"; </script> dari menjadi output ke halaman Anda dan kemudian dieksekusi.

Lakukan sedikit percobaan untuk melihat apa yang dikodekan dan apa yang tidak.

33
Dominic Pettifer

Jawaban atas pertanyaan ini sederhana:

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

Ini akan menonaktifkan validasi untuk permintaan tertentu.

31
flakomalo

Dalam file web.config, di dalam tag, masukkan elemen httpRuntime dengan atribut requestValidationMode = "2.0". Juga tambahkan atribut validateRequest = "false" di elemen halaman.

Contoh:

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

Jika Anda tidak ingin menonaktifkan ValidateRequest, Anda perlu menerapkan fungsi JavaScript untuk menghindari pengecualian. Ini bukan pilihan terbaik, tetapi berhasil.

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;
    }
}

Kemudian dalam kode di belakang, pada acara PageLoad, tambahkan atribut ke kontrol Anda dengan kode berikutnya:

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

Sepertinya belum ada yang menyebutkan di bawah ini, tetapi ini memperbaiki masalah untuk saya. Dan sebelum ada yang bilang ya itu Visual Basic ... huek.

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

Saya tidak tahu apakah ada kerugian, tetapi bagi saya ini bekerja luar biasa.

20
Piercy

Solusi lain adalah:

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;
    }
}
17
Sel

Jika Anda menggunakan framework 4.0 maka entri di web.config (<halaman validateRequest = "false" />)

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

Jika Anda menggunakan framework 4.5 maka entri di web.config (requestValidationMode = "2.0")

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

Jika Anda hanya menginginkan satu halaman saja, Dalam file aspx Anda, Anda harus meletakkan baris pertama seperti ini:

<%@ Page EnableEventValidation="false" %>

jika Anda sudah memiliki sesuatu seperti <% @ Halaman jadi tambahkan saja sisanya => EnableEventValidation="false"%>

Saya sarankan untuk tidak melakukannya.

14
Durgesh Pandey

Di ASP.NET, Anda dapat menangkap pengecualian dan melakukan sesuatu tentangnya, seperti menampilkan pesan ramah atau mengalihkan ke halaman lain ... Juga ada kemungkinan Anda dapat menangani validasinya sendiri ...

Tampilkan pesan ramah:

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

Saya kira Anda bisa melakukannya dalam modul; tetapi itu membuka beberapa pertanyaan; bagaimana jika Anda ingin menyimpan input ke database? Tiba-tiba karena Anda menyimpan data yang disandikan ke database Anda akhirnya percaya input dari itu yang mungkin merupakan ide yang buruk. Idealnya Anda menyimpan data mentah tanpa kode di dalam basis data dan penyandian setiap waktu.

Menonaktifkan proteksi pada level per halaman dan kemudian menyandikan setiap waktu adalah pilihan yang lebih baik.

Daripada menggunakan Server.HtmlEncode Anda harus melihat perpustakaan yang lebih baru, lebih lengkap Anti-XSS dari tim Microsoft ACE.

12
blowdart

Solusi lain di sini adalah Nice, namun itu sedikit sakit di bagian belakang harus menerapkan [AllowHtml] untuk setiap properti Model tunggal, terutama jika Anda memiliki lebih dari 100 model di situs berukuran layak.

Jika seperti saya, Anda ingin mematikan fitur (IMHO ini tidak berguna) di situs Anda dapat menimpa metode Execute () di pengontrol dasar Anda (jika Anda belum memiliki pengontrol basis, saya sarankan Anda membuatnya, mereka dapat cukup berguna untuk menerapkan fungsi umum).

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

Pastikan saja Anda meng-encode semua yang dipompa ke tampilan yang berasal dari input pengguna (itu adalah perilaku default dalam ASP.NET MVC 3 dengan Razor, jadi kecuali jika karena alasan aneh Anda menggunakan Html.Raw () Anda seharusnya tidak memerlukan fitur ini.

10
magritte

Nonaktifkan validasi halaman jika Anda benar-benar membutuhkan karakter khusus seperti, >, <, dll. Kemudian pastikan bahwa ketika input pengguna ditampilkan, data dikodekan dengan HTML. 

Ada kerentanan keamanan dengan validasi halaman, sehingga bisa dilewati. Validasi halaman juga tidak hanya bisa diandalkan.

Lihat: http://web.archive.org/web/20080913071637/http://www.procheckup.com:80/PDFs/bypassing-dot-NET-ValidateRequest.pdf

9
woany

Sebab

ASP.NET secara default memvalidasi semua kontrol input untuk konten yang berpotensi tidak aman yang dapat mengarah ke cross-site scripting (XSS) dan injeksi SQL . Dengan demikian ia melarang konten tersebut dengan melemparkan pengecualian di atas. Secara default, direkomendasikan untuk memungkinkan pemeriksaan ini terjadi pada setiap postback.

Solusi

Pada banyak kesempatan Anda perlu mengirimkan konten HTML ke halaman Anda melalui Rich TextBoxes atau Rich Text Editor. Jika demikian, Anda dapat menghindari pengecualian ini dengan mengatur tag ValidateRequest di arahan @Page menjadi false.

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

Ini akan menonaktifkan validasi permintaan untuk halaman yang Anda setel tanda ValidateRequest menjadi false. Jika Anda ingin menonaktifkan ini, periksa seluruh aplikasi web Anda; Anda harus menjadikannya false di bagian web.config <system.web> Anda

<pages validateRequest ="false" />

Untuk .NET 4.0 atau kerangka kerja yang lebih tinggi Anda harus menambahkan baris berikut di bagian <system.web> untuk membuat pekerjaan di atas.

<httpRuntime requestValidationMode = "2.0" />

Itu dia. Saya harap ini membantu Anda dalam menyingkirkan masalah di atas.

Referensi oleh: Kesalahan ASP.Net: Nilai Request.Form yang berpotensi berbahaya terdeteksi dari klien

9
vakeel

Saya menemukan solusi yang menggunakan JavaScript untuk menyandikan data, yang didekodekan dalam .NET (dan tidak memerlukan jQuery).

  • Jadikan kotak teks sebagai elemen HTML (seperti textarea) alih-alih yang ASP.
  • Tambahkan bidang yang tersembunyi.
  • Tambahkan fungsi JavaScript berikut ke tajuk Anda.

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

Di dalam textarea Anda, sertakan pertukaran yang memanggil boo ():

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

Akhirnya, dalam. NET, gunakan

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

Saya sadar ini satu arah - jika Anda perlu dua arah, Anda harus kreatif, tetapi ini memberikan solusi jika Anda tidak dapat mengedit web.config

Berikut ini adalah contoh yang saya (MC9000) buat dan gunakan melalui 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
    });


});

Dan markupnya:

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

Ini sangat bagus. Jika seorang hacker mencoba memposting melalui bypassing JavaScript, mereka hanya akan melihat kesalahannya. Anda dapat menyimpan semua data yang disandikan dalam basis data juga, lalu menghapusnya (di sisi server), dan menguraikan & memeriksa serangan sebelum ditampilkan di tempat lain.

9
Jason Shuler

Saya mendapatkan kesalahan ini juga.

Dalam kasus saya, pengguna memasukkan karakter beraksen á dalam Nama Peran (terkait penyedia keanggotaan ASP.NET).

Saya meneruskan nama peran ke metode untuk memberikan Pengguna peran itu dan permintaan posting $.ajax gagal total ...

Saya melakukan ini untuk memecahkan masalah:

Dari pada

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

Melakukan hal ini

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

@Html.Raw melakukan trik.

Saya mendapatkan nama Peran sebagai nilai HTML roleName="Cadastro b&#225;s". Nilai ini dengan entitas HTML &#225; sedang diblokir oleh ASP.NET MVC. Sekarang saya mendapatkan nilai parameter roleName seperti seharusnya: roleName="Cadastro Básico" dan mesin ASP.NET MVC tidak akan memblokir permintaan lagi.

9

Anda juga dapat menggunakan fungsi escape (string) JavaScript untuk mengganti karakter khusus. Kemudian sisi server menggunakan Server. URLDecode (string) untuk mengubahnya kembali.

Dengan cara ini Anda tidak perlu mematikan validasi input dan akan lebih jelas bagi programmer lain bahwa string mungkin memiliki konten HTML.

7
Trisped

Saya akhirnya menggunakan JavaScript sebelum setiap postback untuk memeriksa karakter yang tidak Anda inginkan, seperti:

<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;
}

Memang halaman saya sebagian besar entri data, dan ada sangat sedikit elemen yang melakukan postback, tetapi setidaknya data mereka dipertahankan.

6
Ryan

Selama ini adalah hanya "<" dan ">" (dan bukan kutipan ganda itu sendiri) karakter dan Anda menggunakannya dalam konteks seperti <input value = "this" />, Anda Aman (sementara untuk <textarea> yang ini </textarea> Anda tentu saja akan rentan). Itu dapat menyederhanakan situasi Anda, tetapi untuk apa pun lebih banyak gunakan salah satu solusi diposting lainnya.

4
Paweł Hajdan

Jika Anda hanya ingin memberi tahu pengguna Anda bahwa <dan> tidak boleh digunakan TETAPI, Anda tidak ingin seluruh formulir diproses/diposting kembali (dan kehilangan semua input) sebelumnya, bisakah Anda tidak dengan mudah memasukkan validator di sekitar lapangan untuk menyaring karakter (dan mungkin karakter berbahaya lainnya) yang lain?

4
Captain Toad

Anda dapat menggunakan sesuatu seperti:

var nvc = Request.Unvalidated().Form;

Nantinya, nvc["yourKey"] akan berfungsi.

4
Ady Levy

Tidak ada saran yang bekerja untuk saya. Saya tidak ingin mematikan fitur ini untuk seluruh situs web karena 99% waktu saya tidak ingin pengguna saya menempatkan HTML di formulir web. Saya baru saja membuat pekerjaan saya sendiri di sekitar metode karena saya satu-satunya yang menggunakan aplikasi khusus ini. Saya mengonversi input ke HTML dalam kode di belakang dan memasukkannya ke database saya.

4
Mike S.

Anda dapat secara otomatis menyandikan bidang HTML di Pengikat Model kustom. Solusi saya agak berbeda, saya menempatkan kesalahan pada ModelState dan menampilkan pesan kesalahan di dekat bidang. Sangat mudah untuk memodifikasi kode ini untuk disandikan secara otomatis 

 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);
        }
    }

Di Application_Start:

ModelBinders.Binders.DefaultBinder = new AppModelBinder();

Perhatikan bahwa ini hanya berfungsi untuk bidang formulir. Nilai berbahaya tidak diteruskan ke model controller, tetapi disimpan dalam ModelState dan dapat ditampilkan kembali pada formulir dengan pesan kesalahan. 

Karakter berbahaya dalam URL dapat ditangani dengan cara ini:

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

Anda harus menggunakan metode Server.HtmlEncode untuk melindungi situs Anda dari input berbahaya.

Info lebih lanjut di sini

3
bastos.sergio

Seperti yang ditunjukkan dalam komentar saya ke Jawaban Sel , ini adalah ekstensi kami ke validator permintaan khusus.

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

Bagi mereka yang tidak menggunakan pengikatan model, yang mengekstraksi setiap parameter dari Request.Form, yang yakin teks input tidak akan membahayakan, ada cara lain. Bukan solusi yang bagus tetapi akan melakukan pekerjaan. 

Dari sisi klien, disandikan sebagai uri lalu kirim.
misalnya: 

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

Dari sisi server, terima dan dekode sebagai uri.
misalnya: 

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

atau 

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

tolong cari perbedaan antara UrlDecode dan UnescapeDataString

2
Wahid Masud

Last but not least, harap diperhatikan ASP.NET Data Binding mengontrol secara otomatis encode nilai selama pengikatan data. Ini mengubah perilaku default semua kontrol ASP.NET (TextBox, Label dll) yang terkandung dalam ItemTemplate. Contoh berikut menunjukkan (ValidateRequest disetel ke 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> 

kode di belakang

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. Nilai pengiriman case: &#39;

Nilai Label1.Text: &#39;

Nilai TextBox2.Text: &amp;#39;

  1. Nilai pengiriman case: <script>alert('attack!');</script>

Nilai Label1.Text: <script>alert('attack!');</script>

Nilai TextBox2.Text: &lt;script&gt;alert(&#39;attack!&#39;);&lt;/script&gt;

1
dpant

Bagi kita yang masih terjebak pada formulir web, saya menemukan solusi berikut yang memungkinkan Anda untuk hanya menonaktifkan validasi pada satu bidang! (Saya tidak suka menonaktifkannya untuk seluruh halaman.)

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);
    }
}

Sekarang cukup gunakan <prefix:UnvalidatedTextBox id="test" runat="server" /> alih-alih <asp:TextBox, dan itu harus memungkinkan semua karakter (ini sempurna untuk bidang kata sandi!)

1
Peter

Saya tahu pertanyaan ini adalah tentang pengiriman formulir, tetapi saya ingin menambahkan beberapa detail untuk orang-orang yang menerima kesalahan ini pada keadaan lain. Itu juga bisa terjadi pada penangan yang digunakan untuk mengimplementasikan layanan web. 

Misalkan klien web Anda mengirim POST atau permintaan PUT menggunakan ajax dan mengirimkan teks json atau xml atau data mentah (konten file) ke layanan web Anda. Karena layanan web Anda tidak perlu mendapatkan informasi dari header Tipe-Konten, kode JavaScript Anda tidak mengatur header ini untuk permintaan ajax Anda. Tetapi jika Anda tidak menyetel tajuk ini pada permintaan ajax POST/PUT, Safari dapat menambahkan tajuk ini: "Content-Type: application/x-www-form-urlencoded". Saya mengamati bahwa pada Safari 6 di iPhone, tetapi yang lain Safari versi/OS atau Chrome dapat melakukan hal yang sama. Jadi ketika menerima header Jenis-Konten ini, beberapa bagian dari .NET Framework menganggap struktur data badan permintaan sesuai dengan postingan formulir html sementara itu tidak dan naik pengecualian HttpRequestValidationException. Hal pertama yang harus dilakukan adalah jelas untuk selalu mengatur header Tipe-Konten ke apa pun selain bentuk tipe MIME pada permintaan ajax POST/PUT bahkan tidak berguna untuk layanan web Anda.

Saya juga menemukan detail ini:
Pada keadaan ini, pengecualian HttpRequestValidationException naik ketika kode Anda mencoba mengakses koleksi HttpRequest.Params. Tapi yang mengejutkan, pengecualian ini tidak naik ketika mengakses koleksi HttpRequest.ServerVariables. Ini menunjukkan bahwa sementara dua koleksi ini tampaknya hampir identik, satu mengakses data permintaan melalui pemeriksaan keamanan dan yang lainnya tidak.

1
figolu

Di .Net 4.0 dan selanjutnya, yang merupakan kasus biasa, masukkan pengaturan berikut di system.web

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

dalam kasus saya, menggunakan asp: Kontrol kotak teks (Asp.net 4.5), alih-alih mengatur semua halaman untuk validateRequest="false" Saya menggunakan 

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

pada Textbox yang menyebabkan pengecualian.

0
maozx

Sebuah solusi

Saya tidak suka mematikan validasi pos (validateRequest = "false"). Di sisi lain tidak dapat diterima bahwa aplikasi mogok hanya karena pengguna yang tidak bersalah kebetulan mengetik <x atau sesuatu. 

Oleh karena itu saya menulis fungsi javascript sisi klien (xssCheckValidates) yang melakukan pemeriksaan pendahuluan. Fungsi ini dipanggil ketika ada upaya untuk memposting data formulir, seperti ini:

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

Fungsi ini cukup sederhana dan dapat ditingkatkan tetapi melakukan tugasnya.

Harap perhatikan bahwa tujuan dari ini bukan untuk melindungi sistem dari peretasan, ini dimaksudkan untuk melindungi pengguna dari pengalaman buruk. Validasi permintaan yang dilakukan di server masih dinyalakan, dan itu adalah (bagian dari) perlindungan sistem (sejauh itu mampu melakukan itu). 

Alasan saya mengatakan "bagian dari" di sini adalah karena saya telah mendengar bahwa validasi permintaan bawaan mungkin tidak cukup, sehingga cara pelengkap lainnya mungkin diperlukan untuk memiliki perlindungan penuh. Tetapi, sekali lagi, fungsi javascript yang saya sajikan di sini memiliki tidak ada yang berkaitan dengan melindungi sistem. Ini hanya dimaksudkan untuk memastikan pengguna tidak akan memiliki pengalaman buruk.

Anda dapat mencobanya di sini:

    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>

0
Magnus

Gunakan Server.HtmlEncode("yourtext");

0
Voigt

Saya melihat ada banyak yang ditulis tentang ini ... dan saya tidak melihat ini disebutkan . Ini telah tersedia sejak .NET Framework 4.5

Pengaturan ValidateRequestMode untuk kontrol adalah pilihan yang bagus . Dengan cara ini kontrol lain pada halaman masih terlindungi. Tidak perlu perubahan web.config.

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