Next.js dan Kerentanan Middleware: Mekanisme Otorisasi yang Tidak Berfungsi

TechubNews
REACT-2,53%

Tulisan: Rachid.A

Yewlne

01 Teks Terjemahan

Baru-baru ini, saya dan Yasser Allam yang menggunakan nama samaran inzo_ memutuskan untuk bekerja sama dalam penelitian. Setelah mendiskusikan beberapa target potensial, kami memutuskan untuk memfokuskan perhatian pada Next.js (yang memiliki 130 ribu bintang di GitHub dan saat ini diunduh lebih dari 9,4 juta kali setiap minggu). Ini adalah kerangka kerja yang sangat saya kenal, dan saya memiliki pengalaman kreatif yang baik dengannya, seperti yang dibuktikan oleh hasil penelitian saya sebelumnya. Oleh karena itu, “kami” dalam artikel ini secara alami merujuk pada kami berdua.

Next.js adalah kerangka kerja JavaScript yang sepenuhnya fungsional berbasis React, dengan fitur yang kaya—tempat yang ideal untuk mendalami detail. Dengan keyakinan, rasa ingin tahu, dan ketahanan, kami memulai perjalanan untuk mengeksplorasi sudut-sudut yang jarang diketahui, mencari harta yang tersembunyi di dalamnya.

Tidak lama setelah itu, kami menemukan masalah besar di dalam middleware. Dampaknya luas, semua versi terpengaruh, dan eksploitasi kerentanan ini tidak memerlukan prasyarat apapun—kami akan segera menjelaskan secara rinci.

Daftar Isi

Middleware Next.js

Alat Otorisasi: Kode Lama Tingkat Harta Karun

Urutan eksekusi dengan middlewareInfo.name

Alat Otorisasi: Kemarin telah menjadi puisi, pagi ini lebih layak.

/src direktori

Kedalaman rekursi maksimum

eksploitasi kerentanan

Menghindari otorisasi/menulis ulang

Melewati CSP

Melakukan DoS melalui pemanasan cache (Apa?)

menjelaskan

Pengumuman Keamanan - CVE-2025-29927

Penyangkalan

Kesimpulan

Middleware di Next.js

Middleware memungkinkan Anda menjalankan kode sebelum permintaan selesai. Kemudian, Anda dapat mengubah konten respons dengan menulis ulang, mengalihkan, memodifikasi permintaan atau header respons, atau langsung mengembalikan respons berdasarkan permintaan yang masuk (diambil dari dokumentasi Next.js).

Sebagai kerangka kerja yang lengkap, Next.js memiliki middleware-nya sendiri — ini adalah fitur penting dan banyak digunakan. Ada banyak skenario penggunaannya, di antaranya yang paling penting adalah:

Penulisan ulang jalur (Path rewriting)

Pengalihan sisi server

Tambahkan informasi header ke respons (seperti CSP dan lainnya)

Hal yang paling penting adalah: otentikasi (Authentication) dan otorisasi (Authorization)

Salah satu penggunaan umum dari middleware adalah untuk melakukan otorisasi, yang melibatkan perlindungan jalur tertentu berdasarkan kondisi tertentu.

Verifikasi dan otorisasi: Pastikan identitas pengguna dan periksa cookie sesi sebelum memberikan akses ke halaman tertentu atau rute API (Dokumentasi Next.js).

Contoh: Ketika pengguna mencoba mengakses /dashboard/admin, permintaan pertama-tama akan melalui middleware, yang akan memeriksa apakah cookie sesi pengguna valid dan apakah pengguna memiliki izin yang diperlukan. Jika verifikasi berhasil, middleware akan meneruskan permintaan; jika tidak, middleware akan mengarahkan pengguna ke halaman login:

Alat Otorisasi: Kode Lama Berharga

Seperti yang pernah dikatakan seorang tokoh besar, “talk is cheap, show me the bug”, mari kita hindari terlalu banyak narasi dan langsung masuk ke inti; saat kami menelusuri versi lama kerangka (v12.0.7), kami menemukan kode ini:

