
Hari ini kita akan berbicara tentang salah satu mekanisme keamanan modern untuk aplikasi web, yaitu Web Application Firewall (WAF). Kami akan membahas WAF modern dan apa yang menjadi dasarnya, serta teknik memotong, cara menggunakannya, dan mengapa Anda tidak boleh sepenuhnya bergantung pada WAF. Kita berbicara dari perspektif pentester; kami tidak pernah mengembangkan WAF dan hanya mengumpulkan data dari sumber terbuka. Dengan demikian, kita hanya bisa merujuk pada pengalaman kita sendiri dan mungkin tidak menyadari beberapa kekhasan WAF.
Penafian: ini adalah terjemahan dari artikel dari Bahasa Rusia ke Bahasa Inggris, artikel ini dirilis pada akhir 2017, masing-masing, beberapa informasi bisa menjadi usang.Isi
- Pendahuluan
- WAF modern
- Mengidentifikasi WAF
- WAF memotong cheatsheet
- Bypass WAF dalam praktek
- Kesimpulan
Jika Anda tahu mengapa WAF digunakan dan bagaimana cara kerjanya, Anda bisa langsung melompat ke bagian bypass.Pendahuluan
WAF telah menjadi sangat populer baru-baru ini. Vendor menawarkan berbagai solusi dalam rentang harga yang berbeda, kit distribusi, dan opsi, menargetkan pelanggan yang berbeda, dari bisnis kecil hingga perusahaan besar. WAF populer karena merupakan solusi kompleks untuk melindungi aplikasi web, yang mencakup seluruh spektrum tugas. Itu sebabnya pengembang aplikasi web dapat mengandalkan WAF dalam beberapa aspek keamanan. Meskipun, WAF tidak dapat memberikan keamanan total.

Jadi, apa yang harus WAF mampu untuk membenarkan implementasinya dalam suatu proyek? Fungsi utamanya adalah mendeteksi dan memblokir setiap permintaan yang, menurut analisis WAF, memiliki anomali atau vektor serangan. Analisis tidak boleh menghalangi interaksi antara pengguna yang sah dan aplikasi web sementara pada saat yang sama, harus secara akurat dan tepat waktu mendeteksi setiap upaya serangan. Untuk mengimplementasikan fungsi tersebut, pengembang WAF menggunakan ekspresi reguler, tokenizer, analisis perilaku, analisis reputasi, dan tentu saja pembelajaran mesin. Seringkali, semua teknologi ini digunakan bersama. WAF juga dapat mengimplementasikan fungsi-fungsi lain: perlindungan DDoS, larangan IP penyerang, pemantauan IP yang mencurigakan, menambahkan tajuk keamanan (X-XSS-Protection, X-Frame-Options, dll.), Menambahkan hanya bendera http ke cookie, implementasi dari mekanisme HSTS dan token CSRF. Juga, beberapa WAF memiliki modul sisi klien JavaScript untuk situs web.
Tentu saja, WAF menciptakan beberapa kendala bagi peretas dan pentester. WAF membuat kerentanan menemukan dan mengeksploitasi lebih banyak sumber daya-intensif (kecuali jika penyerang tahu metode bypass 0 hari yang efektif untuk WAF tertentu). Pemindai otomatis praktis tidak berguna ketika menganalisis aplikasi web yang dilindungi WAF. WAF adalah perlindungan yang andal terhadap "scriptkiddies". Padahal, peretas berpengalaman atau peneliti tanpa motivasi yang cukup mungkin tidak akan mau membuang waktu untuk mencari cara untuk memotongnya. Perlu dicatat bahwa aplikasi web yang lebih kompleks adalah semakin besar permukaan serangannya, dan semakin mudah untuk menemukan metode memotong.
Dalam audit terbaru kami, kami sering menemukan WAF yang berbeda. Kami akan membicarakan beberapa di antaranya nanti. Kami telah menguji dua WAF eksklusif dalam dua skenario utama:
- Kami tahu ada kerentanan tertentu dalam aplikasi web dan kami mencoba memotong WAF untuk mengeksploitasinya;
- Kami tidak tahu tentang kerentanan apa pun, jadi kami harus menemukannya di samping WAF dan kemudian memanfaatkannya dengan melewati WAF.
Tapi pertama-tama, mari kita melihat lebih dekat mekanisme dasar di balik WAF dan melihat masalah apa yang mereka miliki.
WAF modern
Untuk dapat secara efektif menemukan berbagai cara untuk memotong WAF, pertama, kita perlu mengetahui mekanisme klasifikasi permintaan yang modern. Setiap WAF dibuat khusus dan unik, tetapi ada beberapa metode analisis umum. Mari kita lihat itu.

