it-swarm-vi.tech

Một giá trị Request.Form nguy hiểm tiềm tàng đã được phát hiện từ máy khách

Mỗi khi người dùng đăng một cái gì đó có chứa < hoặc > trong một trang trong ứng dụng web của tôi, tôi sẽ bị ném ngoại lệ này.

Tôi không muốn đi vào cuộc thảo luận về sự thông minh của việc ném một ngoại lệ hoặc làm hỏng toàn bộ ứng dụng web vì ai đó đã nhập một ký tự vào hộp văn bản, nhưng tôi đang tìm một cách thanh lịch để xử lý việc này.

Bẫy ngoại lệ và hiển thị

Đã xảy ra lỗi, vui lòng quay lại và nhập lại toàn bộ biểu mẫu của bạn, nhưng lần này vui lòng không sử dụng <

dường như không đủ chuyên nghiệp với tôi.

Vô hiệu hóa xác thực bài đăng (validateRequest="false") chắc chắn sẽ tránh được lỗi này, nhưng nó sẽ khiến trang dễ bị tấn công.

Lý tưởng nhất: Khi một bài đăng trở lại có chứa các ký tự bị giới hạn HTML, giá trị được đăng trong bộ sưu tập Biểu mẫu sẽ được mã hóa HTML tự động . Vì vậy, thuộc tính .Text của hộp văn bản của tôi sẽ là something & lt; html & gt;

Có cách nào tôi có thể làm điều này từ một người xử lý?

1379
Radu094

Tôi nghĩ rằng bạn đang tấn công nó từ góc độ sai bằng cách cố gắng mã hóa tất cả dữ liệu được đăng.

Lưu ý rằng "<" cũng có thể đến từ các nguồn bên ngoài khác, như trường cơ sở dữ liệu, cấu hình, tệp, nguồn cấp dữ liệu, v.v. 

Hơn nữa, "<" vốn không nguy hiểm. Nó chỉ nguy hiểm trong một ngữ cảnh cụ thể: khi viết các chuỗi chưa được mã hóa thành đầu ra HTML (vì XSS).

Trong các bối cảnh khác, các chuỗi con khác nhau rất nguy hiểm, ví dụ: nếu bạn viết URL do người dùng cung cấp vào một liên kết, chuỗi phụ "javascript:" có thể nguy hiểm. Mặt khác, ký tự trích dẫn là nguy hiểm khi nội suy các chuỗi trong các truy vấn SQL, nhưng hoàn toàn an toàn nếu đó là một phần của tên được gửi từ một biểu mẫu hoặc đọc từ trường cơ sở dữ liệu.

Điểm mấu chốt là: bạn không thể lọc đầu vào ngẫu nhiên cho các ký tự nguy hiểm, bởi vì bất kỳ ký tự nào cũng có thể nguy hiểm trong các trường hợp phù hợp. Bạn nên mã hóa tại điểm mà một số ký tự cụ thể có thể trở nên nguy hiểm vì chúng chuyển sang một ngôn ngữ phụ khác, nơi chúng có ý nghĩa đặc biệt. Khi bạn viết một chuỗi thành HTML, bạn nên mã hóa các ký tự có ý nghĩa đặc biệt trong HTML, sử dụng Server.HtmlEncode. Nếu bạn chuyển một chuỗi cho một câu lệnh SQL động, bạn nên mã hóa các ký tự khác nhau (hoặc tốt hơn, hãy để khung làm việc đó cho bạn bằng cách sử dụng các câu lệnh đã chuẩn bị hoặc tương tự) ..

Khi bạn chắc chắn rằng bạn đã mã hóa HTML ở mọi nơi bạn chuyển chuỗi sang HTML, sau đó đặt validateRequest="false" trong lệnh <%@ Page ... %> trong (các) tệp .aspx của bạn.

Trong .NET 4 bạn có thể cần phải làm nhiều hơn một chút. Đôi khi, cũng cần thêm <httpRuntime requestValidationMode="2.0" /> vào web.config ( tham chiếu ).

1028
JacquesB

Có một giải pháp khác cho lỗi này nếu bạn đang sử dụng ASP.NET MVC:

Mẫu C #:

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

Mẫu Visual Basic:

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

Trong ASP.NET MVC (bắt đầu từ phiên bản 3), bạn có thể thêm thuộc tính AllowHtml vào một thuộc tính trên mô hình của bạn.

Nó cho phép một yêu cầu bao gồm đánh dấu HTML trong quá trình ràng buộc mô hình bằng cách bỏ qua xác thực yêu cầu cho thuộc tính.

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

Nếu bạn đang dùng .NET 4.0, hãy đảm bảo bạn thêm tệp này vào tệp web.config bên trong các thẻ <system.web>:

<httpRuntime requestValidationMode="2.0" />

Trong .NET 2.0, xác thực yêu cầu chỉ được áp dụng cho các yêu cầu aspx. Trong .NET 4.0, điều này đã được mở rộng để bao gồm tất cả yêu cầu. Bạn có thể hoàn nguyên về chỉ thực hiện xác thực XSS khi xử lý .aspx bằng cách chỉ định:

requestValidationMode="2.0"

Bạn có thể vô hiệu hóa yêu cầu xác thực hoàn toàn bằng cách chỉ định:

validateRequest="false"
206
JordanC

Đối với ASP.NET 4.0, bạn có thể cho phép đánh dấu làm đầu vào cho các trang cụ thể thay vì toàn bộ trang bằng cách đặt tất cả trong phần tử <location>. Điều này sẽ đảm bảo tất cả các trang khác của bạn được an toàn. Bạn KHÔNG cần phải đặt ValidateRequest="false" trong trang .aspx của mình.

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

Việc kiểm soát điều này trong web.config sẽ an toàn hơn, bởi vì bạn có thể thấy ở cấp độ trang web cho phép đánh dấu là đầu vào.

Bạn vẫn cần xác thực lập trình nhập liệu trên các trang nơi xác thực yêu cầu bị vô hiệu hóa.

108
Carter Medlin

Các câu trả lời trước đây rất hay, nhưng không ai nói làm thế nào để loại trừ một trường duy nhất khỏi bị xác thực cho việc tiêm HTML/JavaScript. Tôi không biết về các phiên bản trước, nhưng trong MVC3 Beta, bạn có thể làm điều này:

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

Điều này vẫn xác nhận tất cả các trường ngoại trừ trường bị loại trừ. Điều thú vị ở đây là các thuộc tính xác thực của bạn vẫn xác thực trường, nhưng bạn không nhận được ngoại lệ "Giá trị Request.Form nguy hiểm tiềm tàng được phát hiện từ máy khách".

Tôi đã sử dụng điều này để xác nhận một biểu thức chính quy. Tôi đã tạo Xác thực hợp lệ của riêng mình để xem biểu thức chính quy có hợp lệ hay không. Vì các biểu thức thông thường có thể chứa một cái gì đó trông giống như một tập lệnh mà tôi đã áp dụng đoạn mã trên - biểu thức chính quy vẫn đang được kiểm tra xem nó có hợp lệ hay không, nhưng không phải nếu nó chứa tập lệnh hoặc HTML.

70
gligoran

Trong ASP.NET MVC, bạn cần đặt requestValidationMode = "2.0" và validateRequest = "false" trong web.config và áp dụng thuộc tính ValidateInput cho hành động điều khiển của bạn:

<httpRuntime requestValidationMode="2.0"/>

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

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

Bạn có thể HTML mã hóa nội dung hộp văn bản, nhưng thật không may, điều đó sẽ không ngăn chặn ngoại lệ xảy ra. Theo kinh nghiệm của tôi, không có cách nào khác, và bạn phải vô hiệu hóa xác nhận trang. Bằng cách làm điều đó bạn đang nói: "Tôi sẽ cẩn thận, tôi hứa."

45
Pavel Chuchuva

Đối với MVC, bỏ qua xác thực đầu vào bằng cách thêm 

[ValidateInput (sai)]

phía trên mỗi hành động trong Bộ điều khiển.

42
A.Dara