Ketika aplikasi Next.js menggunakan middleware, fungsi runMiddleware disebut. Selain fungsi utamanya, fungsi ini mengambil nilai header x-middleware-subrequest dan menggunakannya untuk menentukan apakah middleware harus diterapkan. Nilai header dibagi menjadi daftar menggunakan titik dua (:) sebagai pemisah, dan daftar diperiksa untuk melihat apakah berisi nilai middlewareInfo.name. Ini berarti bahwa jika kita menambahkan header x-middleware-subrequest dengan nilai yang benar ke permintaan, maka middleware – terlepas dari tujuannya – akan sepenuhnya diabaikan dan permintaan akan diteruskan melalui NextResponse.next() dan jalur ke tujuan awal akan selesai tanpa pengaruh dari middleware. Kepala ini dan nilainya seperti “kunci utama” yang melewati semua aturan. Pada titik ini kami telah menyadari bahwa kami telah menemukan masalah yang luar biasa, dan beberapa potongan terakhir dari teka-teki harus diselesaikan selanjutnya.

Agar “kunci universal” kami berfungsi, nilai tersebut harus mencakup middlewareInfo.name, tetapi apa sebenarnya nilai ini?

Urutan eksekusi dengan middlewareInfo.name

Nilai middlewareInfo.name sangat mudah diperkirakan, itu hanyalah jalur tempat middleware berada. Untuk memahami hal ini, kita perlu memahami secara singkat cara konfigurasi middleware di versi lama.

Pertama, sebelum versi 12.2 — di mana kesepakatan middleware telah berubah — file harus dinamai _middleware.ts. Selain itu, router aplikasi hanya diperkenalkan di versi 13 Next.js. Router yang ada saat itu adalah router pages, sehingga file tersebut harus ditempatkan di dalam folder pages (spesifik untuk router).

Dengan informasi ini, kita dapat menyimpulkan jalur pasti dari middleware, sehingga dapat memperkirakan nilai dari header x-middleware-subrequest. Nilai ini terdiri hanya dari nama direktori (yaitu nama router unik yang ada pada saat itu) dan nama file, mengikuti konvensi penamaan yang dimulai dengan garis bawah pada saat itu:

x-middleware-subrequest: pages/_middleware

Ketika kami mencoba untuk menghindari middleware yang dikonfigurasi untuk secara sistematis mengalihkan upaya akses dari /dashboard/team/admin ke /dashboard:

Berhasil, kami telah menyusup ⚔️

Kita sekarang dapat sepenuhnya menghindari middleware, sehingga dapat melewati sistem perlindungan apa pun yang berbasis padanya, yang paling khas adalah otorisasi, seperti contoh di atas. Temuan ini cukup mengejutkan, tetapi ada poin lain yang perlu dipertimbangkan.

Versi sebelum 12.2 memungkinkan penempatan satu atau lebih file _middleware di mana saja dalam pohon direktori (dimulai dari folder pages), dan mereka memiliki urutan eksekusi, seperti yang terlihat pada tangkapan layar dokumen lama yang kami ambil dari Web Archive:

apa artinya ini bagi eksploitasi kerentanan kita?

Kemungkinan = Jumlah level dalam jalur

Oleh karena itu, untuk mengakses /dashboard/panel/admin (yang dilindungi oleh middleware), ada tiga kemungkinan nilai untuk middlewareInfo.name, dan dengan demikian ada tiga kemungkinan nilai untuk x-middleware-subrequest:

pages/_middleware

atau

pages/dashboard/_middleware

atau

pages/dashboard/panel/_middleware

Alat Otorisasi: Kemarin telah menjadi puisi, pagi ini lebih layak.

Hingga saat ini, kami percaya bahwa hanya versi sebelum 13 yang rentan terhadap serangan, karena middleware telah dipindahkan dalam kode sumber, dan kami belum menutupi semua aspeknya. Kami menduga bahwa pemelihara pasti telah menyadari kerentanan ini dan telah memperbaikinya sebelum perubahan besar di versi 13, jadi kami melaporkan kerentanan ini kepada pemelihara kerangka kerja dan melanjutkan penelitian kami.