Aturan berdasarkan pada ekspresi reguler
Mayoritas WAF yang ada menggunakan aturan berdasarkan ekspresi reguler. Pengembang meneliti serangkaian serangan yang diketahui untuk mengidentifikasi struktur sintaksis kunci yang dapat menunjukkan serangan. Berdasarkan data ini, pengembang membuat ekspresi reguler yang menemukan struktur sintaksis tersebut. Kedengarannya sederhana, tetapi metode ini memiliki kelemahan tertentu. Pertama, ekspresi reguler dapat diterapkan hanya pada satu permintaan, atau bahkan parameter permintaan tunggal, yang jelas-jelas mengurangi efisiensi aturan tersebut dan meninggalkan beberapa titik buta. Kedua, sintaks ekspresi reguler dan logika kompleks dari protokol teks, yang memungkinkan penggantian ke struktur yang setara dan menggunakan representasi simbol yang berbeda, menyebabkan kesalahan saat membuat aturan ini.
Membangun kembali bangunan
Mereka yang tahu cara kerja firewall jaringan dan anti-virus harus terbiasa dengan mekanisme ini. Itu tidak mendeteksi serangan tetapi melengkapi mekanisme lain yang membuatnya lebih tepat dan fleksibel. Masalahnya adalah bahwa struktur "mencurigakan" dalam permintaan bukanlah kondisi yang cukup untuk mendeteksi serangan dan dapat menyebabkan banyak kesalahan positif. Masalah ini diselesaikan dengan menerapkan sistem penilaian. Setiap aturan berdasarkan ekspresi reguler dilengkapi dengan informasi tentang kekritisannya; setelah semua aturan yang dipicu diidentifikasi, kekritisannya dirangkum. Jika kekritisan total mencapai nilai ambang, serangan terdeteksi dan permintaan diblokir. Terlepas dari kesederhanaannya, mekanisme ini terbukti efisien dan banyak digunakan untuk tugas-tugas tersebut.
Tokenizer
Metode deteksi ini disajikan di Black Hat 2012 sebagai
libinjeksi perpustakaan C / C +, yang memungkinkan untuk mengidentifikasi injeksi SQL dengan cepat dan dengan presisi. Pada saat ini, ada banyak port libinjection untuk berbagai bahasa pemrograman, seperti PHP, Lua, Python, dll. Mekanisme ini mencari tanda tangan yang disajikan sebagai satu set token. Sejumlah tanda tangan tertentu dimasukkan dalam daftar hitam, dan dianggap tidak diinginkan dan berbahaya. Dengan kata lain, sebelum beberapa permintaan dianalisis, itu diterjemahkan ke dalam satu set token. Token dibagi menjadi beberapa tipe tertentu, seperti variabel, string, operator reguler, tidak diketahui, angka, komentar, operator seperti serikat, fungsi, koma, dll. Salah satu kelemahan utama dari metode ini adalah kemungkinan untuk membangun struktur yang mengarah pada pembentukan token yang salah, maka tanda tangan permintaan akan berbeda dari yang diharapkan. Struktur ini biasanya disebut sebagai token breaker, dan kita akan membahasnya nanti
Analisis perilaku
Mendeteksi dan memblokir upaya eksploitasi dalam permintaan bukan satu-satunya tugas WAF. Penting juga untuk mengidentifikasi proses pencarian kerentanan dan WAF harus bereaksi sesuai. Ini mungkin memanifestasikan dirinya sebagai upaya pemindaian, kekuatan kasar direktori, pembelahan parameter, dan metode otomatis lainnya. WAF canggih dapat membangun rantai permintaan yang tipikal untuk perilaku normal normal dan memblokir upaya untuk mengirim permintaan yang tidak biasa. Metode ini tidak begitu banyak mendeteksi serangan, karena menghambat proses pencarian kerentanan. Membatasi jumlah permintaan per menit tidak akan memengaruhi pengguna biasa tetapi akan menjadi penghambat serius bagi pemindai, yang bekerja di banyak utas.
Analisis reputasi
Ini adalah mekanisme lain yang secara langsung diwarisi dari firewall dan anti-virus. Saat ini, hampir semua WAF termasuk daftar alamat VPN, anonim, Tor node, dan botnet untuk memblokir permintaan dari mereka. WAF lanjutan dapat secara otomatis memperbarui basis mereka dan melengkapinya dengan entri tambahan berdasarkan lalu lintas yang dianalisis.
Pembelajaran mesin
Ini adalah salah satu aspek WAF yang paling dipertanyakan. Mari kita perhatikan bahwa istilah "pembelajaran mesin" cukup luas dan mencakup banyak teknologi dan metode. Selain itu, itu hanya salah satu kelas AI. "Implementasi" pembelajaran mesin, atau "penggunaan AI" adalah ungkapan pemasaran yang sangat populer. Tidak selalu jelas algoritma mana yang digunakan dengan tepat, dan kadang-kadang terlihat seperti omong kosong belaka. Vendor yang benar-benar menggunakan pembelajaran mesin dan melakukannya secara efektif tidak mau berbagi pengalaman mereka. Itu membuat sulit bagi orang luar untuk mencoba mencari tahu situasinya. Namun demikian, mari kita coba membuat beberapa poin berdasarkan informasi yang tersedia.
Pertama, pembelajaran mesin sepenuhnya tergantung pada data yang dilatihnya, yang menimbulkan masalah tertentu. Pengembang harus memiliki basis serangan terkini dan lengkap, yang sulit dicapai. Itu sebabnya banyak pengembang secara menyeluruh mencatat hasil WAF mereka dan bekerja sama dengan vendor yang menyediakan sistem IDS dan SIEM untuk mendapatkan contoh serangan dunia nyata. Kedua, model yang dilatih pada aplikasi web abstrak mungkin ternyata sama sekali tidak efektif pada aplikasi web nyata. Untuk kualitas yang lebih baik, direkomendasikan untuk melatih model pada tahap implementasi, yang membutuhkan banyak sumber daya dan memakan waktu dan masih tidak memberikan hasil terbaik.
Mengidentifikasi WAF
Pengembang WAF menggunakan berbagai cara untuk memberi tahu pengguna bahwa permintaan diblokir. Dengan demikian, kami dapat mengidentifikasi WAF dengan menganalisis respons terhadap permintaan serangan kami. Ini biasanya disebut sebagai WAF Fingerprint. Sidik jari dapat membantu jika WAF tidak diperbarui karena alasan tertentu (kebanyakan berlaku untuk proyek open source). Para pengembang WAFs eksklusif merawat klien mereka dan mengimplementasikan pembaruan otomatis. Juga, setelah kami mengidentifikasi WAF, yang ternyata diperbarui, kami masih dapat menggunakan informasi tentangnya untuk mempelajari sesuatu tentang logikanya.
Berikut daftar kemungkinan sidik jari WAF:
- Cookie tambahan
- Header tambahan untuk setiap respons atau permintaan
- Isi respons (jika permintaan diblokir)
- Kode respons (jika permintaan diblokir)
- Alamat IP (Cloud WAF)
- Modul sisi klien JS (Sisi klien WAF)
Mari kita ilustrasikan dengan beberapa contoh
PT AFKode respons untuk permintaan yang diblokir: 403
Dapat memasukkan modul klien waf.js ke halaman respons
Tubuh tanggapan:
<h1>Forbidden</h1> <pre>Request ID: 2017-07-31-13-59-56-72BCA33A11EC3784</pre>
Header tambahan yang ditambahkan oleh waf.js:
X-RequestId: cbb8ff9a-4e91-48b4-8ce6-1beddc197a30
Nemesida wafKode respons untuk permintaan yang diblokir: 403
Tubuh tanggapan:
<p style="font-size: 16px; align: center;"> Suspicious activity detected. Access to the site is blocked. If you think that is's an erroneous blocking, please email us at <a href="mailto:nwaf@pentestit.ru">nwaf@pentestit.ru</a> and specify your IP-address. </p>
WallarmKode respons untuk permintaan yang diblokir: 403
Header tambahan: nginx-wallarm
Citrix NetScaler AppFirewallCookie tambahan:
ns_af=31+LrS3EeEOBbxBV7AWDFIEhrn8A000; ns_af_.target.br_%2F_wat=QVNQU0VTU0lP TklEQVFRU0RDU0Nf?6IgJizHRbTRNuNoOpbBOiKRET2gA
Mod_Security ver. 2.9Kode respons untuk permintaan yang diblokir: 403
Badan tanggapan:
<head> <title>403 Forbidden</title> </head><body> <h1>Forbidden</h1> <p>You don't have permission to access /form.php on this server.<br /></p>
Mod_Security ver. <2.9Kode respons untuk permintaan yang diblokir: 406 atau 501
Di badan respons, Anda dapat menemukan mod_security, Mod_Security, atau NOYB
Firewall pernisMenambahkan tajuk berikut ke respons:
X-Varnish: 127936309 131303037. X-Varnish: 435491096 Via: 1.1 varnish-v4
Pengembang WAF memutuskan sendiri kode respons mana yang akan dikembalikan jika ada permintaan yang diblokir; ada beberapa kode spesifik juga. Misalnya, Web_Knight WAF mengembalikan kode 999, dan dotDefender mengembalikan kode 200 dengan badan respons kosong atau dengan pesan kesalahan. Selain itu, pengembang dapat membuat halaman respons khusus dengan beberapa konten lainnya.
WAF, seperti aplikasi lain, berkembang dan berubah. Itu sebabnya penting untuk terus memeriksa relevansi sidik jari yang Anda miliki.
Lembar cheat bypass WAF
Gagasan umum di balik menemukan cara untuk memotong WAF adalah untuk mengubah permintaan yang kami butuhkan sehingga itu masih berlaku untuk aplikasi web tetapi tidak untuk WAF atau tampaknya tidak berbahaya. Sangat penting bagi satu jenis WAF untuk dapat melayani berbagai jenis server, termasuk yang "eksotis", seperti Unicorn, Tornado, Weblogic, Lighttpd, dll. Setiap server dapat melihat kasus-kasus eksklusif permintaan HTTP yang diuraikan dengan cara yang berbeda, yang juga harus dipertimbangkan oleh WAF. Dengan demikian, seorang penyerang dapat menggunakan spesifik server dari permintaan HTTP parsing untuk menemukan cara untuk memotong WAF.

