Apakah ada cara untuk memasukkan kode berbahaya ke dalam ekspresi reguler?

138

Saya ingin menambahkan kemampuan pencarian ekspresi reguler ke halaman web publik saya. Selain HTML yang mengkodekan output, apakah saya perlu melakukan apa pun untuk melindungi terhadap input pengguna jahat?

Pencarian Google dibanjiri oleh orang-orang yang memecahkan masalah sebaliknya - menggunakan ekspresi reguler untuk mendeteksi input berbahaya - yang saya tidak tertarik. Dalam skenario saya, input pengguna adalah ekspresi reguler.

Saya akan menggunakan perpustakaan Regex di .NET (C #).

MatthewMartin
sumber
4
Ini bisa bergantung pada bahasa apa dan / atau pustaka regex yang Anda gunakan.
aschepler
Beberapa bahan bacaan lagi: ReDoS di OWASP , ReDoS di Wikipedia
joeytwiddle

Jawaban:

216

Masalah Penolakan Layanan

Perhatian yang paling umum dengan regex adalah serangan penolakan layanan melalui pola patologis yang bersifat eksponensial - atau bahkan super eksponensial! - dan tampaknya butuh waktu lama untuk dipecahkan. Ini hanya dapat muncul pada input data tertentu, tetapi umumnya dapat membuat satu di mana ini tidak masalah.

Yang mana ini akan tergantung pada seberapa pintar kompiler regex yang Anda gunakan kebetulan, karena beberapa di antaranya dapat dideteksi selama waktu kompilasi. Kompiler regex yang menerapkan rekursi biasanya memiliki penghitung kedalaman rekursi built-in untuk memeriksa non-progresi.

Makalah Russ Cox 2007 yang luar biasa tentang Pencocokan Ekspresi Reguler Dapat Sederhana dan Cepat (tetapi lambat di Jawa, Perl, PHP, Python, Ruby, ...) berbicara tentang cara NFA paling modern, yang semuanya tampaknya berasal dari kode Henry Spencer , mengalami penurunan kinerja yang parah, tetapi di mana NFA gaya Thompson tidak memiliki masalah seperti itu.

Jika Anda hanya mengakui pola yang dapat dipecahkan oleh DFA, Anda dapat mengkompilasinya seperti itu, dan mereka akan berjalan lebih cepat, mungkin jauh lebih cepat. Namun, perlu waktu untuk melakukan ini. Makalah Cox menyebutkan pendekatan ini dan masalah yang menyertainya. Semuanya bermuara pada pertukaran ruang-waktu klasik.

Dengan DFA, Anda menghabiskan lebih banyak waktu untuk membangunnya (dan mengalokasikan lebih banyak status), sedangkan dengan NFA Anda menghabiskan lebih banyak waktu untuk mengeksekusinya, karena itu dapat berupa beberapa negara sekaligus, dan melakukan backtracking dapat memakan makan siang Anda - dan CPU Anda.

Solusi Penolakan Layanan

Mungkin cara yang paling masuk akal untuk mengatasi pola-pola ini yang berada di ujung yang kalah dari perlombaan dengan kematian-panas alam semesta adalah dengan membungkusnya dengan sebuah pengatur waktu yang secara efektif menempatkan jumlah waktu maksimum yang diizinkan untuk dieksekusi. Biasanya ini akan jauh, jauh lebih sedikit daripada batas waktu default yang disediakan oleh sebagian besar server HTTP.

Ada berbagai cara untuk mengimplementasikannya, mulai dari yang sederhana alarm(N)di level C, hingga semacam try {}memblokir pengecualian tipe alarm tangkapan, semua cara untuk memunculkan thread baru yang secara khusus dibuat dengan batasan waktu yang dibangun tepat di dalamnya.

Panggilan Kode

Dalam bahasa regex yang menerima panggilan kode, beberapa mekanisme untuk membolehkan atau melarang ini dari string yang akan Anda kompilasi harus disediakan. Meskipun panggilan kode hanya untuk kode dalam bahasa yang Anda gunakan, Anda harus membatasi mereka; mereka tidak harus dapat memanggil kode eksternal, meskipun jika mereka bisa, Anda punya masalah yang jauh lebih besar.

Sebagai contoh, di Perl seseorang tidak dapat memiliki kode panggilan dalam regex yang dibuat dari interpolasi string (seperti yang akan terjadi, seperti yang dikompilasi selama waktu run-time) kecuali pragma use re "eval";dengan cakupan leksikal khusus aktif dalam lingkup saat ini.

Dengan begitu, tidak ada yang bisa menyelinap masuk dalam kode panggilan untuk menjalankan program sistem seperti rm -rf *, misalnya. Karena pemanggilan kode sangat peka terhadap keamanan, Perl menonaktifkannya secara default pada semua string yang diinterpolasi, dan Anda harus keluar dari cara Anda untuk mengaktifkannya kembali.

User-Defined \ P {roperties}

Masih ada satu masalah keamanan yang sensitif yang berkaitan dengan sifat Unicode-gaya - seperti \pM, \p{Pd}, \p{Pattern_Syntax}, atau \p{Script=Greek}- yang mungkin ada di beberapa kompiler regex bahwa dukungan yang notasi.

Masalahnya adalah bahwa dalam beberapa di antaranya, sekumpulan properti yang mungkin dapat dikembangkan pengguna. Itu berarti Anda dapat memiliki properti khusus yang merupakan panggilan kode aktual ke fungsi-fungsi yang disebutkan dalam beberapa ruang nama tertentu, seperti \p{GoodChars}atau \p{Class::Good_Characters}. Bagaimana bahasa Anda menangani hal-hal itu mungkin layak dilihat.

Kotak pasir

Di Perl, kompartemen kotak pasir melalui Safemodul akan memberikan kontrol atas visibilitas namespace. Bahasa lain menawarkan teknologi kotak pasir serupa. Jika perangkat tersebut tersedia, Anda mungkin ingin melihatnya, karena mereka dirancang khusus untuk eksekusi terbatas kode yang tidak dipercaya.

tchrist
sumber
4
NFA-> Konversi DFA dapat menghasilkan ledakan keadaan eksponensial, mengubah DoS waktu menjadi DoS ruang, serta biaya waktu menghasilkan jumlah negara eksponensial.
Barry Kelly
tapi mungkin dia tidak akan memerlukan seluruh kemampuan ekspresi reguler, apa yang Anda pikirkan tentang membatasi kekuatan ekspresi reguler seperti yang dilakukan google: google.com/intl/id/help/faq_codesearch.html#regexp
systemsfault
1
@ Barry Cukup benar. Saya telah memikirkan strategi Russ Cox yang dijelaskan dalam salah satu makalahnya yang secara bertahap menyusun bagian-bagian NFA ke dalam DFA yang setara tetapi membuangnya jika terlalu besar. Tetapi tidak ada peluru perak dalam DFA, bahkan jika Thompson memang membuktikannya setara dengan NFA, karena Anda harus membayar piper di beberapa titik. Waktu yang dihabiskan memohon sistem operasi untuk lebih banyak ruang, dan biaya pengaturan tabel-tabel yang hadir, kadang-kadang dapat mendorong skala penyeimbangan lebih jauh dengan cara lain dan membuat konversi dari waktu ke waktu menjadi kurang menarik daripada sebelumnya.
tchrist
20

Menambah jawaban bagus tchrist: Russ Cox yang sama yang menulis halaman "Regular Expression" juga telah merilis kode! re2 adalah pustaka C ++ yang menjamin runtime O (length_of_regex) dan batas penggunaan memori yang dapat dikonfigurasi. Ini digunakan dalam Google sehingga Anda dapat mengetik regex ke dalam pencarian kode google - yang berarti bahwa itu telah diuji pertempuran.

Brian Bloniarz
sumber
2
Memang begitu. Anda dapat menukar re2 ke mesin regex Perl dengan modul, dan itu akan menggunakan re2 jika mungkin dan Perl jika tidak. Bekerja dengan sangat baik.
tchrist
6

Anda ingin membaca makalah ini:

Peralihan Konteks Tidak Aman: Menyuntikkan ekspresi reguler untuk bertahan hidup Makalah ini membahas lebih lanjut tentang apa yang bisa salah dengan mesin ekspresi reguler (misalnya PCRE), tetapi mungkin membantu Anda memahami apa yang Anda hadapi.

Bruce Ediger
sumber
1
Berikut ini adalah penasihat keamanan pada kode regcomp (3) libc GNU: securityreason.com/achievement_securityalert/93 Bagaimana tepat waktu! Setidaknya di bawah linux, kerentanannya mudah ditunjukkan: grep -E ". * {10,} {10,} {10,} {10,} {10,}"
Bruce Ediger
5

Anda tidak hanya harus khawatir tentang pencocokan itu sendiri, tetapi bagaimana Anda melakukan pencocokan. Misalnya, jika input Anda melewati semacam fase eval atau substitusi perintah dalam perjalanan ke mesin ekspresi reguler mungkin ada kode yang dieksekusi di dalam pola. Atau, jika sintaks ekspresi reguler Anda memungkinkan untuk perintah yang disematkan, Anda juga harus waspada terhadap itu. Karena Anda tidak menentukan bahasa dalam pertanyaan Anda, sulit untuk mengatakan dengan pasti apa semua implikasi keamanan itu.

Bryan Oakley
sumber
1

Cara yang baik untuk menguji RegEx Anda untuk masalah keamanan (setidaknya untuk Windows) adalah alat fuzzing SDL RegEx yang dirilis oleh Microsoft baru-baru ini. Ini dapat membantu menghindari konstruksi RegEx yang buruk secara patologis.

RandomNickName42
sumber