Keamanan melalui pembatasan pengguna atau cara membuat kerentanan

Pada tahun 2019, kerentanan CPDoS Cache Poisoned Denial of Service) ditemukan di jaringan CDN, yang memungkinkan keracunan cache HTTP dari penyedia CDN dan menyebabkan penolakan layanan. Kerentanan belum mengumpulkan banyak hype, karena belum terlihat dalam serangan nyata. Tapi saya ingin berbicara tentang salah satu metode keracunan cache secara terpisah. Metode HTTP Override.


Jika varian lain dari mengeksploitasi kerentanan dalam satu atau lain cara bergantung pada bug atau fitur modifikasi permintaan oleh perantara, maka varian Metode Override didasarkan pada taktik dengan nama yang sama, yang bukan bagian dari standar HTTP, disertai dengan masalah tambahan, dan yang muncul dan menyebar karena ceroboh. hubungan dengan keamanan. Di sini kita akan mempertimbangkannya.

Singkat tentang CPDoS jika Anda melewatkannya
, URI method .

, , , , - . โ€” - - -, , - , . , .

, . , , -. - , , .


Batasi klien, lebih sedikit bisa - lebih sedikit akan rusak


Sangat perlu untuk menimpa metode dalam permintaan muncul karena fakta bahwa beberapa Aplikasi Web Firewall dan implementasi klien HTTP sangat terbatas dan tidak memungkinkan pelaksanaan metode selain GET dan POST. Masalahnya bukan bahwa itu adalah pembatasan implementasi, tetapi bahwa itu adalah pembatasan yang disengaja dari klien HTTP oleh kebijakan keamanan.

Jelas bahwa semuanya dilakukan dengan niat baik untuk memotong lalu lintas yang sempit, non-standar untuk klien HTTP biasa. Tetapi dalam mengejar keamanan, semua metode kecuali GET dan POST terputus. Mungkin karena ini adalah satu-satunya metode yang tidak opsional dan diperlukan untuk server tujuan umum.

Mengapa itu diperlukan untuk memperkenalkan pembatasan ketat seperti itu tidak jelas. Ya, serangan dengan pengenalan berbagai karakter untuk membingungkan parser hanyalah hobi protokol teks. Tetapi Anda dapat mengizinkan sedikit lebih banyak metode, misalnya, mengambil setidaknya yang dijelaskan dalam standar itu sendiri atau terdaftar di IANA . Itu tidak layak untuk sepenuhnya menghapus pemeriksaan metode, tetapi Anda bisa memanggil sejumlah metode yang paling populer dan mengecualikan mereka yang mengubah protokol interaksi dan memutus pekerjaan dengan koneksi pada server proxy (CONNECT). Tapi tidak, ternyata kebijakan keamanan yang memberlakukan pembatasan dan larangan yang tidak perlu bagi pelanggan.

Dan pelanggan terbatas pada yang salah. Mereka ingin membatasi variabilitas pesan dari klien HTTP, dan membatasi klien yang dilindungi oleh WAF ini, server aplikasi akhir dan pengembangnya. Sekarang, pengembang hanya memiliki dua metode yang tidak selalu cukup untuk menggambarkan logika klien HTTP.

Kendala diciptakan untuk mengatasinya.


Diharapkan bahwa pembatasan yang berlebihan ini cepat atau lambat akan mulai mengganggu pengembang web. Ironinya adalah sangat mudah untuk tidak menyingkirkan WAF seperti itu. Terutama ketika mereka bersama pelanggan atau penyedia. Menantang kebijakan keamanan orang lain adalah masalah yang menghancurkan.

Karena fleksibilitas HTTP, tidak sulit untuk menghindari batasan ini, cukup tambahkan sesuatu ke permintaan di mana Anda dapat mengganti metode. WAF yang ketat hanya akan memeriksa metode di Baris Permintaan (baris pertama permintaan) dan akan senang melihat GET atau POST yang disetujui di sana. Dan backend akan dapat menguraikan elemen yang ditambahkan dan mengekstrak metode nyata darinya.