Bạn có thể bắt lỗi đó trong Global.asax. Tôi vẫn muốn xác nhận, nhưng hiển thị một thông điệp thích hợp. Trên blog được liệt kê dưới đây, một mẫu như thế này đã có sẵn. 

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

Chuyển hướng đến một trang khác cũng có vẻ như là một phản ứng hợp lý cho ngoại lệ.

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

41
BenMaddox

Xin lưu ý rằng một số điều khiển .NET sẽ tự động mã hóa HTML đầu ra. Chẳng hạn, đặt thuộc tính .Text trên điều khiển TextBox sẽ tự động mã hóa nó. Điều đó đặc biệt có nghĩa là chuyển đổi < thành &lt;, > thành &gt;& thành &amp;. Vì vậy, hãy cảnh giác khi làm điều này ...

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

Tuy nhiên, thuộc tính .Text cho HyperLink, Literal và Label sẽ không mã hóa mọi thứ HTML, do đó, bao bọc Server.HtmlEncode (); xung quanh bất cứ điều gì được đặt trên các thuộc tính này là bắt buộc nếu bạn muốn ngăn <script> window.location = "http://www.google.com"; </script> xuất ra trang của mình và sau đó được thực thi.

Làm một thử nghiệm nhỏ để xem những gì được mã hóa và những gì không.

33
Dominic Pettifer

Câu trả lời cho câu hỏi này là đơn giản:

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

Điều này sẽ vô hiệu hóa xác nhận cho các yêu cầu cụ thể.

31
flakomalo

Trong tệp web.config, trong các thẻ, chèn phần tử httpR.78 với thuộc tính requestValidationMode = "2.0". Đồng thời thêm thuộc tính validateRequest = "false" trong phần tử trang.

Thí dụ:

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

Nếu bạn không muốn vô hiệu hóa ValidateRequest, bạn cần triển khai hàm JavaScript để tránh ngoại lệ. Nó không phải là lựa chọn tốt nhất, nhưng nó hoạt động.

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

Sau đó, trong mã phía sau, trên sự kiện PageLoad, hãy thêm thuộc tính vào điều khiển của bạn bằng mã tiếp theo:

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

Có vẻ như chưa có ai đề cập đến những điều dưới đây, nhưng nó đã khắc phục vấn đề cho tôi. Và trước khi bất cứ ai nói vâng, đó là Visual Basic ... yuck.

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

Tôi không biết nếu có bất kỳ nhược điểm nào, nhưng đối với tôi điều này đã làm việc tuyệt vời.

20
Piercy

Một giải pháp khác là:

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

Nếu bạn đang sử dụng khung 4.0 thì mục nhập trong web.config (<PagesterateRequest = "false" />)

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

Nếu bạn đang sử dụng framework 4.5 thì mục trong web.config (requestValidationMode = "2.0")

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

Nếu bạn chỉ muốn một trang duy nhất, Trong tệp aspx của bạn, bạn nên đặt dòng đầu tiên như sau:

<%@ Page EnableEventValidation="false" %>

nếu bạn đã có một cái gì đó như <% @ Trang, vì vậy chỉ cần thêm phần còn lại => EnableEventValidation="false"%>

Tôi khuyên bạn không nên làm điều đó.

14
Durgesh Pandey

Trong ASP.NET, bạn có thể bắt ngoại lệ và thực hiện điều gì đó về nó, chẳng hạn như hiển thị thông báo thân thiện hoặc chuyển hướng đến một trang khác ... Ngoài ra, có khả năng bạn có thể tự xử lý xác thực ...

Hiển thị tin nhắn thân thiện:

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

Tôi đoán bạn có thể làm điều đó trong một mô-đun; nhưng điều đó để lại một số câu hỏi; Điều gì nếu bạn muốn lưu đầu vào vào cơ sở dữ liệu? Đột nhiên vì bạn đang lưu dữ liệu được mã hóa vào cơ sở dữ liệu nên cuối cùng bạn tin tưởng đầu vào từ đó có lẽ là một ý tưởng tồi. Lý tưởng nhất là bạn lưu trữ dữ liệu chưa được mã hóa thô trong cơ sở dữ liệu và mã hóa mỗi lần.

