double escape sequence di dalam url: Modul pemfilteran permintaan dikonfigurasi untuk menolak permintaan yang berisi urutan escape ganda


86

Pada aplikasi ASP.NET MVC saya, saya mencoba menerapkan URL seperti di bawah ini:

/ product / tags / for + family

Ketika saya mencoba menjalankan aplikasi saya dengan konfigurasi default, saya mendapatkan pesan ini dengan Kode Respon 404.11:

Kesalahan HTTP 404.11 - Tidak Ditemukan

Modul pemfilteran permintaan dikonfigurasi untuk menolak permintaan yang berisi urutan pelolosan ganda.

Saya bisa mengatasi kesalahan ini dengan menerapkan kode di bawah ini di dalam web.config saya:

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

Jadi, sekarang saya tidak mendapatkannya 404.11.

Apa yang saya pikirkan adalah jenis lubang keamanan yang saya buka dengan implementasi ini.

BTW, aplikasi saya sedang .Net Framework 4.0dan berjalan di bawah IIS 7.5.


Apakah mungkin untuk mencapai sumber daya yang diinginkan dengan menggunakan /product/tags/for%20families? Kemudian Anda memiliki solusi untuk id yang berisi spasi. Atau apakah saya benar-benar di sini?
Anders Tornblad

@atornblad sedikit aneh kurasa. Pertanyaan saya: Apa yang saya pikirkan adalah lubang keamanan seperti apa yang saya buka dengan implementasi ini.
kapal tunda

5
IIS menggunakan karakter "+", yang merupakan perilaku default Microsoft.
Todd Shelton

Jawaban:


57

Lubang keamanan yang mungkin Anda buka berkaitan dengan injeksi kode - injeksi HTML, injeksi JavaScript atau injeksi SQL.

Pengaturan default melindungi Anda dari serangan secara semi-efisien dengan tidak mengizinkan strategi injeksi umum untuk bekerja. Semakin banyak keamanan default yang Anda hapus, semakin Anda harus memikirkan tentang apa yang Anda lakukan dengan input yang diberikan melalui URL, GET request querystrings, data permintaan POST, header HTTP, dan sebagainya ...

Misalnya, jika Anda membuat kueri SQL dinamis berdasarkan idparameter metode tindakan Anda, seperti ini:

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

(... yang BUKAN merupakan ide yang baik), perlindungan default, yang diterapkan oleh framework .NET, mungkin menghentikan beberapa skenario yang lebih berbahaya, seperti pengguna yang meminta URL ini:

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

Keseluruhan idenya adalah untuk memperlakukan setiap bagian url dan masukan lainnya untuk metode tindakan sebagai ancaman yang mungkin. Pengaturan keamanan default memang memberikan beberapa perlindungan itu untuk Anda. Setiap pengaturan keamanan default yang Anda ubah terbuka untuk sedikit lebih banyak potensi kejahatan yang perlu Anda tangani secara manual.

Saya berasumsi bahwa Anda tidak membangun kueri SQL dengan cara ini. Tapi hal yang lebih licik datang saat Anda menyimpan input pengguna di database Anda, lalu menampilkannya nanti. Pengguna jahat dapat menyimpan JavaScript atau HTML di database Anda yang tidak dienkode, yang pada gilirannya akan mengancam pengguna lain dari sistem Anda.


6

Risiko keamanan

Pengaturan allowDoubleEscapinghanya berlaku untuk path(cs-uri-stem) dan paling baik dijelaskan oleh OWASP Double Encoding . Teknik ini digunakan untuk menghindari kontrol keamanan dengan URL Mengkodekan permintaan dua kali. Menggunakan URL Anda sebagai contoh:

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

Misalkan ada kontrol keamanan khusus untuk /product/tags/for+families. Sebuah permintaan datang /product/tags/for%252Bfamiliesyang merupakan sumber daya yang sama meskipun tidak dicentang oleh kontrol keamanan yang disebutkan di atas. Saya menggunakan istilah umum dari kontrol keamanan karena mereka bisa berupa apa saja seperti membutuhkan pengguna yang diautentikasi, memeriksa SQLi, dll.

Mengapa IIS Memblokir?

Tanda plus (+) adalah karakter yang dicadangkan per RFC2396 :

Banyak URI menyertakan komponen yang terdiri dari atau dibatasi oleh, karakter khusus tertentu. Karakter ini disebut "dicadangkan", karena penggunaannya dalam komponen URI dibatasi untuk tujuan yang dicadangkan. Jika data untuk komponen URI akan bertentangan dengan tujuan yang dicadangkan, maka data yang berkonflik tersebut harus di-escape sebelum membentuk URI.

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

Wade Hilmo memiliki posting luar biasa berjudul Bagaimana IIS memblokir karakter di URL . Ada banyak informasi dan latar belakang yang disediakan. Bagian yang khusus untuk tanda plus adalah sebagai berikut:

Jadi allowDoubleEscaping / VerifyNormalization tampaknya cukup mudah. Mengapa saya mengatakan bahwa itu menyebabkan kebingungan? Masalahnya adalah ketika karakter '+' muncul di URL. Karakter '+' tampaknya tidak di-escape, karena tidak melibatkan '%'. Selain itu, RFC 2396 mencatatnya sebagai karakter yang dicadangkan yang dapat disertakan dalam URL jika dalam bentuk pelolosan (% 2b). Tetapi dengan allowDoubleEscaping disetel ke nilai defaultnya false, kami akan memblokirnya bahkan dalam bentuk pelarian. Alasannya bersifat historis: Jauh di masa-masa awal HTTP, karakter '+' dianggap singkatan untuk karakter spasi. Beberapa canonicalizer, ketika diberi URL yang mengandung '+' akan mengubahnya menjadi spasi. Karena alasan ini, kami menganggap '+' sebagai non-kanonik di URL. Saya tidak dapat menemukan referensi ke RFC yang menyebut perlakuan '+' ini,

Dari pengalaman saya sendiri, saya tahu bahwa ketika IIS mencatat ruang permintaan diganti dengan tanda tambah. Memiliki tanda plus di nama dapat menyebabkan kebingungan saat mengurai log.

Larutan

Ada tiga cara untuk memperbaikinya dan dua cara untuk tetap menggunakan tanda tambah.

  1. allowDoubleEscaping=true- Ini akan memungkinkan pelolosan ganda untuk seluruh situs web / aplikasi Anda. Bergantung pada kontennya, ini bisa jadi tidak diinginkan untuk sedikitnya. Perintah berikut akan disetel allowDoubleEscaping=true.

    appcmd.exe set config "Default Web Site" -section:system.webServer/security/requestFiltering /allowDoubleEscaping:True
    
  2. alwaysAllowedUrls- Request Filtering menawarkan pendekatan daftar putih. Dengan menambahkan jalur URL tersebut ke alwaysAllowedUrls, permintaan tidak akan diperiksa oleh setelan Filter Permintaan lainnya dan dilanjutkan di pipa permintaan IIS. Perhatian di sini adalah bahwa Request Filtering tidak akan memeriksa permintaan untuk:

    • Batas Permintaan: maxContentLength, maxUrl, maxQueryString
    • Kata kerja
    • Query - parameter string query tidak akan diperiksa
    • Escaping Ganda
    • Karakter Bit Tinggi
    • Minta Aturan Pemfilteran
    • Minta Batas Header

    Perintah berikut akan ditambahkan /product/tags/for+familieske alwaysAllowedUrlsdi Situs Web Default.

    appcmd.exe set config "Default Web Site" -section:system.webServer/security/requestFiltering /+"alwaysAllowedUrls.[url='/product/tags/for+families']"
    
  3. Ubah nama - ya, cukup ganti nama file / folder / controller / etc. jika memungkinkan. Ini adalah solusi termudah.


Untuk mengizinkanDoubleEscaping selama pengembangan dengan IIS Express, inilah yang saya lakukan: stackoverflow.com/q/56463044/381082
DeveloperDan

5

Saya telah bekerja keras untuk ini. jadi bila Anda ingin meletakkan string yang dienkripsi di dalam url untuk (IIS), Anda harus membersihkannya dari kotor: {";", "/", "?", ":", "@", "&", " = "," + "," $ ",", "}; dan ketika Anda ingin mendekripnya dan menggunakannya lagi, Anda harus membuatnya kotor lagi sebelum mendekripnya (untuk mendapatkan hasil yang diinginkan).

Ini kode saya, saya harap ini membantu seseorang:

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

Apa itu pntGlm?
StuperUser

@StuperUser hanya karakter acak
Mark Dibeh

1
String harus base64dienkode daripada menggunakan teknik substitusi ini. Misalnya, Autentikasi Dasar menggunakan base64untuk menyandikan kredensial yang dikirimkan karena mungkin berisi karakter khusus / cadangan.
pengguna2320464

masalah dengan base64 adalah / adalah karakter base64 dan dapat merusak rute
Garr Godfrey

1

Jadi saya mengalami ini ketika saya memanggil API dari aplikasi MVC. Alih-alih membuka lubang keamanan, saya mengubah jalur saya.

Pertama, saya sarankan untuk TIDAK menonaktifkan pengaturan ini. Lebih tepat untuk memodifikasi desain aplikasi / sumber daya (mis. Menyandikan jalur, meneruskan data di header atau di badan).

Meskipun ini adalah posting yang lebih lama, saya pikir saya akan berbagi bagaimana Anda bisa mengatasi kesalahan ini jika Anda menerima ini dari panggilan ke API dengan menggunakan metode HttpUtility.UrlPathEncode di System.Web .

Saya menggunakan RestSharp untuk melakukan panggilan, jadi contoh saya adalah menggunakan RestRequest:

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

Ini menghasilkan jalur yang sama dengan:

/ product / tags / untuk% 2Bfamilies

Di catatan lain, JANGAN membuat kueri dinamis berdasarkan masukan pengguna. Anda HARUS selalu menggunakan SqlParameter . Selain itu, sangat penting dari perspektif keamanan untuk mengembalikan nilai dengan pengkodean yang sesuai untuk mencegah serangan injeksi.

~ Cheers


0

Enkode string terenkripsi yang dipisahkan:

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

Dekode string terenkripsi dipisahkan:

string x = Encoding.UTF8.GetString(HttpServerUtility.UrlTokenDecode(id));
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.