Anda dapat google banyak artikel, benar-benar banyaktentang bagaimana proxy yang buruk merusak aplikasi REST, dan bagaimana penulis harus melewati metode nyata di header yang terpisah. Dalam semuanya, mereka menyarankan agar Anda memasukkan kira-kira tajuk yang sama (X-HTTP-Method, X-HTTP-Method-Override atau X-Method-Override - ejaannya agak bervariasi) untuk menunjukkan metode yang diganti. Sangat, sangat jarang orang dapat menemukan referensi yang dapat digunakan untuk tujuan-komponen URI tujuan yang sama.

Apa yang hilang dari artikel ini adalah bagian Pertimbangan Keamanan. Dan memang begitu.

Apakah metode utama aman?


Terkadang pengembang aplikasi web lupa bahwa antara klien dan server mungkin ada peserta menengah yang berinteraksi melalui protokol HTTP: proksi, cache web penyedia, CDN dan WAF. Proliferasi TLS sangat mengurangi kemungkinan peserta perantara antara klien dan server. Kemungkinan besar satu-satunya proxy antara klien dan backend adalah servernya sendiri dengan Nginx. Dan konfigurasi seperti itu cukup mudah untuk menguji skenario tipikal sebelum rilis.

Tapi kami memasuki era CDN, dan semakin banyak aplikasi akan bersembunyi di balik CDN yang membaca dan memanipulasi traffic pengguna. Backends secara langsung hampir tidak pernah melayani pengguna, dan bersembunyi di balik proxy terbalik untuk meningkatkan daya tanggap dan kinerja. Oleh karena itu, Anda harus ingat bagaimana mengganti metode dapat memengaruhi pemrosesan permintaan pada server mediasi.

Serangan yang ingin saya bicarakan terutama berlaku untuk HTTP / 1.1. HTTP / 2 dalam beberapa hal mewarisi perilaku standar lama, dalam beberapa hal berjalan dengan caranya sendiri, sehingga penerapan setiap serangan ke standar baru akan dipertimbangkan secara terpisah.

Serangan cache


Paling sering, server perantara tidak memperhitungkan penggantian metode akun, jangan memeriksa header keluarga X-HTTP-Method-Override, dan bekerja dengan permintaan menggunakan metode utamanya dari Baris Permintaan. Dan karena metode yang diganti tidak termasuk dalam kunci untuk mencari permintaan dalam cache (metode + URI), server tersebut tidak dapat membedakan POST dari POST + X-HTTP-Method-Override: DELETE. Ini berarti bahwa Anda tidak dapat mengizinkan caching permintaan apa pun ke URI tertentu jika backend dapat memantau dan menjalankan metode yang diganti.

Dokumen CPDoS memiliki contoh bagus tentang apa yang terjadi jika Anda menyimpan permintaan seperti itu. Ketika seorang penyerang menyamarkan permintaan POST sebagai permintaan GET, proksi tidak mengenali substitusi dan memperlakukan permintaan tersebut sebagai permintaan GET yang sah. Backend, bagaimanapun, mengenali metode yang ditimpa dan mengeksekusi kata kerja yang dijelaskan dalam X-HTTP-Method-Override - POST header. Karena metode POST tidak ditentukan untuk URI tujuan, server menghasilkan kesalahan. Selanjutnya, respons backend disimpan dalam cache sebagai respons terhadap metode asli - GET. Sekarang setiap permintaan GET berikutnya untuk URI yang sama akan mengembalikan kesalahan dalam cache.


Bahkan, serangannya sedikit lebih lebar dari yang disajikan dalam dokumen. Para penulis fokus pada menyimpan kesalahan dalam cache, yang tidak di mana-mana (sudah) dapat direproduksi. Tetapi jika metode yang diminta untuk URI yang dipilih ditentukan dan akan berhasil dijalankan, proksi akan menerima respons dengan status 200 dan menyimpannya. Kemudian permintaan selanjutnya dari URI yang sama untuk menerima tanggapan terhadap metode yang sepenuhnya salah. Dalam skenario ini, tidak ada lagi persyaratan dengan kesalahan cache tanggapan 4XX, seperti dalam deskripsi CPDoS asli.