Sulit untuk mengklasifikasikan semua cara yang mungkin untuk memotong WAF baik oleh mekanisme keamanan WAF atau oleh bidang penggunaan. Cara memotong yang sama dapat berinteraksi dan secara simultan mempengaruhi berbagai komponen WAF. Teknik-teknik yang dijelaskan di bawah ini dikumpulkan dari sumber terbuka atau ditemukan selama penelitian kami sendiri dan terbukti menjadi yang paling efektif.
Menambahkan simbol khusus
Berbagai simbol khusus dapat melanggar logika analisis WAF dan pada saat yang sama dapat ditafsirkan oleh server. Variasi dari simbol-simbol ini mungkin berbeda: mereka dapat diubah menjadi urlencode (walaupun sebagian besar WAF dapat mengatasinya) atau pengkodean lainnya. Dimungkinkan juga untuk memasukkan simbol khusus ke dalam permintaan tanpa pengkodean apa pun, dalam format mentah, yang mungkin mengejutkan bagi WAF. Misalnya,
\ r \ n \ r \ n dalam presentasi ini dapat dianggap sebagai akhir dari badan permintaan HTTP, dan null byte dapat melanggar logika analisis ekspresi reguler dan pengurai data secara bersamaan. Juga, simbol khusus lainnya dari dua puluh simbol pertama dari tabel ASCII dapat digunakan.
Contoh:
- 0x00 - Null byte;
- 0x0D - Pengembalian gerbong;
- 0x0A - Umpan baris;
- 0x0B - Tab Vertikal;
- 0x09 - Tab horizontal;
- 0x0C - Halaman baru
Saat mencari bypass, sangat berguna untuk menyisipkan simbol khusus di berbagai tempat di badan permintaan dan tidak hanya ke dalam nilai parameter. Misalnya, jika permintaan dalam format JSON, kami dapat menyisipkan NULL-byte baik ke dalam parameter maupun di antara parameter, baik di awal maupun di akhir JSON. Hal yang sama berlaku untuk format lain dari tubuh permintaan POST. Secara umum, kami sarankan untuk melakukan penelitian dan bersenang-senang, untuk mencari tempat yang dapat dipantau dan diuraikan oleh WAF, dan coba gunakan simbol khusus yang berbeda di sana.
Sebagai contoh:
{"id":1337,"string0x00":"test' or sleep(9)#"} {"id":1337,"string":"test'/*0x00*/ or sleep(9)#"} {"id":1337,"string"0x0A0x0D:"test' or sleep(9)#"}
<a href="ja0x09vas0x0A0x0Dcript:alert(1)">clickme</a> <a 0x00 href="javascript:alert(1)">clickme</a> <svg/0x00/onload="alert(1)">
id=13371 UNION SELECT version(), user()
Untuk lebih jelasnya, kami telah mengganti simbol khusus dengan presentasi hex mereka.Mengganti simbol ruang
Dalam kebanyakan sintaksis, kata-kata kunci dan operator harus dipisahkan, tetapi simbol spasi yang lebih disukai tidak ditentukan. Dengan demikian, alih-alih
0x20 (Spasi) umum, Anda dapat menggunakan
0x0B (Tab Vertikal) atau
0x09 (tab Horizontal). Mengganti ruang dengan struktur pemisah tanpa maknanya sendiri termasuk dalam kategori yang sama. Dalam SQL, itu adalah
/ ** / (komentar SQL multi-baris),
# \ r \ n (komentar SQL satu-baris, diakhiri dengan umpan baris),
- \ r \ n (alternatif komentar satu-baris SQL, berakhir dengan umpan baris). Berikut ini beberapa contohnya:
http://test.com/test?id=1%09union/**/select/**/1,2,3 http://test.com/test?id=1%09union%23%0A%0Dselect%2D%2D%0A%0D1,2,3
Selain itu, kami dapat mengubah ekspresi untuk menghilangkan spasi menggunakan sintaks bahasa. Misalnya, dalam SQL, kita bisa menggunakan tanda kurung:
UNION(SELECT(1),2,3,4,5,(6)FROM(Users)WHERE(login='admin'))
Dan di JS, gunakan
/ :
<svg/onload=confirm(1)>
Mengubah penyandian
Metode ini didasarkan pada penggunaan pengkodean yang berbeda untuk menjaga WAF dari penguraian data di tempat-tempat tertentu. Misalnya, jika simbol diganti dengan kode-URL-nya, WAF tidak akan dapat memahami bahwa simbol harus mendekode data dan akan melewati permintaan. Pada saat yang sama, parameter yang sama akan diterima dan berhasil diterjemahkan oleh aplikasi web.
Bentuk desimal dari simbol HTML adalah
& # 106 atau
& # 0000106 .WAF mungkin tahu tentang versi pendek dan tidak tahu tentang versi dengan nol tambahan (tidak boleh ada total lebih dari 7 simbol). Dengan cara yang sama, bentuk hex simbol HTML adalah
& # x6A atau
& # x000006A .
Ada juga trik melarikan diri karakter dengan backslash
\ , misalnya:
<svg/on\load=a\lert(1)>
Padahal, itu tergantung pada bagaimana aplikasi web memproses data input tersebut. Jadi, urutan
\ l akan diproses sebagai
l dan diubah menjadi simbol tunggal; WAF dapat memproses masing-masing simbol secara terpisah dan dapat merusak ekspresi reguler atau logika WAF lainnya. Dengan demikian, WAF akan kehilangan kata kunci. Dengan menggunakan teknik ini kita tidak dapat melarikan diri karakter
\ n ,
\ r ,
\ t , karena mereka akan diubah menjadi karakter yang berbeda: baris baru, carriage return, dan tab.
HTML-encode dapat digunakan di dalam atribut tag, misalnya:
<a href="javascript:alert(1)">clickme</a> <input/onmouseover="javascript:confirm(1rpar;">
Karakter-karakter ini dapat dengan mudah diganti oleh representasi HTML lain dari karakter target. Anda dapat melihat berbagai transformasi karakter di
sini .
Selain penyandian HTML, kami dapat menyisipkan karakter dengan
\ u :
<a href="javascript:\u0061lert(1)">Clickme</a> <svg onload=confir\u006d(1)>
Mari kita juga melihat vektor yang terkait dengan memasukkan karakter khusus. Mari pecahkan payload dengan HTML encode:
<a href="ja	vas
cript:alert(1)">clickme</a>
Dalam hal ini, kita juga dapat menempatkan karakter pemisah lainnya.
Jadi, kami menyarankan untuk menggabungkan penyandian yang berbeda dengan metode lain, misalnya, untuk menyandikan karakter khusus.
Cari struktur sintaksis setara atipikal
Metode ini bertujuan untuk menemukan cara eksploitasi yang tidak dipertimbangkan oleh pengembang WAF, atau vektor yang tidak ada dalam sampel pelatihan pembelajaran mesin. Contoh sederhana adalah fungsi JavaScript:
ini, diri teratas, orang tua, bingkai; atribut tag:
data-bind, ontoggle, onfilterchange, onbeforescriptexecute, onpointerover, srcdoc; dan operator SQL:
lpad, bidang, bit_count .
Berikut ini beberapa contohnya:
<script>window['alert'](0)</script> <script>parent['alert'](1)</script> <script>self['alert'](2)</script>
SELECT if(LPAD(' ',4,version())='5.7',sleep(5),null);
Anda juga dapat menggunakan representasi non-simbolik dari ekspresi JavaScript:
Masalah yang jelas dengan itu adalah payload yang panjang.
Bypass WAF dengan teknik ini tergantung pada serangan dan tumpukan teknologi yang dieksploitasi. Eksploitasi ImageTragick yang terkenal adalah contoh yang bagus untuk itu. Sebagian besar WAF yang melindungi dari serangan ini memasukkan kata kunci hitam seperti
url ,
kapasitas , dan
label karena kata-kata tersebut disebutkan di sebagian besar makalah dan PoC yang menggambarkan kerentanan ini. Meskipun segera terungkap bahwa kata kunci lain dapat digunakan juga, misalnya,
singkat dan
pango . Akibatnya, WAF dapat dilewati dengan penggunaan kata kunci ini.
HTTP Parameter Pollution (HPP) dan HTTP Parameter Fragmentation (HPF)
Serangan HPP didasarkan pada bagaimana server menginterpretasikan parameter dengan nama yang sama. Berikut beberapa kemungkinan bypass:
- Server menggunakan parameter yang terakhir diterima, dan WAF hanya memeriksa yang pertama;
- Server menyatukan nilai dari parameter yang sama, dan WAF memeriksanya secara terpisah.
Anda dapat membandingkan bagaimana berbagai server memproses parameter yang sama dalam tabel di bawah ini:

Pada gilirannya, serangan HPF didasarkan pada prinsip yang berbeda. Jika logika aplikasi web menyatukan dua dan lebih parameter dalam permintaan, musuh dapat membagi permintaan untuk mem-bypass pemeriksaan WAF tertentu.
Injeksi SQL berikut adalah contoh serangan seperti itu:
http://test.com/url?a=1+select&b=1+from&c=base
HPF dan HPP sangat mirip, tetapi yang pertama menargetkan aplikasi web, dan yang terakhir adalah lingkungan tempat ia beroperasi. Menggabungkan teknik-teknik ini meningkatkan kemungkinan melewati WAF.
Normalisasi Unicode
Normalisasi Unicode adalah fitur Unicode yang dimaksudkan untuk membandingkan simbol Unicode yang mirip. Misalnya, simbol
'ª' dan
'ᵃ' memiliki kode yang berbeda tetapi sangat mirip sebaliknya, jadi setelah normalisasi mereka berdua akan terlihat seperti
'a' yang sederhana dan dianggap sama. Normalisasi memungkinkan transformasi beberapa simbol Unicode kompleks menjadi alternatifnya yang lebih sederhana. Ada
tabel normalisasi Unicode dengan semua simbol Unicode dan kemungkinan normalisasi mereka. Dengan menggunakannya, Anda dapat membuat berbagai muatan dan menggabungkannya dengan metode lain. Meskipun, itu tidak berfungsi untuk semua aplikasi web dan sangat tergantung pada lingkungan.
Sebagai contoh, pada tabel di atas, kita dapat melihat bahwa simbol
<
dan
﹤
berubah menjadi sederhana
<
. Jika aplikasi menggunakan penyandian HTML setelah normalisasi, maka kemungkinan besar simbol yang dinormalisasi
<
akan disandikan ke
<
. Namun, dalam kasus lain, pengembang mungkin mengabaikan fitur ini dan tidak menyandikan simbol Unicode. Dengan demikian, kita mendapatkan simbol yang tidak dikodekan HTML
< dan
> , yang dapat diubah menjadi serangan XSS. WAF mungkin mengalami kesulitan dalam memahami simbol Unicode - itu mungkin tidak memiliki aturan untuk trik seperti itu, dan pembelajaran mesin mungkin juga tidak berguna. Saat menemukan bypass di aplikasi web dengan normalisasi Unicode, kita dapat mengganti tidak hanya
<> tetapi simbol lain dari payload juga.
Sebagai contoh:
<img src﹦x onerror=alert︵1)>
Baru-baru ini, masalah ini ditemukan di program Rockstar BugBounty di HackerOne. Tidak ada WAF, hanya penyaringan input pengguna yang ketat:
hackerone.com/reports/231444hackerone.com/reports/231389Pemecah tanda
Serangan pada tokenizers berusaha untuk mematahkan logika pemisahan permintaan menjadi token dengan bantuan yang disebut token breaker. Token breakers adalah simbol yang memungkinkan memengaruhi korespondensi antara elemen string dan token tertentu, dan dengan demikian mem-bypass pencarian dengan tanda tangan. Tetapi saat menggunakan token breaker, permintaan harus tetap valid. Permintaan berikut adalah contoh serangan menggunakan token breaker
SELECT-@1,version()
dimana
- @ adalah token breaker.
Ada
lembar chear yang diakuisisi oleh mysql fuzzing dan memeriksa hasilnya di libinjection.
Lebih lanjut tentang menemukan masalah dalam libinjection:
Fuzzer lainFuzz untuk memotongCara memintas libinjectionMenggunakan fitur RFC
Dalam spesifikasi untuk protokol HTTP / 1.1 dan berbagai jenis permintaan (mis. Multipart / formulir-data), kita dapat menemukan beberapa hal aneh terkait dengan kasus batas dan trik pemrosesan header dan parameter. Pengembang WAF sering tidak mempertimbangkan masalah seperti itu, maka WAF dapat menguraikan permintaan secara salah dan melewatkan bagian data, tempat vektor serangan disembunyikan. Sebagian besar masalah dalam WAF terkait dengan pemrosesan multipart / formulir-data dan nilai-nilai spesifik dari parameter batas, yang menentukan batas parameter dalam permintaan tersebut. Selain itu, pengembang server mungkin juga melakukan kesalahan dan tidak mendukung spesifikasi sepenuhnya, sehingga mungkin ada fitur tidak berdokumen dalam pengurai HTTP server.
Dalam permintaan HTTP dengan data multi-bagian / formulir, batas parameter bertanggung jawab atas pemisahan parameter yang berbeda di badan permintaan. Menurut RFC, batas yang ditentukan sebelumnya dengan awalan yang mengandung "-" harus diletakkan sebelum setiap parameter POST baru, sehingga server dapat membedakan parameter yang berbeda dari permintaan.
POST /vuln.php HTTP/1.1 Host: test.com Connection: close Content-Type: multipart/form-data; boundary=1049989664 Content-Length: 192 --1049989664 Content-Disposition: form-data; name="id" 287356 --1049989664--
Serangan juga dapat didasarkan pada kenyataan bahwa server dan WAF berbeda menangani situasi di mana batas dibiarkan kosong. Menurut RFC, dalam hal ini, "-" adalah batas antara parameter. Namun demikian, WAF dapat menggunakan parser yang tidak mempertimbangkan hal itu, dan, sebagai akibatnya, WAF akan meneruskan permintaan tersebut karena data dari parameter permintaan POST tidak akan muncul di penganalisa. Server web dapat mengurai permintaan seperti itu tanpa masalah dan menyerahkan data untuk diproses lebih lanjut.
Berikut ini beberapa contoh yang lebih menarik.
POST /vuln.php HTTP/1.1 Host: test.com Connection: close Content-Type: multipart/form-data; boundary= Content-Length: 192 -- Content-Disposition: form-data; name="id" 123' or sleep(20)# ----
Kami akan memberikan beberapa contoh yang lebih menarik dari
slide oleh
Bo0oM di ZeroNights 2016 dan menjelaskannya:
POST /vuln.php HTTP/1.1 Host: test.com Content-Type: multipart/form-data; boundary=FIRST; Content-Type: multipart/form-data; boundary=SECOND; Content-Type: multipart/form-data; boundary=THIRD; --THIRD Content-Disposition: form-data; name=param UNION SELECT version() --THIRD--
Dalam serangan ini, kami mencoba menentukan salah satu parameter batas yang akan diterima oleh WAF dan yang oleh server web. Dengan demikian, jika mereka akan menerima parameter yang berbeda, dimungkinkan untuk melakukan serangan dengan menentukan batas yang WAF tidak akan lihat. Serangan ini agak mirip HPP.
POST /vuln.php HTTP/1.1 Host: test.com Content-Type: multipart/form-data; xxxboundaryxxx=FIRST; boundary=SECOND; --FIRST Content-Disposition: form-data; name=param UNION SELECT version() --FIRST--
Serangan ini didasarkan pada asumsi bahwa ada perbedaan dalam penguraian permintaan HTTP oleh WAF dan oleh server web. Yaitu, pengurai server web mencari entri 'batas' pertama, dan kemudian untuk simbol '=', dan hanya setelah itu mendefinisikan nilai batas. Pengurai WAF, pada gilirannya, hanya mencari entri "boundary =" dan kemudian mendefinisikan batas. Jika kondisi ini terpenuhi, WAF tidak akan menemukan batas dalam permintaan, dan karenanya tidak akan dapat menemukan dan menganalisis parameter. Sebaliknya, server web akan mendapatkan permintaan dan memproses parameter. Serangan ini juga akan bekerja sebaliknya: parser server web mencari "boundary =", dan parser WAF hanya mencari 'batas'. Dalam hal ini, kita hanya perlu mengubah batas nyata dari PERTAMA ke DETIK.
POST /somepage.php HTTP/1.1 Host: test.com Content-Type: multipart/form-data; boundary=Test0x00othertext; --Test Content-Disposition: form-data; name=param Attack --Test--
Serangan ini juga menggunakan karakter khusus. Pada parameter batas, kami menambahkan NULL-byte sehingga server web akan memotongnya, tetapi WAF akan menerimanya secara penuh. Dalam hal ini, WAF tidak dapat menganalisis parameter karena tidak dapat menemukan batasannya.
Melewati pembelajaran mesin
Logikanya sederhana: kita harus menyusun serangan yang akan memenuhi parameter model statistik terlatih. Tapi itu sangat tergantung pada bagaimana WAF dilatih dan model pelatihan apa yang digunakan. Terkadang mungkin untuk menemukan celah, dan terkadang tidak. Biasanya, pada tahap implementasi, WAF dengan pembelajaran mesin membutuhkan pelatihan tambahan berdasarkan permintaan ke aplikasi web klien. Itu menimbulkan masalah bagi pentester: parameter yang mirip dan tidak banyak berubah dari permintaan ke permintaan tidak dapat diuji, karena setiap penyimpangan dari bentuk parameter biasa akan dianggap sebagai anomali. Katakanlah cara memiliki permintaan ke
api.test.com/getuser?id=123 . Parameter id selalu numerik, dan itu numerik dalam sampel pelatihan. Jika modul pembelajaran mesin menemukan sesuatu selain angka dalam parameter ini, kemungkinan besar akan memutuskan bahwa itu adalah anomali. Contoh lain: misalkan WAF dilatih untuk mengklasifikasikan permintaan POST ke
api.test.com/setMarkDown dengan parameter POST yang memiliki teks penurunan harga. Jelas, mungkin ada tanda kutip, simbol khusus, dan pada dasarnya apa pun yang ada di bawah. Dalam hal ini, jauh lebih mudah untuk mem-bypass modul pembelajaran mesin karena WAF mentoleransi kutipan dan simbol khusus.
Selain itu, pada contoh dari praktik kami, kami akan menunjukkan bahwa itu tidak selalu sejauh modul pembelajaran mesin karena masalah dengan penguraian parameter yang disebabkan oleh metode memotong yang dijelaskan di atas.
Secara umum, kami harus mempertimbangkan secara spesifik permintaan yang diuji dan parameternya, mengandaikan opsi yang memungkinkan dari nilai parameter, yang WAF mungkin toleran terhadapnya, dan membangunnya.
Kapan WAF tidak berguna?
WAF menganalisis permintaan dan mencari perilaku aneh di dalamnya, tetapi ada beberapa kelas kerentanan yang tidak dapat ditemukan. Misalnya, kerentanan logika, yang tidak memiliki anomali tetapi memiliki beberapa tindakan yang mengganggu logika aplikasi web. Kemungkinan besar, WAF juga tidak berguna jika kondisi ras, IDOR, dan otentikasi pengguna tidak aman.
Utilitas yang ada
Ada beberapa alat otomatis untuk menemukan bypass WAF, yang ditulis oleh para penggemar di bidang ini. Inilah yang paling terkenal dan layak:
lightbulb-framework - seluruh kerangka kerja untuk menguji aplikasi web yang dilindungi dengan WAF. Ini ditulis dengan Python dan juga porting sebagai plugin untuk Burp Suite. Fitur utamanya adalah dua algoritma ini:
- GOFA - algoritma pembelajaran mesin aktif yang memungkinkan menganalisis penyaringan dan sanitasi parameter di aplikasi web.
- SFADiff - algoritma pengujian kotak hitam deferential, berdasarkan pelatihan dengan automate terbatas simbolik (SFA). Ini memungkinkan menemukan perbedaan dalam perilaku aplikasi web yang membantu mengidentifikasi WAF dan menemukan bypass.
Bypass WAF - sebuah plugin untuk Burp Suite, yang memungkinkan pengaturan perubahan elemen secara otomatis di tubuh permintaan sesuai dengan aturan yang berbeda dan penyandian perubahan. Itu juga dapat mengotomatiskan serangan HPP.
WAFW00F - alat untuk identifikasi WAF, ditulis dengan Python. Ini memiliki basis WAF yang layak dan masih diperbarui. Meskipun, hasilnya mungkin tidak tepat karena banyak WAF diperbarui lebih sering daripada proyek itu sendiri.
Memotong waf dalam praktik