Yang mengejutkan kami adalah, hanya dua hari setelah penemuan awal, kami menemukan bahwa semua versi Next.js—mulai dari versi 11.1.4—memiliki celah! Kode tidak lagi berada di lokasi yang sama, dan logika untuk mengeksploitasi celah juga sedikit berubah.

Seperti yang disebutkan sebelumnya, mulai versi 12.2, file tidak lagi menyertakan garis bawah dan harus dinamai sederhana sebagai middleware.ts. Selain itu, file tersebut tidak lagi berada di dalam folder pages (ini sangat nyaman bagi kami karena mulai versi 13, router app diperkenalkan, yang akan menggandakan kemungkinan).

Dengan itu dalam pikiran, payload untuk versi pertama yang dimulai dengan versi 12.2 sangat sederhana:

Mengingat hal ini, payload versi pertama yang mulai dari versi 12.2 sangat sederhana:

x-middleware-subrequest: middleware

/src direktori

Perlu juga dipertimbangkan bahwa Next.js menyediakan kemungkinan untuk membuat direktori /src:

(Dokumentasi Next.js) Sebagai alternatif untuk memiliki direktori Next.js app atau pages yang spesial di direktori akar proyek, Next.js juga mendukung penempatan kode aplikasi di bawah pola umum di direktori src. (Dokumentasi Next.js)

Dalam kasus ini, payload akan menjadi:

x-middleware-subrequest: src/middleware

Oleh karena itu, terlepas dari berapa banyak tingkat dalam jalur, hanya ada dua kemungkinan. Ini menyederhanakan tingkat kesulitan dalam mengeksploitasi kerentanan untuk versi terkait.

Dalam versi terbaru, ada sedikit perubahan lagi (kami jamin, ini yang terakhir).

Kedalaman rekursi maksimum

Dalam versi yang diperbarui, logika sedikit berubah, silakan lihat cuplikan kode ini:

v15.1.7

Sama seperti sebelumnya, sistem akan mengambil nilai dari header x-middleware-subrequest dan membentuk daftar menggunakan titik dua sebagai pemisah. Namun kali ini, syarat untuk meneruskan permintaan secara langsung—yaitu mengabaikan aturan middleware—berbeda:

Nilai konstanta depth harus lebih besar dari atau sama dengan nilai konstanta MAX_RECURSION_DEPTH (yaitu 5). Selama proses penugasan, setiap kali suatu nilai dalam daftar subrequests (yaitu nilai header yang dipisahkan oleh :) sama dengan params.name (yaitu jalur middleware), konstanta depth akan meningkat 1. Seperti yang disebutkan sebelumnya, hanya ada dua kemungkinan di sini: middleware atau src/middleware.

Oleh karena itu, untuk melewati middleware, kita hanya perlu menambahkan header/nilai berikut dalam permintaan:

x-middleware-subrequest: middleware:middleware:middleware:middleware:middleware

atau

x-middleware-subrequest: src/middleware:src/middleware:src/middleware:src/middleware:src/middleware

Apa tujuan awal dari kode ini?

Kode ini tampaknya dirancang untuk mencegah permintaan rekursif terjebak dalam loop tak terbatas.

eksploitasi kerentanan

Karena kami tahu Anda menyukai konten semacam ini, berikut adalah beberapa contoh nyata dari Program Bug Bounty.

Menghindari otorisasi/menulis ulang

Dalam contoh ini, ketika kami mencoba mengakses /admin/login, kami menerima respons 404. Dari header respons, terlihat bahwa middleware telah melakukan penulisan ulang jalur untuk mencegah akses oleh pengguna yang tidak berwenang atau tidak pantas:

Namun, gunakan alat otorisasi kami:

Kami dapat mengakses titik akhir ini tanpa hambatan, middleware sepenuhnya diabaikan. Versi Next.js yang dituju: 15.1.7

Melewati CSP

Situs web kali ini menggunakan middleware untuk mengatur—selain fitur lainnya—CSP dan cookie:

Mari kita lewati itu:

Target next.js versi: 15.0.3Target next.js version: 15.0.3

Perhatian: Harap perhatikan perbedaan payload dari kedua tujuan, salah satunya menggunakan direktori src/ sementara yang lainnya tidak.

Melakukan DoS melalui pemanasan cache (Apa?)

Ya, serangan DoS dengan racun cache juga mungkin bisa direalisasikan melalui celah ini. Ini jelas bukan yang pertama kali kita cari, tetapi jika tidak ada jalur sensitif yang dilindungi, dan tidak ada titik pemanfaatan yang lebih menarik, maka dalam beberapa keadaan bisa menyebabkan layanan ditolak karena racun cache (CPDoS):

Misalkan sebuah situs web menulis ulang jalur pengguna berdasarkan lokasi geografis pengguna, menambahkan (/en, /fr, dll), dan tidak menyediakan halaman atau sumber daya di jalur akar (/). Jika kita melewati middleware, kita akan menghindari penulisan ulang dan akhirnya mencapai halaman akar. Karena pengembang tidak bermaksud untuk membiarkan pengguna mengakses halaman akar, mereka tidak menyediakan halaman yang sesuai, kita akan mendapatkan 404 (atau tergantung pada konfigurasi/tipe penulisan ulang yang berbeda, mungkin 500).

Jika situs web menggunakan sistem cache/CDN, mungkin akan memaksa cache respons 404, menyebabkan halaman tidak tersedia, yang sangat mempengaruhi ketersediaan situs.

menjelaskan

Sejak pengumuman keamanan dirilis, kami menerima beberapa pertanyaan dari orang-orang yang khawatir tentang keamanan aplikasi mereka dan tidak terlalu memahami cakupan serangan. Perlu dijelaskan bahwa elemen yang rentan adalah middleware. Jika Anda tidak menggunakan middleware (atau setidaknya tidak menggunakannya untuk tujuan sensitif), maka tidak perlu khawatir (namun, silakan periksa aspek DoS yang disebutkan di atas), karena melewati middleware tidak akan melewati mekanisme keamanan yang sebenarnya.

Jika tidak, konsekuensinya bisa menjadi bencana, kami sarankan Anda segera melaksanakan langkah-langkah panduan dalam pengumuman keamanan.

Pengumuman Keamanan - CVE-2025-29927

patch

Untuk Next.js 15.x, masalah ini telah diperbaiki di 15.2.3

Untuk Next.js 14.x, masalah ini telah diperbaiki di 14.2.25

Untuk versi Next.js 11.1.4 hingga 13.5.6, kami sarankan untuk merujuk pada solusi berikut.

solusi

Jika tidak dapat memperbarui ke versi yang aman, kami sarankan Anda memblokir permintaan pengguna eksternal yang mengandung header permintaan x-middleware-subrequest untuk mengakses aplikasi Next.js Anda.

Serius

CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:N (Tingkat keparahan: 9.1/10, Kritis)

lebih banyak informasi

Saat artikel ini ditulis, aplikasi yang di-deploy di Vercel dan Netlify jelas sudah tidak lagi terpengaruh oleh kerentanan ini (pembaruan: karena banyaknya laporan salah, Cloudflare telah menyesuaikan aturan ini agar hanya berlaku ketika diaktifkan secara aktif oleh pengguna — laporan salah ini gagal membedakan secara efektif antara permintaan dari pengguna yang sah dan permintaan dari potensi penyerang).

Penyangkalan

Penelitian ini dirilis hanya untuk tujuan edukasi, bertujuan untuk membantu pengembang memahami akar penyebab masalah, atau memberikan inspirasi bagi peneliti / pencari celah dalam pekerjaan penelitian di masa depan. Artikel ini sebagai bahan tambahan untuk pengumuman keamanan, memberikan penjelasan dan klarifikasi lebih lanjut tentang sifat celah - karena pengumuman tersebut telah mengungkapkan header permintaan yang menyebabkan celah tersebut (beserta perbedaan pengajuan yang relevan).