Masalah sebaliknya dapat terjadi. Jika klien HTTP yang terhormat mengirim GET + X-HTTP-Method-Override: permintaan PATCH (ini buruk, tetapi lebih lanjut tentang itu nanti), dan cache sudah memiliki respons GET, maka klien akan menerima respons cache ini. Dalam kasus ini, backend tidak akan pernah menerima permintaan PATCH, yang dapat melanggar logika aplikasi pada klien dan server.

Anda dapat mengurangi efek pada cache dengan membangun kebijakan cache yang benar dan membagi sumber daya menjadi dua grup: yang metode yang menimpa operasi tidak dapat diterima atau tidak diperlukan, respons terhadapnya bisa di-cache, dan yang metode diperlukan untuk menimpanya, caching jawaban semacam itu tidak dapat diterima . Tetapi semakin sedikit sumber daya yang di-cache, semakin tidak berguna adalah CDN dan semakin banyak lalu lintas mencapai backend, semakin banyak aplikasi terkena banjir HTTP.

Oleh karena itu, lebih baik menggunakan cache HTTP sebanyak mungkin, untuk ini perlu bahwa server cache dapat membedakan antara permintaan dengan metode menimpa yang berbeda. Cara pertama adalah mentransfer metode override komponen kueri ke URI:

POST /some-uri HTTP/1.1
X-HTTP-Method-Override: DELETE
   โ†“  โ†“   โ†“
POST /some-uri?method=DELETE HTTP/1.1

Sekarang permintaan dengan metode berbeda terlihat berbeda untuk cache, karena mereka mendapatkan kunci yang berbeda. Beberapa proksi memilih untuk tidak menembaki respons ke permintaan yang berisi komponen kueri di URI. Tetapi ini hanya akan mempengaruhi efisiensi caching. Metode ini selalu memecahkan masalah dengan caching yang salah.

Cara lain adalah meninggalkan metode override di header yang terpisah, tetapi masukkan kunci sekunder untuk menemukan jawabannya di cache. Ini dimungkinkan dengan header Vary. Saat melayani permintaan, server akan mengulangi tajuk dengan metode override dan mencerminkan nama tajuk ini di tajuk Vary. Kemudian, pada permintaan berikut, server cache akan menggunakan nilai metode yang diganti sebagai kunci sekunder saat mencari permintaan di cache.


Metode ini berfungsi jika server perantara dapat bekerja dengan kunci sekunder. Ini biasanya terjadi, tetapi tingkat kepercayaan proxy, yang memotong semua metode kecuali GET dan POST, biasanya lebih rendah dan lebih baik untuk memeriksa ini.

Mengganti metode melalui entitas apa pun di dalam tubuh permintaan memiliki kelemahan yang sama persis dengan mengesampingkan melalui header tambahan - itu berada di luar visibilitas cache.

Serangan Antrian Pesan


Bahkan jika serangan cache ditutup, itu tidak semua. Seorang penyerang dengan mengganti metode mungkin mencoba mengubah pembingkaian respons dan dengan demikian melanggar korespondensi dari pasangan permintaan-respons untuk klien lain. Atau paksakan sisi server aplikasi untuk memproses permintaan yang sama beberapa kali.

Hal terpenting yang diperlukan untuk ini adalah server perantara yang beroperasi dalam mode reverse-proxy. Artinya, semua caching atau server CDN. Proxy semacam itu mendukung sejumlah kecil koneksi ke backend, dan melipatgandakan permintaan dari banyak klien di masing-masing. Hal ini diperlukan baik untuk mengambil beban mendukung sejumlah besar koneksi klien dari backend ke server proxy, dan untuk menyeimbangkan beban antara backend. Pengakhiran koneksi TLS juga terjadi pada proksi, koneksi klien tidak pernah terhubung langsung ke backend.