Kami telah menjalankan uji penetrasi toko online, yang dilindungi oleh
PT AF (Positive Technologies Application Firewall). Sulit menemukan titik lemah, yang bisa menjadi basis untuk memotong. Namun segera kami menemukan perilaku yang tidak biasa di sisi aplikasi web, yang tidak difilter oleh WAF. Anomali itu ditemukan dalam pencarian dalam sejarah barang yang dibeli. Permintaan dikirim dalam format JSON dan terlihat seperti itu:
{"request":{"Count":10,"Offset":0,"ItemName":"Phone"}}
Kami menempatkan
Telepon ' dan
Telepon' + ' , nilai ke dalam parameter
ItemName dan menemukan bahwa server mengembalikan respons yang berbeda untuk dua permintaan ini. Dalam kasus pertama, responsnya kosong; dalam kasus kedua, itu berisi data tentang barang lain dengan kata
Phone dalam nama mereka, seolah-olah parameter
ItemName memiliki
Telepon sebagai nilainya. Perilaku semacam ini sangat dikenal di kalangan peretas dan pentester dan menunjuk ke masalah aplikasi dengan penyaringan input pengguna, yang mengarah ke injeksi SQL antara lain.
Mari kita lihat mengapa ini terjadi dengan contoh injeksi SQL. Jika perilaku seperti itu ditemukan dalam aplikasi web, maka sangat mungkin bahwa data untuk permintaan SQL sesuai dengan permintaan itu sendiri. Dalam kasus pertama, dengan parameter
Phone ' , kita akan memiliki kueri SQL berikut:
SELECT item FROM items WHERE item_name='Phone''
Jelas, itu tidak akan dieksekusi karena sintaks yang salah dan tidak akan mengembalikan hasil apa pun. Permintaan kedua, dengan parameter
Ponsel '+' , akan terlihat seperti ini:
SELECT item FROM items WHERE item_name='Phone'+''
Sintaksnya benar, sehingga akan memilih barang dengan nama
Telepon . Metode mendeteksi kerentanan ini memiliki keuntungan besar saat menguji aplikasi web yang dilindungi oleh WAF. Simbol kutipan tunggal tidak dianggap sebagai anomali yang cukup dalam suatu parameter oleh sebagian besar WAF modern, sehingga mereka menyampaikan permintaan dengannya.
Kami telah menjelaskan deteksi kerentanan, tetapi bagaimana dengan melewati WAF dan mengeksploitasi kerentanan? Setelah melewati beberapa bypass, kami menemukan masalah di WAF. Ternyata WAF ini rentan terhadap karakter khusus yang ditambahkan ke parameter JSON. Bahkan, jika kita menambahkan simbol JSON
0x0A, 0x0D (\ r \ n atau carrige reutrn dan baris baru) dalam format mentah, tanpa pengkodean apa pun, ke bidang teks apa pun, WAF akan meneruskannya, dan aplikasi web akan mempertimbangkannya untuk menjadi benar dan memprosesnya. Kemungkinan besar, masalahnya adalah di parser JSON, yang tidak dibuat untuk simbol khusus dan diurai JSON sampai tempat di mana simbol-simbol ini akan muncul. Dengan demikian, penganalisa WAF tidak akan mendapatkan permintaan penuh, jadi kami dapat memasukkan vektor serangan apa pun setelah karakter khusus. Selain jeda baris, karakter lain (misalnya NULL-byte) juga akan berfungsi. Sebagai hasilnya, kami dapat menulis permintaan berikut, yang akan mematikan WAF ketika mencoba memeriksa permintaan ini (penghentian baris dan carriage return digantikan dengan representasi tekstual mereka):
{"request":{"kill-waf":"die0x0A0x0D", "Count":10,"Offset":0,"ItemName":["'+(SELECT 'Phone'+CHAR(ASCII(substring(@@version,1,1))-24))+'"]}}
0x0A dan 0x0D adalah byte mentah.Dengan demikian, kami dapat dengan mudah dan cepat menguji semua parameter untuk kerentanan apa pun (beberapa di antaranya ditemukan di parameter lain). Memotong WAF dan mengeksploitasi injeksi ini memungkinkan kami untuk benar-benar membahayakan semua pengguna aplikasi web.
Masalah yang sama juga ditemukan di
Nemesida WAF . Satu-satunya perbedaan adalah, permintaan itu tidak dalam pengkodean JSON, tapi itu adalah permintaan POST biasa dengan parameter, dan parameter disatukan dengan permintaan SQL sebagai angka. Jika beberapa simbol ditempatkan dalam permintaan dalam url-encode, misalnya,
% 03% 04 lalu WAF memblokir permintaan, tetapi jika simbol ditempatkan dalam bentuk mentah tanpa pengkodean url maka WAF mengabaikan permintaan ini. Perlu dicatat, bahwa ekspresi-SQL normal ditempatkan untuk meminta serta dalam WAF sebelumnya. Ekspresi SQL sederhana
'UNION SELECT' tanpa kebingungan tambahan, yang berarti bahwa WAF tidak bisa menguraikan permintaan dengan benar dan meneruskan analisis lebih lanjut. Tetapi ada satu masalah - bagaimana cara membuat sintaks SQL-query benar? Karena menggunakan karakter khusus seperti
% 03% 04 di SQL-query tidak benar. Jawabannya sederhana - kita hanya perlu menggunakan komentar / ** /. Jadi, permintaan hasil tampak seperti:
1 UNION SELECT version(), user()
0x03 dan 0x04 adalah byte mentah.Juga, masalah lain ditemukan di Nemesida WAF. Itu terkait dengan pemrosesan yang salah dari permintaan POST dengan multipart / formulir-data. Seperti yang kami jelaskan di bawah ini, dalam permintaan HTTP dengan multipart / form-data,
batas parameter bertanggung jawab atas pemisahan parameter yang berbeda di badan permintaan. Menurut RFC, batas yang ditentukan sebelumnya dengan awalan yang mengandung
"-" harus diletakkan sebelum setiap parameter POST baru, sehingga server dapat membedakan parameter yang berbeda dari permintaan.
Jadi, masalahnya adalah bahwa server dan WAF menangani situasi secara berbeda ketika parameter batas kosong. Berdasarkan RFC, dalam situasi seperti itu batas antara parameter akan menjadi urutan karakter
"-" . Namun, WAF menggunakan parser yang tidak memperhitungkan fitur ini, itulah sebabnya WAF sekali lagi meneruskan permintaan, karena data dari parameter permintaan POST tidak masuk ke modul penganalisa, dan server mem-parsing situasi ini tanpa masalah dan mentransfer data lebih lanjut ke pemrosesan. Ini adalah contoh permintaan untuk serangan ini:
POST /wp-content/plugins/answer-my-question/modal.php HTTP/1.1 Host: example.com Content-Type: multipart/form-data; boundary= Content-Length: 209 -- Content-Disposition: form-data; name="id" 1 UNION SELECT 1,2,3,CONVERT(version() USING utf8) AS name,CONVERT(user() USING utf8) AS name,6,7,8,9,10,11,12 FROM wp_users WHERE id=1 ----
Kedua masalah itu dilaporkan ke Pentestit, orang-orang membayar hadiah untuk program karunia bug mereka untuk Nemesida WAF, dan memperbaiki masalah sesegera mungkin. Terima kasih untuk itu.
Seperti yang bisa kita lihat, WAF mungkin modern dan cerdas, tetapi kadang-kadang dimungkinkan untuk memotongnya hanya dengan menambahkan satu karakter khusus. Hari ini kita tidak dapat melihat semua jenis input data yang mungkin untuk semua server pada tahap pengembangan, dan pembelajaran mesin, dilaksanakan untuk melakukan hal itu, menemukan parser yang terjebak dengan karakter khusus.
Kesimpulan

