trình tự thoát kép bên trong url: Mô-đun lọc yêu cầu được định cấu hình để từ chối yêu cầu chứa trình tự thoát kép


86

Trên ứng dụng ASP.NET MVC của tôi, tôi đang cố gắng triển khai một URL như sau:

/ product / tags / cho + gia đình

Khi tôi cố gắng chạy ứng dụng của mình với cấu hình mặc định, tôi nhận được thông báo này với Mã phản hồi 404.11:

Lỗi HTTP 404.11 - Không tìm thấy

Mô-đun lọc yêu cầu được định cấu hình để từ chối yêu cầu có chứa chuỗi thoát kép.

Tôi có thể khắc phục lỗi này bằng cách triển khai mã bên dưới bên trong web.config của mình:

  <system.webServer>
    <security>
      <requestFiltering allowDoubleEscaping="true" />
    </security>
  </system.webServer>

Vì vậy, bây giờ tôi không nhận được bất kỳ 404.11.

Điều tôi tự hỏi là loại lỗ hổng bảo mật nào tôi đang mở khi triển khai này.

BTW, ứng dụng của tôi đang .Net Framework 4.0và đang chạy IIS 7.5.


Có thể đạt được tài nguyên mong muốn bằng cách sử dụng /product/tags/for%20familiesthay thế không? Sau đó, bạn có một giải pháp cho id chứa khoảng trắng. Hay tôi hoàn toàn không ở đây?
Anders Tornblad

Tôi đoán là @atornblad một chút. Câu hỏi của tôi: Điều tôi tự hỏi là loại lỗ hổng bảo mật nào tôi đang mở khi triển khai này.
tugberk

5
IIS đang ném vào ký tự "+", đây là hành vi mặc định của Microsoft.
Todd Shelton

Câu trả lời:


57

Các lỗ hổng bảo mật mà bạn có thể mở ra liên quan đến việc chèn mã - chèn HTML, chèn JavaScript hoặc chèn SQL.

Cài đặt mặc định bảo vệ bạn khỏi các cuộc tấn công bán hiệu quả bằng cách không cho phép các chiến lược tiêm thông thường hoạt động. Bạn càng loại bỏ bảo mật mặc định, bạn càng phải suy nghĩ nhiều hơn về những gì bạn làm với đầu vào được cung cấp thông qua URL, chuỗi truy vấn yêu cầu GET, dữ liệu yêu cầu POST, tiêu đề HTTP, v.v.

Ví dụ: nếu bạn đang xây dựng các truy vấn SQL động dựa trên idtham số của phương thức hành động của bạn, như sau:

public ActionResult Tags(string id)
{
    var sql = "SELECT * FROM Tags Where tagName = '" + id + "'";
    // DO STUFF...
}

(... KHÔNG phải là một ý kiến ​​hay), bảo vệ mặc định, được đặt bởi .NET framework, có thể ngăn chặn một số tình huống nguy hiểm hơn, như người dùng yêu cầu URL này:

/product/tags/1%27;drop%20table%20Tags;%20--

Toàn bộ ý tưởng là coi mọi phần của url và các đầu vào khác cho các phương pháp hành động là các mối đe dọa có thể xảy ra. Cài đặt bảo mật mặc định cung cấp một số biện pháp bảo vệ đó cho bạn. Mỗi cài đặt bảo mật mặc định mà bạn thay đổi sẽ mở ra thêm một chút tính năng xấu tiềm ẩn mà bạn cần phải xử lý theo cách thủ công.

Tôi giả sử rằng bạn không xây dựng các truy vấn SQL theo cách này. Nhưng những thứ lén lút hơn xảy ra khi bạn lưu trữ thông tin đầu vào của người dùng trong cơ sở dữ liệu của mình, sau đó hiển thị chúng sau đó. Người dùng ác ý có thể lưu trữ JavaScript hoặc HTML trong cơ sở dữ liệu của bạn mà không được mã hóa, điều này sẽ đe dọa những người dùng khác trong hệ thống của bạn.


6

Rủi ro bảo mật

Cài đặt này allowDoubleEscapingchỉ áp dụng cho path(cs-uri-gốc) và được giải thích tốt nhất bằng Mã hóa kép OWASP . Kỹ thuật này được sử dụng để vượt qua các kiểm soát bảo mật bằng URL Mã hóa yêu cầu hai lần. Sử dụng URL của bạn làm ví dụ:

/product/tags/for+families --> /product/tags/for%2Bfamilies --> /product/tags/for%252Bfamilies