Karena sekarang permintaan dari klien yang berbeda akan berada dalam koneksi yang sama antara backend dan proksi, perlu untuk menjaga korespondensi yang jelas antara pasangan permintaan-respons. Sebagian besar proxy tidak menggunakan saluran pipa(pipa) permintaan ke backend dan bekerja dengannya dalam mode permintaan-respons. Mode permintaan-respons lebih sederhana dan tunduk pada satu ancaman - pemblokiran koneksi. Jika Anda membuat koneksi menggantung pada pasangan permintaan-respons tunggal, Anda dapat menyebabkan penundaan atau bahkan penolakan untuk memproses permintaan berikut (misalnya, jika Anda berhasil meluap antrian permintaan proxy).

Permintaan pipa proksi yang lebih produktif ke backend - ini memungkinkan Anda untuk mengirim paket permintaan ke server segera dan menunggu eksekusi. Kinerja lebih tinggi, tetapi ada lebih banyak ancaman. Pertama, masalah pemblokiran head-of-line tidak hilang di mana pun - bahkan jika backend dapat menyapu pipa permintaan dan menjalankannya secara paralel, mereka tidak dapat dikirim jika yang pertama hang. Kedua, jika Anda mematahkan framing respons, Anda dapat membingungkan proksi dan memutus korespondensi dari pasangan permintaan-respons, maka beberapa klien dapat memperoleh jawaban orang lain, atau setidaknya mencapai penutupan koneksi instan dengan backend.


Redefinisi paling sederhana dan paling menyenangkan dari suatu metode adalah mengganti GET dengan kata kerja HEAD. Jika jawaban yang pertama memiliki tubuh, maka jawaban kedua tidak. Selain itu, semua tajuk lainnya adalah sama, termasuk yang menyediakan framing permintaan. Ketika proxy mengarahkan kembali HEAD yang ditimpa ke server, itu akan diharapkan dari server tidak hanya header respons, tetapi juga badan respons, yang tidak akan dikirim oleh backend. Jika proksi dan server berinteraksi dalam mode permintaan-respons, maka koneksi akan โ€œhangโ€ hingga terputus oleh batas waktu.

Jika server mengirim jawaban berikut (mode pipelined), maka mereka dapat diurai bukan sebagai jawaban independen, tetapi sebagai bagian dari respons sebelumnya, tidak lengkap untuk GET. Proxy akan menempatkan mereka (atau sebagian dari mereka) di badan respons "GET" dan mengirimkannya ke penyerang untuk membacanya. Anda dapat membuat pseudo-GET tersebut untuk menerima file besar dan membuang beberapa lalu lintas antara proksi dan backend. Keberhasilan tergantung pada bagaimana backend menempatkan Content-Length dan Transfer-Encoding: header chunked untuk membingkai pesan. Yang pertama hampir selalu memungkinkan Anda untuk mendapatkan dump, yang kedua akan sering menghasilkan kesalahan parsing dan menyebabkan pemutusan dari backend. Jika Anda sama sekali tidak beruntung, pseudo-GET dapat mencakup beberapa jawaban secara keseluruhan dan berakhir tepat sebelum jawaban berikutnya.Proxy tidak akan dapat mengenali masalah ini sama sekali dan untuk jawaban lebih lanjut dalam hubungan ini korespondensi permintaan-respons akan dilanggar.


Bahkan jika semua yang dicapai dengan mengganti metode adalah menutup koneksi antara proxy dan backend, maka ini mungkin cukup untuk serangan. Anda dapat mengajukan permintaan layanan dengan permintaan seperti itu - koneksi dengan backend akan terus putus. Jumlahnya tidak terlalu banyak, dan pembukaan kembali membutuhkan waktu, sebagai hasilnya, Anda dapat mencapai penurunan yang signifikan dalam kinerja koneksi backend proxy dan dengan demikian mengurangi bandwidth layanan.