Vô hiệu hóa bảo vệ ở cấp độ trên mỗi trang và sau đó mã hóa mỗi lần là một lựa chọn tốt hơn.

Thay vì sử dụng Server.HtmlEncode, bạn nên xem thư viện mới hơn, đầy đủ hơn Anti-XSS từ nhóm Microsoft ACE.

12
blowdart

Các giải pháp khác ở đây là Nice, tuy nhiên, phía sau phải áp dụng [AllowHtml] cho mọi thuộc tính Model, đặc biệt là nếu bạn có hơn 100 mô hình trên một trang web có kích thước khá.

Nếu giống như tôi, bạn muốn tắt tính năng này (IMHO khá vô nghĩa) khỏi trang web rộng, bạn có thể ghi đè phương thức Execute () trong bộ điều khiển cơ sở của bạn (nếu bạn chưa có bộ điều khiển cơ bản tôi khuyên bạn nên tạo một, chúng có thể khá hữu ích cho việc áp dụng các chức năng phổ biến).

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

Chỉ cần đảm bảo rằng bạn đang mã hóa HTML mọi thứ được đưa ra cho các lượt xem xuất phát từ đầu vào của người dùng (dù sao đó là hành vi mặc định trong ASP.NET MVC 3 với Dao cạo, vì vậy trừ khi vì một lý do kỳ quái nào đó bạn đang sử dụng Html.Raw () không nên yêu cầu tính năng này.

10
magritte

Vô hiệu hóa xác thực trang nếu bạn thực sự cần các ký tự đặc biệt như, > , <, v.v. Sau đó, đảm bảo rằng khi đầu vào của người dùng được hiển thị, dữ liệu được mã hóa HTML. 

Có một lỗ hổng bảo mật với xác nhận trang, vì vậy nó có thể được bỏ qua. Ngoài ra, xác nhận trang không nên chỉ dựa vào.

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

9
woany

Nguyên nhân

ASP.NET theo mặc định xác nhận tất cả các điều khiển đầu vào cho các nội dung có khả năng không an toàn có thể dẫn đến kịch bản chéo trang (XSS) và SQL tiêm . Do đó, nó không cho phép nội dung như vậy bằng cách ném ngoại lệ trên. Theo mặc định, nên cho phép kiểm tra này xảy ra trên mỗi postback.

Dung dịch

Trong nhiều trường hợp, bạn cần gửi nội dung HTML đến trang của mình thông qua Rich TextBoxes hoặc Rich Text Editorors. Trong trường hợp đó, bạn có thể tránh ngoại lệ này bằng cách đặt thẻ ValidateRequest trong chỉ thị @Page thành false.

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

Điều này sẽ vô hiệu hóa xác thực các yêu cầu cho trang bạn đã đặt cờ ValidateRequest thành false. Nếu bạn muốn vô hiệu hóa điều này, hãy kiểm tra trong suốt ứng dụng web của bạn; bạn cần phải đặt nó thành false trong phần web.config <system.web> của bạn

<pages validateRequest ="false" />

Đối với các khung công tác .NET 4.0 trở lên, bạn cũng cần thêm dòng sau vào phần <system.web> để thực hiện công việc trên.

<httpRuntime requestValidationMode = "2.0" />

Đó là nó. Tôi hy vọng điều này sẽ giúp bạn trong việc thoát khỏi vấn đề trên.

Tham chiếu bởi: Lỗi ASP.Net: Giá trị Request.Form nguy hiểm tiềm tàng được phát hiện từ máy khách

9
vakeel

Tôi đã tìm thấy một giải pháp sử dụng JavaScript để mã hóa dữ liệu, được giải mã bằng .NET (và không yêu cầu jQuery).

  • Biến hộp văn bản thành một phần tử HTML (như textarea) thay vì ASP.
  • Thêm một trường ẩn.
  • Thêm chức năng JavaScript sau vào tiêu đề của bạn.

    hàm boo () { targetText = document.getEuityById ("HiddenField1"); sourceText = document.getEuityById ("hộp người dùng"); targetText.value = esc (sourceText.innerText); }

Trong textarea của bạn, bao gồm một onchange gọi boo ():

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

Cuối cùng, trong .NET, sử dụng

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

Tôi biết rằng đây là một chiều - nếu bạn cần hai chiều, bạn sẽ phải sáng tạo, nhưng điều này cung cấp giải pháp nếu bạn không thể chỉnh sửa web.config

Đây là một ví dụ tôi (MC9000) đã đưa ra và sử dụng thông qua 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
    });


});

