Câu hỏi Một giá trị Request.Form nguy hiểm tiềm ẩn đã được phát hiện từ máy khách


Mỗi lần người dùng đăng nội dung có chứa < hoặc là > trong một trang trong ứng dụng web của tôi, tôi nhận được ngoại lệ này.

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

Trapping 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.

Tắt 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ẽ rời khỏi trang dễ bị tấn công bởi một số tấn công.

Lý tưởng nhất: Khi một bài đăng trở lại xảy ra có chứa các ký tự bị hạn chế HTML, giá trị được đăng trong bộ sưu tập Biểu mẫu sẽ tự động được mã hóa HTML. Nên .Text tài sản 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 xử lý?


1326
2017-09-17 10:58


gốc


Lưu ý rằng bạn có thể gặp phải lỗi này nếu bạn có các tên thực thể HTML (& amp;) hoặc số thực thể (') trong đầu vào của bạn. - Drew Noakes
Vâng, vì đó là câu hỏi của tôi, tôi cảm thấy tôi có thể xác định điểm thực sự là: làm rơi toàn bộ quá trình ứng dụng và trả về một thông báo lỗi chung vì ai đó gõ '<' là quá mức cần thiết. Đặc biệt là vì bạn biết hầu hết mọi người sẽ chỉ 'validateRequest = false' để loại bỏ nó, do đó mở lại lỗ hổng - Radu094
@DrewNoakes: tên thực thể (& amp;) dường như không phải là vấn đề theo thử nghiệm của tôi (được thử nghiệm trong .Net 4.0), mặc dù số thực thể (') không xác thực (như bạn đã nói). Nếu bạn tháo rời phương thức System.Web.CrossSiteScriptingValidation.IsDangerousString bằng cách sử dụng .Net Reflector, bạn sẽ thấy rằng mã trông đặc biệt cho các thẻ html (bắt đầu bằng <) và các số thực thể (bắt đầu bằng & #) - Gyum Fox
Tạo một trang mới trong VS2014 bằng cách sử dụng dự án MVC mặc định và chạy nó. Nhấp vào liên kết đăng ký, thêm bất kỳ email nào và sử dụng "<P455-0r [!" làm mật khẩu. Lỗi tương tự ra khỏi hộp, không cố gắng làm bất cứ điều gì độc hại, trường mật khẩu sẽ không được hiển thị vì vậy nó sẽ không phải là một cuộc tấn công XSS, nhưng cách duy nhất để khắc phục nó là gỡ bỏ hoàn toàn xác nhận hợp lệ với ValidateInput (false) ? Đề xuất AllowHtml không hoạt động trong tình huống này, vẫn bị lỗi với cùng một lỗi. Một giá trị Request.Form nguy hiểm tiềm tàng đã được phát hiện từ máy khách (Password = "<P455-0r [!"). - stephenbayer
TL; DR đưa <httpRuntime requestValidationMode="2.0" /> trong web.config


Các câu trả lời:


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.v.

Hơn nữa, "<"không phải là vốn 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 ngữ cảnh khác, các chuỗi con khác nhau là nguy hiểm, ví dụ: nếu bạn viết URL do người dùng cung cấp vào liên kết, chuỗi con "javascript:Nhân vật báo giá duy nhất, mặt khác là nguy hiểm khi nội suy chuỗi trong các truy vấn SQL, nhưng hoàn toàn an toàn nếu nó là một phần của tên được gửi từ một biểu mẫu hoặc đọc từ mộ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, vì bất kỳ ký tự nào có thể nguy hiểm trong các trường hợp thích hợp. Bạn nên mã hóa tại điểm mà một số nhân vật cụ thể có thể trở nên nguy hiểm bởi vì họ vượt qua một ngôn ngữ phụ khác nhau, nơi họ 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 tới 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 nào bạn chắc chắn bạn mã hóa HTML ở mọi nơi bạn chuyển chuỗi thành HTML, sau đó đặt validateRequest="false" bên trong <%@ Page ... %> chỉ thị trong .aspx các tập tin).

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 phải thêm <httpRuntime requestValidationMode="2.0" /> tới web.config (tài liệu tham khảo).


996
2017-09-17 11:26



Đối với những người đến trễ: validateRequest = "false" đi trong chỉ thị Trang (dòng đầu tiên của tệp .aspx của bạn) - MGOwen
Mẹo: Đặt <httpRuntime requestValidationMode="2.0" /> trong thẻ vị trí để tránh làm mất khả năng bảo vệ hữu ích do xác thực từ phần còn lại của trang web của bạn cung cấp. - Brian
Trong MVC3, đây là [AllowHtml] trên thuộc tính mô hình. - Jeremy Holovacs
@MGOwen bạn cũng có thể thêm chỉ thị trang vào web.config qua <pages validateRequest="false" /> trong <system.web />. Làm như vậy sẽ áp dụng thuộc tính cho tất cả các trang. - oliver-clare
Trong MVC4, [ValidateInput(false)] công trinh. - Adam K Dean


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

467
2017-10-08 22:56



vấn đề có thể xảy ra khi nó cần trên một trang của toàn bộ ứng dụng
Bạn cũng có thể thêm thuộc tính [ValidateInput (false)] ở cấp lớp. Nếu bạn thêm nó vào lớp điều khiển cơ sở của bạn, nó sẽ áp dụng cho tất cả các hành động của phương thức điều khiển. - Shan Plourde
@Zack Cảm ơn vì giải pháp. Mặt khác, tôi tự hỏi nếu [AllowHtml] tốt hơn ValidateInput(false), bởi vì [AllowHtml]được xác định cùng một lúc cho thuộc tính tức là trường Editor và bất cứ khi nào nó được sử dụng, không cần sử dụng nó cho một số hành động. Bạn có đề nghị gì? - Clint Eastwood
@Zack Peterson Có an toàn để sử dụng không? Không có vấn đề bảo mật? - shrey Pav


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

Nó cho phép 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 nhận yêu cầu cho thuộc tính.

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

361
2017-09-05 09:33



Tốt hơn nhiều để làm điều này declarativly hơn trong bộ điều khiển! - Andiih
Câu trả lời đúng duy nhất! vô hiệu hóa xác nhận trên hành động điều khiển là hacky. Và để vô hiệu hóa xác nhận ở cấp ứng dụng, các nhà phát triển phải bị treo cổ! - trailmax
Đẹp! Đây là cách nó Nên được làm. - beautifulcoder
@AnthonyJohnston Nó cũng có thể được sử dụng trong MVC 4 và MVC 5 không? Cảm ơn... - Clint Eastwood
Sự khác biệt giữa ValidateInput(false) và AllowHtml? Lợi thế của cái này với cái kia là gì? Khi nào tôi muốn sử dụng AllowHtml thay vì ValidateInput(false)? Khi nào tôi muốn sử dụng ValidateInput(false) kết thúc AllowHtml? Khi nào tôi muốn sử dụng cả hai? Liệu nó có ý nghĩa để sử dụng cả hai? - Ian Boyd


Nếu bạn đang sử dụng .NET 4.0, hãy đảm bảo bạn đã thêm điều này vào web.config tập tin bên trong <system.web> thẻ:

<httpRuntime requestValidationMode="2.0" />

Trong .NET 2.0, yêu cầu xác thực chỉ được áp dụng cho aspx yêu cầu. Trong .NET 4.0, điều này đã được mở rộng để bao gồm tất cả các yêu cầu. Bạn có thể hoàn nguyên về chỉ có thực hiện xác nhận 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"

203
2017-07-30 04:51



Bên trong <system.web> thẻ. - Hosam Aly
Tôi đã đặt điều này trong web.config, nhưng vẫn còn lỗi "Giá trị Request.Form nguy hiểm tiềm tàng" - Filip
Có vẻ như <httpRuntime requestValidationMode = "2.0" /> chỉ hoạt động khi 2.0 khung được cài đặt trên máy. Điều gì sẽ xảy ra nếu khung 2.0 không được cài đặt nhưng chỉ có 4,0 khung được cài đặt? - Samuel
Điều này hoàn toàn làm việc cho tôi. Không có tài liệu nào trong các bước trong các câu trả lời khác là cần thiết (bao gồm validateRequest = "false")! - tom redfern
Điều này cố định vấn đề hiện tại của tôi. Cảm ơn bạn! - Dyrborg


Đố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 web bằng cách đặt tất cả trong một <location> thành phần. Điều này sẽ đảm bảo rằng tất cả các trang khác của bạn đều an toàn. Bạn KHÔNG cần phải đặt ValidateRequest="false" trong trang .aspx của bạn.

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

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

Bạn vẫn cần phải xác thực hợp lệ đầu vào trên các trang có xác thực yêu cầu bị vô hiệu hóa.


102
2017-11-27 17:22



Thông tin thêm về yêu cầuValidationMode = 2 | 4 tại đây: msdn.microsoft.com/en-us/library/… - GlennG
Đáng buồn thay điều này sẽ không làm việc với ASP.net 2.0 như là. Loại bỏ dòng httpRuntime và nó sẽ hoạt động. - Fandango68
bạn vẫn có validateRequest = "false" - VERY BAD !!! - MC9000
Tôi đã thêm một cảnh báo nhắc nhở mọi người để xác thực hợp lệ đầu vào khi xác thực bị vô hiệu hóa. - Carter Medlin
Giải pháp này làm việc hoàn hảo cho tôi. Cảm ơn bạn. - aspnetdeveloper


Các câu trả lời trước là tuyệt vời, nhưng không ai nói làm thế nào để loại trừ một lĩnh vực duy nhất không được xác nhận cho 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 được loại trừ. Điều tốt đẹp về điều này là các thuộc tính xác thực của bạn vẫn xác nhận được trường, nhưng bạn không nhận được "Một giá trị Request.Form nguy hiểm tiềm ẩn đã được phát hiện từ máy khách" ngoại lệ.

Tôi đã sử dụng điều này để xác thực một biểu thức chính quy. Tôi đã tạo ValidationAttribute của riêng mình để xem biểu thức chính quy có hợp lệ hay không. Như 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 kịch bản tôi đã áp dụng mã trên - biểu thức chính quy vẫn đang được kiểm tra nếu nó hợp lệ hay không, nhưng không phải nếu nó có chứa các tập lệnh hoặc HTML.


68
2017-11-06 14:58



Đáng buồn thay, có vẻ như tính năng Loại trừ đã bị xóa khỏi MVC 3 RTW :( - Matt Greer
Nó cũng không được bao gồm trong MVC 4 - wilsjd
Sử dụng [AllowHtml] trên các thuộc tính của mô hình thay vì [ValidateInput] trên Hành động để đạt được cùng kết quả cuối cùng. - Mrchief
@gligoran Is [AllowHtml] tốt hơn ValidateInput(false) cho các trường Editor? Bởi vì [AllowHtml]được xác định cùng một lúc cho thuộc tính tức là trường Editor và bất cứ khi nào nó được sử dụng, không cần sử dụng nó cho một số hành động. Bạn có đề nghị gì? - Clint Eastwood
@Christof Lưu ý rằng câu trả lời của tôi là 5 tuổi. Tôi đã không gặp vấn đề này trong một thời gian dài, vì vậy có thể có nhiều cách giải quyết tốt hơn với nó. Về hai lựa chọn này, tôi nghĩ rằng nó phụ thuộc vào tình hình của bạn. Có thể bạn phơi bày mô hình đó trong nhiều hành động và ở một số nơi HTML được phép hay không. Trong trường hợp như vậy [AllowHtml] không phải là một lựa chọn. Tôi khuyên bạn nên kiểm tra bài viết này: weblogs.asp.net/imranbaloch/…, nhưng nó cũng hơi cũ và có thể đã lỗi thời. - gligoran


Trong ASP.NET MVC bạn cần phải đặ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) {
    ...
}

46
2017-11-30 12:56



Cho tôi, validateRequest="false" không cần thiết, chỉ requestValidationMode="2.0" - tom redfern
requestValidationMode = "2.0" vẫn tạo ra lỗi với dữ liệu được mã hóa HTML. Không có giải pháp nào ngoại trừ mã hóa base64, sau đó gửi nó đi. - MC9000