Giả sử có các kiểm soát bảo mật dành riêng cho /product/tags/for+families. Một yêu cầu đến với /product/tags/for%252Bfamiliescùng một tài nguyên mặc dù không được kiểm tra bởi các biện pháp kiểm soát bảo mật nói trên. Tôi đã sử dụng thuật ngữ tổng quát của các biện pháp kiểm soát bảo mật vì chúng có thể là bất kỳ điều gì chẳng hạn như yêu cầu người dùng được xác thực, kiểm tra SQLi, v.v.

Tại sao IIS lại chặn?

Dấu cộng (+) là một ký tự dành riêng cho mỗi RFC2396 :

Nhiều URI bao gồm các thành phần bao gồm hoặc được phân cách bằng một số ký tự đặc biệt. Các ký tự này được gọi là "dành riêng", vì việc sử dụng chúng trong thành phần URI được giới hạn cho mục đích dành riêng của chúng. Nếu dữ liệu cho một thành phần URI sẽ xung đột với mục đích dành riêng, thì dữ liệu xung đột phải được thoát trước khi hình thành URI.

  reserved    = ";" | "/" | "?" | ":" | "@" | "&" | "=" | "+" |
                "$" | ","

Wade Hilmo có một bài đăng xuất sắc với tiêu đề Cách IIS chặn các ký tự trong URL . Có rất nhiều thông tin và nền tảng được cung cấp. Phần cụ thể cho dấu cộng như sau:

Vì vậy, allowDoubleEscaping / VerifyNormalization có vẻ khá đơn giản. Tại sao tôi nói rằng nó gây ra sự nhầm lẫn? Vấn đề là khi ký tự '+' xuất hiện trong URL. Ký tự '+' dường như không được thoát, vì nó không liên quan đến '%'. Ngoài ra, RFC 2396 lưu ý nó là một ký tự dành riêng có thể được đưa vào URL khi nó ở dạng thoát (% 2b). Nhưng với allowDoubleEscaping được đặt thành giá trị mặc định là false, chúng tôi sẽ chặn nó ngay cả ở dạng thoát. Lý do cho điều này là lịch sử: Quay lại những ngày đầu của HTTP, ký tự '+' được coi là viết tắt của một ký tự khoảng trắng. Một số công cụ chuẩn hóa, khi được cung cấp một URL chứa dấu '+' sẽ chuyển đổi nó thành một khoảng trắng. Vì lý do này, chúng tôi coi dấu '+' là không chuẩn trong URL. Tôi không thể tìm thấy bất kỳ tham chiếu nào đến RFC gọi điều trị '+' này,

Từ kinh nghiệm của riêng tôi, tôi biết rằng khi IIS ghi nhật ký, các khoảng trắng yêu cầu được thay thế bằng dấu cộng. Việc có dấu cộng trong tên có thể gây nhầm lẫn khi phân tích cú pháp nhật ký.

Giải pháp

Có ba cách để sửa lỗi này và hai cách để vẫn sử dụng dấu cộng.

  1. allowDoubleEscaping=true- Điều này sẽ cho phép thoát kép cho toàn bộ trang web / ứng dụng của bạn. Tùy thuộc vào nội dung, điều này có thể là không mong muốn để nói rằng ít nhất. Lệnh sau sẽ được thiết lập allowDoubleEscaping=true.

    appcmd.exe set config "Default Web Site" -section:system.webServer/security/requestFiltering /allowDoubleEscaping:True
    
  2. alwaysAllowedUrls- Lọc Yêu cầu cung cấp một cách tiếp cận danh sách trắng. Bằng cách thêm đường dẫn URL đó vào alwaysAllowedUrls, yêu cầu sẽ không bị bất kỳ cài đặt Lọc yêu cầu nào khác kiểm tra và tiếp tục trong đường dẫn yêu cầu IIS. Mối quan tâm ở đây là Lọc Yêu cầu sẽ không kiểm tra yêu cầu cho:

    • Giới hạn yêu cầu: maxContentLength, maxUrl, maxQueryString
    • Động từ
    • Truy vấn - tham số chuỗi truy vấn sẽ không được kiểm tra
    • Chạy trốn kép
    • Ký tự bit cao
    • Yêu cầu quy tắc lọc
    • Yêu cầu giới hạn tiêu đề

    Lệnh sau sẽ bổ sung thêm /product/tags/for+familiesđể alwaysAllowedUrlsvào Default Web Site.

    appcmd.exe set config "Default Web Site" -section:system.webServer/security/requestFiltering /+"alwaysAllowedUrls.[url='/product/tags/for+families']"
    
  3. Đổi tên - có, chỉ cần đổi tên tệp / thư mục / bộ điều khiển / v.v. nếu có thể. Đây là giải pháp dễ dàng nhất.


