Antipattern: Menggunakan kuantitatif rakit dalam kebijakan RegularExpressionProtection

Anda sedang melihat dokumentasi Apigee Edge.
Buka dokumentasi Apigee X.
info

Kebijakan RegularExpressionProtection menentukan ekspresi reguler yang dievaluasi saat runtime pada parameter input atau variabel alur. Anda biasanya menggunakan kebijakan ini untuk memberikan perlindungan dari ancaman konten seperti injeksi SQL atau JavaScript, atau untuk memeriksa parameter permintaan yang salah format seperti alamat email atau URL.

Ekspresi reguler dapat ditetapkan untuk jalur permintaan, parameter kueri, parameter formulir, header, elemen XML (dalam payload XML yang ditentukan menggunakan XPath), atribut objek JSON (dalam payload JSON yang ditentukan menggunakan JSONPath).

Contoh kebijakan RegularExpressionProtection berikut melindungi backend dari serangan injeksi SQL:

<!-- /antipatterns/examples/greedy-1.xml -->
<RegularExpressionProtection async="false" continueOnError="false" enabled="true"
  name="RegexProtection">
    <DisplayName>RegexProtection</DisplayName>
    <Properties/>
    <Source>request</Source>
    <IgnoreUnresolvedVariables>false</IgnoreUnresolvedVariables>
    <QueryParam name="query">
      <Pattern>[\s]*(?i)((delete)|(exec)|(drop\s*table)|
        (insert)|(shutdown)|(update)|(\bor\b))</Pattern>
    </QueryParam>
</RegularExpressionProtection>

Antipola

Penghitungan default (*, +, dan ?) pada dasarnya bersifat berlebihan: kuantifikasi mulai dicocokkan dengan urutan terpanjang yang memungkinkan. Jika tidak ditemukan kecocokan, sistem akan mundur secara bertahap untuk mencoba mencocokkan pola. Jika string yang dihasilkan yang cocok dengan pola sangat pendek, penggunaan quantifier dapat memakan waktu lebih lama dari yang diperlukan. Hal ini terutama berlaku jika payload-nya besar (dalam puluhan atau ratusan KB).

Contoh ekspresi berikut menggunakan beberapa instance .*, yang merupakan operator greedy:

<Pattern>.*Exception in thread.*</Pattern>

Dalam contoh ini, kebijakan RegularExpressionProtection pertama-tama mencoba mencocokkan urutan terpanjang yang memungkinkan—seluruh string. Jika tidak ditemukan kecocokan, kebijakan akan kembali secara bertahap. Jika string yang cocok mendekati awal atau tengah payload, penggunaan kuantitatif rakus seperti .* dapat memakan lebih banyak waktu dan daya pemrosesan daripada penentu yang enggan seperti .*? atau (lebih jarang) quantifier yang positif seperti .*+.

Penghitung enggan (seperti X*?, X+?, X??) dimulai dengan mencoba mencocokkan satu karakter dari awal payload dan secara bertahap menambahkan karakter. Penghitung yang positif (seperti X?+, X*+, X++) mencoba mencocokkan seluruh payload sekali saja.

Dengan teks contoh berikut untuk pola di atas:

Hello this is a sample text with Exception in thread
with lot of text after the Exception text.

Dalam kasus ini, penggunaan .* yang umum tidak berperforma tinggi. Pola .*Exception in thread.* memerlukan 141 langkah untuk dicocokkan. Jika Anda menggunakan pola .*?Exception in thread.* (yang menggunakan kuantitatif enggan), hasilnya hanya 55 langkah.

Dampak

Menggunakan kuantitatif rakus seperti karakter pengganti (*) dengan kebijakan RegularExpressionProtection dapat menyebabkan:

  • Peningkatan latensi keseluruhan untuk permintaan API untuk ukuran payload sedang (hingga 1 MB)
  • Waktu yang lebih lama untuk menyelesaikan eksekusi kebijakan RegularExpressionProtection
  • Permintaan API dengan payload besar (>1 MB) gagal dengan Error 504 Gateway Timeout jika periode waktu tunggu yang telah ditetapkan berlalu di Edge Router
  • Pemakaian CPU yang tinggi pada Pemroses Pesan karena banyaknya pemrosesan yang dapat berdampak lebih lanjut pada permintaan API lainnya

Praktik terbaik

  • Hindari penggunaan kuantitatif yang serakah seperti .* dalam ekspresi reguler dengan kebijakan RegularExpressionProtection. Sebagai gantinya, gunakan kuantitatif enggan seperti .*? atau pengukur kepemilikan seperti .*+ (lebih jarang) jika memungkinkan.

Bacaan lebih lanjut