Putar ulang spam otomatis


Saya katakan di atas bahwa permintaan formulir GET + X-HTTP-Method-Override: PATCH dari klien terhormat adalah buruk. Dan ini buruk karena metode memiliki dua properti: keamanan dan idempotensi . Keamanan berarti bahwa metode ini tidak mengubah status server (hanya baca), dan tidak menarik bagi kami dalam konteks artikel ini. Idempotensi metode memastikan bahwa permintaan yang diulang memiliki efek yang sama dengan satu permintaan. Anda dapat menggambar analogi: (a = 5)- permintaan idempoten, dan (a += 2) - non-idempoten.

Properti ini yang menarik minat kami. Jika koneksi antara klien dan server tiba-tiba terputus, klien, mengetahui bahwa metode ini idempoten, dapat secara otomatis mengirim ulang permintaan. Proxy berperilaku dengan cara yang sama. Permintaan non-idempoten tidak secara otomatis diulang karena tidak diketahui bagaimana mereka mempengaruhi server dan apa yang akan diterima klien pada akhirnya. Saya pikir semua orang tahu pop-up di browser: "Apakah Anda yakin ingin mengulangi permintaan?"

Jika Anda menutupi metode non-idempoten sebagai idempoten, maka jika terjadi kesalahan tidak akan dibuang, tetapi akan dialihkan ke server lagi. Bahkan jika klien akan mempertimbangkan metode permintaan sebenarnya sebelum mengirimkan kembali permintaan, ini tidak akan banyak membantu, karena server proxy tidak mengetahui metode menimpa dan akan mengulangi permintaan tersebut.

Jika penyerang dapat memaksa pemutusan antara backend dan klien, ia akan dapat menyebabkan server untuk berulang kali mengeksekusi permintaan non-idempoten dan mengurangi keandalan dan prediktabilitas aplikasi. Di bagian sebelumnya, kami baru saja menemukan cara bagaimana Anda dapat menyebabkan koneksi terputus dengan metode override yang sama. Meskipun harus diingat bahwa Internet adalah jaringan yang tidak dapat diandalkan, menurut definisi, dan aplikasi itu sendiri dalam bahaya.

Untuk melindungi dari serangan ini, Anda harus menggunakan hanya metode yang tidak menambahkan properti baru ke permintaan sebagai transportasi. POST adalah kandidat yang baik, karena secara default tidak aman atau idempoten.

HTTP / 1.1 kuno itu, seperti HTTP / 2?


HTTP / 2 telah mengubah cara permintaan diangkut antar node, tetapi tidak mengubah makna leksikalnya. Oleh karena itu, dalam serangan yang terkait dengan nilai permintaan, HTTP / 2 berperilaku sama. Tetapi serangan โ€œtransportasiโ€ tidak direproduksi, karena sudah diperhitungkan dalam standar.

Serangan pada cache direproduksi dengan cara yang mirip dengan HTTP / 1, dan perlindungannya serupa.

Pesan Serangan antrian tidak berlaku untuk HTTP / 2. Pesan HTTP di dalamnya dibagi menjadi beberapa frame terpisah, dengan header frame terpisah yang secara eksplisit menentukan panjang dan akhir pesan. Seolah-olah penyerang tidak akan mengubah metode dan memodifikasi header HTTP, ini tidak akan mempengaruhi bingkai pesan. Mencuri jawabannya akan gagal.

Serangan pada pengulangan pesan non-idempoten berlaku bahkan dengan mempertimbangkan fakta bahwa dalam HTTP / 2 adamekanisme pemberitahuan permintaan terakhir yang diproses . Dalam HTTP / 2, banyak permintaan dikalikan dalam TCP yang sama dan dengan demikian menciptakan aliran . Setiap utas memiliki nomornya sendiri. Jika server HTTP / 2 terputus, ini dapat menunjukkan jumlah permintaan yang diproses terakhir di GOAWAY. Permintaan dengan nomor yang lebih tinggi selalu aman untuk dialihkan, permintaan dengan nomor yang lebih rendah hanya dialihkan jika mereka idempoten. Jika permintaan dengan metode yang diganti terlihat idempoten untuk server proxy, maka proxy akan meneruskannya ke server.