Và đánh dấu:

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

Điều này làm việc tuyệt vời. Nếu một hacker cố gắng đăng bài thông qua bỏ qua JavaScript, họ sẽ chỉ thấy lỗi. Bạn cũng có thể lưu tất cả dữ liệu được mã hóa trong cơ sở dữ liệu, sau đó hủy bỏ nó (ở phía máy chủ) và phân tích & kiểm tra các cuộc tấn công trước khi hiển thị ở nơi khác.

9
Jason Shuler

Tôi đã nhận được lỗi này quá.

Trong trường hợp của tôi, một người dùng đã nhập một ký tự có dấu á trong Tên vai trò (liên quan đến nhà cung cấp thành viên ASP.NET).

Tôi chuyển tên vai trò cho một phương thức để cấp cho Người dùng vai trò đó và yêu cầu bài đăng $.ajax đã thất bại thảm hại ...

Tôi đã làm điều này để giải quyết vấn đề:

Thay vì

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

Làm cái này

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

@Html.Raw đã lừa.

Tôi đã nhận được tên Vai trò là giá trị HTML roleName="Cadastro b&#225;s". Giá trị này với thực thể HTML &#225; đã bị ASP.NET MVC chặn. Bây giờ tôi nhận được giá trị tham số roleName theo cách nó phải là: roleName="Cadastro Básico" và công cụ ASP.NET MVC sẽ không chặn yêu cầu nữa.

9
Leniel Maccaferri

Bạn cũng có thể sử dụng chức năng esc (chuỗi) của JavaScript để thay thế các ký tự đặc biệt. Sau đó, phía máy chủ sử dụng Server. URLDecode (chuỗi) để chuyển đổi lại.

Bằng cách này, bạn không phải tắt xác thực đầu vào và sẽ rõ ràng hơn với các lập trình viên khác rằng chuỗi có thể có nội dung HTML.

7
Trisped

Tôi đã kết thúc việc sử dụng JavaScript trước mỗi lần đăng lại để kiểm tra các ký tự bạn không muốn, chẳng hạn như:

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

Cấp cho trang của tôi chủ yếu là nhập dữ liệu và có rất ít yếu tố thực hiện postback, nhưng ít nhất dữ liệu của họ được giữ lại.

6
Ryan

Miễn là đây là các ký tự chỉ "<" và ">" (chứ không phải là dấu ngoặc kép) và bạn đang sử dụng chúng trong ngữ cảnh như <input value = "this" /> 'an toàn (trong khi đối với <textarea> cái này </ textarea> bạn sẽ dễ bị tổn thương). Điều đó có thể đơn giản hóa tình huống của bạn, nhưng đối với bất cứ điều gì nhiều hơn hãy sử dụng một trong những giải pháp được đăng khác.

4
Paweł Hajdan

Nếu bạn chỉ muốn nói với người dùng của mình rằng <và> không được sử dụng NHƯNG, bạn không muốn toàn bộ biểu mẫu được xử lý/đăng lại (và mất tất cả đầu vào) trước đó, bạn không thể đơn giản đặt trình xác nhận xung quanh trường để sàng lọc các ký tự đó (và có thể nguy hiểm khác)?

4
Captain Toad

Bạn có thể sử dụng một cái gì đó như:

var nvc = Request.Unvalidated().Form;

Sau đó, nvc["yourKey"] sẽ hoạt động.

4
Ady Levy