Jadi, haruskah kita sepenuhnya mengandalkan WAF?
Jawabannya adalah TIDAK.Dalam salah satu audit kami, kami telah menemukan bypass WAF yang memungkinkan kami untuk mengeksploitasi beberapa kerentanan. Ternyata, para pengembang sudah melakukan audit aplikasi web, sebelum dilindungi oleh WAF, dan itu mengungkapkan kerentanan yang sama. Alih-alih memperbaikinya, mereka memutuskan untuk membeli WAF modern yang dilengkapi dengan pembelajaran mesin. Sangat disayangkan bahwa vendor WAF tidak bersikeras untuk memperbaiki kerentanan terlebih dahulu; atau mungkin para pengembang sendiri berpikir bahwa WAF akan menjadi pilihan yang lebih baik. Kami tidak tahu pasti. Either way, ini adalah contoh praktik yang sangat buruk, pada bagian dari pengembang dan vendor. Perlu juga dicatat bahwa pembelajaran mesin masih berupa kotak hitam dan lebih mirip alat pemasaran daripada pertahanan nyata.
Secara umum, WAF adalah solusi keamanan modern, dan tidak ada salahnya dengan aplikasi web Anda. Meskipun saat ini, itu hanya dapat menghambat proses pencarian kerentanan dan eksploitasi, tetapi tidak dapat melindungi mereka sama sekali. Sudah barang tentu, ini adalah keadaan seni untuk sementara waktu. Kerentanan dalam aplikasi web hanya dapat diperbaiki dengan memperbaiki kode yang terkait dengannya, dan itulah satu-satunya solusi yang sangat mudah.
KontributorIlia Bulatov barracud4Denis Rybin thefaeriedragonAlexander Romanov web_rock