Kami dengan tegas menyatakan tidak mendukung penggunaan tidak etis dari artikel ini.

Kesimpulan

Seperti yang ditekankan dalam artikel ini, kerentanan ini telah ada di dalam kode sumber Next.js selama beberapa tahun, berubah seiring evolusi middleware dan versinya. Setiap perangkat lunak dapat memiliki kerentanan serius, tetapi ketika itu mempengaruhi salah satu kerangka kerja paling populer, itu menjadi sangat berbahaya dan dapat menyebabkan konsekuensi serius bagi ekosistem yang lebih luas. Seperti yang disebutkan sebelumnya, pada saat penulisan artikel ini, jumlah unduhan Next.js hampir 10 juta per minggu. Ini digunakan secara luas dalam bidang-bidang penting mulai dari layanan perbankan hingga blockchain. Ketika kerentanan mempengaruhi fitur mapan yang diandalkan pengguna (seperti otorisasi dan autentikasi), risikonya menjadi lebih besar.

Tim Vercel menghabiskan beberapa hari untuk menyelesaikan kerentanan ini, tetapi yang perlu dicatat adalah, begitu mereka menyadari masalahnya, perbaikan dikirimkan dan digabungkan dalam beberapa jam untuk diterapkan ke versi baru (termasuk porting mundur).

Garis waktu :

27 Februari 2025: Melaporkan kerentanan kepada pemelihara (pada saat itu kami percaya hanya versi 12.0.0 hingga 12.0.7 yang terpengaruh, dan ini dicatat dalam laporan).

1 Maret 2025: Mengirimkan email kedua, menjelaskan bahwa sebenarnya semua versi memiliki kerentanan, termasuk versi stabil terbaru.

5 Maret 2025: Menerima balasan awal dari tim Vercel, yang menyatakan bahwa versi 12.x sudah tidak lagi dipelihara (mungkin belum membaca template pengumuman keamanan yang kami lampirkan dalam email kedua, dan tidak menyadari bahwa semua versi terkena dampak).

5 Maret 2025: Kirim ulang email, mohon tim segera meninjau email kedua dan template pengumuman keamanan.

11 Maret 2025: Kirim email lagi, konfirmasi apakah informasi baru telah diterima.

17 Maret 2025: Menerima balasan dari tim Vercel, mengonfirmasi bahwa informasi terkait telah diterima.

18 Maret 2025: Menerima email dari tim Vercel yang menyatakan bahwa laporan telah diterima dan patch perbaikan telah selesai. Beberapa jam kemudian, versi 15.2.3 yang berisi perbaikan (dan termasuk perbaikan mundur) dirilis.

21 Maret 2025: Pengumuman keamanan resmi dirilis.

Secara keseluruhan, proses mencari kerentanan zero-day hanya menjadi menggembirakan dan memicu adrenalin saat petunjuk ditemukan; sisanya adalah perjalanan penuh ketidakpastian—bagi para penasaran, ini memberikan hasil pengetahuan; bagi mereka yang kurang sabar, perjalanan ini terasa sangat panjang. Jangan ragu, bekerja sama jauh lebih mudah daripada melintasi padang pasir sendirian.

Lihat Asli
Penafian: Informasi di halaman ini dapat berasal dari pihak ketiga dan tidak mewakili pandangan atau opini Gate. Konten yang ditampilkan hanya untuk tujuan referensi dan bukan merupakan nasihat keuangan, investasi, atau hukum. Gate tidak menjamin keakuratan maupun kelengkapan informasi dan tidak bertanggung jawab atas kerugian apa pun yang timbul akibat penggunaan informasi ini. Investasi aset virtual memiliki risiko tinggi dan rentan terhadap volatilitas harga yang signifikan. Anda dapat kehilangan seluruh modal yang diinvestasikan. Harap pahami sepenuhnya risiko yang terkait dan buat keputusan secara bijak berdasarkan kondisi keuangan serta toleransi risiko Anda sendiri. Untuk detail lebih lanjut, silakan merujuk ke Penafian.
Komentar
0/400
Tidak ada komentar