Không có gợi ý nào làm việc cho tôi. Dù sao tôi cũng không muốn tắt tính năng này cho toàn bộ trang web vì 99% tôi không muốn người dùng của mình đặt HTML trên các biểu mẫu web. Tôi chỉ tạo ra công việc của riêng mình xung quanh phương pháp vì tôi là người duy nhất sử dụng ứng dụng cụ thể này. Tôi chuyển đổi đầu vào thành HTML trong mã phía sau và chèn nó vào cơ sở dữ liệu của tôi.

4
Mike S.

Bạn có thể tự động mã hóa trường HTML trong Binder Model tùy chỉnh. Giải pháp của tôi khác, tôi đặt lỗi trong ModelState và hiển thị thông báo lỗi gần trường. Thật dễ dàng để sửa đổi mã này để tự động mã hóa 

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

Trong Application_Start:

ModelBinders.Binders.DefaultBinder = new AppModelBinder();

Lưu ý rằng nó chỉ hoạt động cho các trường mẫu. Giá trị nguy hiểm không được chuyển cho mô hình bộ điều khiển, nhưng được lưu trữ trong ModelState và có thể được hiển thị lại trên biểu mẫu với thông báo lỗi. 

Các ký tự nguy hiểm trong URL có thể được xử lý theo cách này:

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

Lỗi kiểm soát: 

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

Bạn nên sử dụng phương pháp Server.HtmlEncode để bảo vệ trang web của bạn khỏi đầu vào nguy hiểm.

Thêm thông tin ở đây

3
bastos.sergio

Như đã nêu trong nhận xét của tôi về Câu trả lời của Sel , đây là phần mở rộng của chúng tôi cho trình xác nhận yêu cầu tùy chỉnh.

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

Đối với những người không sử dụng liên kết mô hình, những người đang trích xuất từng tham số từ Request.Form, những người chắc chắn văn bản đầu vào sẽ không gây hại, có một cách khác. Không phải là một giải pháp tuyệt vời nhưng nó sẽ làm công việc. 

Từ phía khách hàng, mã hóa nó thành uri sau đó gửi nó.
ví dụ: 

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

Từ phía máy chủ, chấp nhận nó và giải mã nó là uri.
ví dụ: 

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

hoặc là 

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

vui lòng tìm sự khác biệt giữa UrlDecodeUnescapeDataString

2
Wahid Masud