Cara mengganti metode dengan aman


Jawaban singkatnya tidak mungkin. Lebih baik tidak menggunakan metode menimpa sama sekali. Dan sepenuhnya menonaktifkan dukungan di backend, jika ada. Blokir metode penggantian klien HTTP. Menolak proxy / WAF, yang memotong metode "ekstra".

Jika Anda harus entah bagaimana hidup dengan redefinisi metode, maka untuk mencegah pengeditan cukup ke backend. Pertama, disarankan untuk mengganti metode hanya melalui komponen kueri URI.

Kedua, harus ada daftar putih dari transformasi metode: yang dapat diterima sebagai "transportasi" dan yang merupakan hasil. Seharusnya tidak ada fungsi transformasi umum ketika metode apa pun dapat diganti oleh apa pun. Metode "transportasi" tidak boleh memiliki sifat keamanan dan idempotensi jika yang dihasilkan tidak. Transformasi berbahaya harus dilarang, GET pengganti yang sama -> KEPALA.

Apakah saya perlu menambal proxy masalah / WAF?


Jika proxy hanya mengimplementasikan metode GET dan POST, dan memblokir yang lain karena satu dan lain alasan, pasti ya. Anda dapat mengoptimalkannya terutama untuk GET dan POST, tetapi memblokir metode lain adalah ide yang buruk. Yang masih menciptakan jurang ketidakpercayaan pada produk: jika hal-hal dasar diblokir, apa yang diharapkan dari implementasi masalah yang lebih kompleks?

Jika Anda khawatir tentang keamanan aplikasi web yang dilindungi, maka mungkin ada baiknya untuk mengamankan aplikasi dari metode yang tidak aman dan mengabaikan kebijakan. Tentu saja, dalam kasus umum, tanpa mengetahui detail penerapan aplikasi web, tidak mungkin untuk sepenuhnya melindungi aplikasi dari penggantian yang salah, tetapi Anda dapat sebagian melindungi pengguna yang tidak tahu tentang masalahnya. Diperlukan tidak hanya untuk melindungi dari meracuni cache Anda sendiri, tetapi juga untuk memungkinkan untuk mengaktifkan atau menonaktifkan penggantian untuk setiap aplikasi yang dilindungi. Untuk melakukan ini, perhatikan tajuk yang biasa digunakan.X-HTTP-Method, X-HTTP-Method-Override dan X-Method-Override. Melacak redefinisi dalam komponen kueri URI tidak masuk akal: cache tidak meracuni permintaan seperti itu, dan kueri bisa sangat panjang dan memiliki format yang sepenuhnya arbitrer.

?


Pengembang keamanan, jangan membatasi pengembang aplikasi untuk kebijakan keamanan. Mereka masih akan menemukan cara menyiasatinya, dan semakin fleksibel protokolnya, semakin mudah melakukannya. Sangat mungkin bahwa mereka tidak akan menendang Anda dan menunggu sampai Anda membuat batasan lebih masuk akal, tetapi hanya memotongnya.

Jika Anda menemukan cara mengimplementasikan sesuatu dalam protokol, tetapi menimpa atau bertentangan dengan salah satu konsep kunci standar, maka masalah kompatibilitas dan keamanan pasti akan muncul. Dan mereka perlu dibahas pada saat yang sama dengan keputusan. Setiap saat. Jika Anda bertemu saran tersebut dan tidak melihat peringatan keamanan, maka jangan menduplikasi saran di seluruh Internet. Selalu kritis terhadap keputusan dan mencari tahu apa yang salah .

Alih-alih kata penutup


Apa masalah server proxy yang Anda temui? Apa yang harus dielakkan dan bagaimana?

All Articles