Để cho phépDoubleEscaping trong quá trình phát triển với IIS Express, đây là những gì tôi đã làm: stackoverflow.com/q/56463044/381082
DeveloperDan

3

Tôi đã giải quyết vấn đề này. vì vậy khi bạn muốn đặt chuỗi được mã hóa bên trong url cho (IIS), bạn phải làm sạch nó khỏi bẩn: {";", "/", "?", ":", "@", "&", " = "," + "," $ ",", "}; và khi bạn muốn giải mã nó và sử dụng lại, bạn phải làm bẩn nó một lần nữa trước khi giải mã (để có được kết quả mong muốn).

Đây là mã của tôi, tôi hy vọng nó sẽ giúp được ai đó:

 public static string cleanUpEncription(string encriptedstring)
        {
            string[] dirtyCharacters = { ";", "/", "?", ":", "@", "&", "=", "+", "$", "," };
            string[] cleanCharacters = { "p2n3t4G5l6m","s1l2a3s4h","q1e2st3i4o5n" ,"T22p14nt2s", "a9t" , "a2n3nd","e1q2ua88l","p22l33u1ws","d0l1ar5","c0m8a1a"};

            foreach (string dirtyCharacter in dirtyCharacters)
            {
                encriptedstring=encriptedstring.Replace(dirtyCharacter, cleanCharacters[Array.IndexOf(dirtyCharacters, dirtyCharacter)]);
            }
            return encriptedstring;
        }

        public static string MakeItDirtyAgain(string encriptedString)
        {
            string[] dirtyCharacters = { ";", "/", "?", ":", "@", "&", "=", "+", "$", "," };
            string[] cleanCharacters = { "p2n3t4G5l6m", "s1l2a3s4h", "q1e2st3i4o5n", "T22p14nt2s", "a9t", "a2n3nd", "e1q2ua88l", "p22l33u1ws", "d0l1ar5", "c0m8a1a" };
            foreach (string symbol in cleanCharacters)
            {
                encriptedString = encriptedString.Replace(symbol, dirtyCharacters[Array.IndexOf(cleanCharacters,symbol)]);
            }
            return encriptedString;
        }

PntGlm là gì?
StuperUser

@Stuper Người dùng chỉ là các ký tự ngẫu nhiên
Mark Dibeh

1
Chuỗi phải được base64mã hóa thay vì sử dụng kỹ thuật thay thế này. Ví dụ: Xác thực cơ bản sử dụng base64để mã hóa thông tin đăng nhập đã gửi vì nó có thể chứa các ký tự đặc biệt / dành riêng.
dùng2320464

vấn đề với base64 là / là một ký tự base64 và có thể phá vỡ các tuyến
Garr Godfrey

1

Vì vậy, tôi đã gặp phải vấn đề này khi tôi đang gọi một API từ một ứng dụng MVC. Thay vì mở lỗ hổng bảo mật, tôi đã sửa đổi đường dẫn của mình.

Trước hết, tôi khuyên bạn KHÔNG nên tắt cài đặt này. Sẽ thích hợp hơn nếu sửa đổi thiết kế của ứng dụng / tài nguyên (ví dụ: mã hóa đường dẫn, truyền dữ liệu trong tiêu đề hoặc trong nội dung).

Mặc dù đây là một bài đăng cũ hơn, nhưng tôi nghĩ rằng tôi sẽ chia sẻ cách bạn có thể giải quyết lỗi này nếu bạn nhận được lỗi này từ một lệnh gọi tới API bằng cách sử dụng phương thức HttpUtility.UrlPathEncode trong System.Web .

Tôi sử dụng RestSharp để thực hiện các cuộc gọi, vì vậy ví dụ của tôi đang sử dụng RestRequest:

var tags = new[] { "for", "family" };
var apiRequest = new RestRequest($"product/tags/{HttpUtility.UrlPathEncode(string.Join("+", tags))}");

Điều này tạo ra một đường dẫn bằng:

/ product / tags / for% 2Bfamilies

Một lưu ý khác, KHÔNG tạo truy vấn động dựa trên đầu vào của người dùng. Bạn NÊN luôn sử dụng SqlParameter . Ngoài ra, từ góc độ bảo mật, điều cực kỳ quan trọng là trả về các giá trị bằng mã hóa thích hợp để ngăn chặn các cuộc tấn công tiêm vào.

~ Chúc mừng


0

Mã hóa chuỗi mã hóa được phân tách:

return HttpServerUtility.UrlTokenEncode(Encoding.UTF8.GetBytes("string"));

Giải mã chuỗi mã hóa được phân tách:

string x = Encoding.UTF8.GetString(HttpServerUtility.UrlTokenDecode(id));
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.