Cuối cùng nhưng không kém phần quan trọng, xin lưu ý các điều khiển Binding Data ASP.NET tự động encode value trong khi liên kết dữ liệu. Điều này thay đổi hành vi mặc định của tất cả các điều khiển ASP.NET (TextBox, Label, v.v.) có trong ItemTemplate. Mẫu sau đây chứng minh (ValidateRequest được đặt thành 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> 

mã ẩn

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. Giá trị gửi trường hợp: &#39;

Label1.Text giá trị: &#39;

TextBox2.Text giá trị: &amp;#39;

  1. Giá trị gửi trường hợp: <script>alert('attack!');</script>

Label1.Text giá trị: <script>alert('attack!');</script>

TextBox2.Text giá trị: &lt;script&gt;alert(&#39;attack!&#39;);&lt;/script&gt;

1
dpant

Đối với những người trong chúng ta vẫn bị mắc kẹt trên các biểu mẫu web, tôi đã tìm thấy giải pháp sau cho phép bạn chỉ vô hiệu hóa xác thực trên một trường! (Tôi ghét phải vô hiệu hóa nó cho toàn bộ trang.)

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

Bây giờ chỉ cần sử dụng <prefix:UnvalidatedTextBox id="test" runat="server" /> thay vì <asp:TextBox và nó sẽ cho phép tất cả các ký tự (điều này hoàn hảo cho các trường mật khẩu!)

1
Peter

Tôi biết câu hỏi này là về việc đăng mẫu, nhưng tôi muốn thêm một số chi tiết cho những người nhận được lỗi này trong các trường hợp khác. Nó cũng có thể xảy ra trên một trình xử lý được sử dụng để thực hiện một dịch vụ web. 

Giả sử ứng dụng khách web của bạn gửi POST hoặc PUT yêu cầu sử dụng ajax và gửi văn bản json hoặc xml hoặc dữ liệu thô (nội dung tệp) đến dịch vụ web của bạn. Vì dịch vụ web của bạn không cần nhận bất kỳ thông tin nào từ tiêu đề Kiểu nội dung, mã JavaScript của bạn không đặt tiêu đề này thành yêu cầu ajax của bạn. Nhưng nếu bạn không đặt tiêu đề này trên yêu cầu ajax POST/PUT, Safari có thể thêm tiêu đề này: "Loại nội dung: application/x-www-form-urlencoding". Tôi đã quan sát thấy rằng trên Safari 6 trên iPhone, nhưng các phiên bản Safari/HĐH hoặc Chrome khác có thể làm tương tự. Vì vậy, khi nhận được tiêu đề Kiểu nội dung này, một phần của .NET Framework giả định cấu trúc dữ liệu thân yêu cầu tương ứng với một bài đăng mẫu html trong khi nó không và tăng một ngoại lệ HttpRequestValidationException. Điều đầu tiên cần làm rõ ràng là luôn đặt tiêu đề Kiểu nội dung thành bất cứ thứ gì ngoại trừ loại MIME dạng trên yêu cầu ajax POST/PUT ngay cả khi dịch vụ web của bạn vô dụng.

Tôi cũng phát hiện ra chi tiết này:
Trong những trường hợp này, ngoại lệ HttpRequestValidationException sẽ xuất hiện khi mã của bạn cố gắng truy cập vào bộ sưu tập HttpRequest.Params. Nhưng thật đáng ngạc nhiên, ngoại lệ này không tăng khi truy cập vào bộ sưu tập httpRequest.ServerVariables. Điều này cho thấy rằng trong khi hai bộ sưu tập này dường như gần giống nhau, một bộ truy cập dữ liệu yêu cầu thông qua kiểm tra bảo mật và bộ kia thì không.

1
figolu

Trong .Net 4.0 trở đi, đó là trường hợp thông thường, hãy đặt cài đặt sau vào system.web

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

trong trường hợp của tôi, sử dụng asp: Điều khiển hộp văn bản (Asp.net 4.5), thay vì đặt tất cả trang cho validateRequest="false"

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

trên Hộp văn bản gây ra ngoại lệ.

0
maozx

Một giải pháp

Tôi không muốn tắt xác thực bài đăng (validateRequest = "false"). Mặt khác, không thể chấp nhận rằng ứng dụng gặp sự cố chỉ vì một người dùng vô tội xảy ra gõ <x hoặc một cái gì đó. 

Do đó, tôi đã viết một hàm javascript phía máy khách (xssCheckValidates) để kiểm tra sơ bộ. Hàm này được gọi khi có nỗ lực đăng dữ liệu biểu mẫu, như thế này:

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

Chức năng này khá đơn giản và có thể được cải thiện nhưng nó đang thực hiện công việc của mình.

Xin lưu ý rằng mục đích của việc này không phải là để bảo vệ hệ thống khỏi bị hack, nó có nghĩa là để bảo vệ người dùng khỏi trải nghiệm xấu. Xác thực yêu cầu được thực hiện tại máy chủ vẫn được bật và đó là (một phần) bảo vệ hệ thống (trong phạm vi có khả năng thực hiện điều đó). 

Lý do tôi nói "một phần" ở đây là vì tôi đã nghe nói rằng xác thực yêu cầu tích hợp có thể không đủ, vì vậy các phương tiện bổ sung khác có thể cần thiết để có sự bảo vệ đầy đủ. Nhưng, một lần nữa, chức năng javascript tôi trình bày ở đây có nothing để bảo vệ hệ thống. Đó là chỉ có nghĩa là đảm bảo người dùng sẽ không có trải nghiệm xấu.

Bạn có thể thử nó ở đây:

    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

Sử dụng Server.HtmlEncode("yourtext");

0
Voigt

Tôi thấy có rất nhiều điều được viết về điều này ... và tôi đã không thấy điều này được đề cập . Điều này đã có sẵn từ .NET Framework 4.5

ValidateRequestMode cài đặt cho điều khiển là một tùy chọn tuyệt vời . Bằng cách này, các điều khiển khác trên trang vẫn được bảo vệ. Không cần thay đổi web.config.

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