Gawat, NextJS terancam... 13 kerentanan BARU

BBetter Stack
컴퓨터/소프트웨어경제 뉴스AI/미래기술

Transcript

00:00:00Terjadi lagi. Ini seperti video ketiga saya tentang CVE komponen server tahun ini dan saya
00:00:05bahkan tidak berpikir telah membahas semuanya. Kali ini ada 13 CVE, ya 13, di seluruh React
00:00:11dan Next.js, 6 di antaranya tingkat keparahan tinggi termasuk denial of service, bypass
00:00:15middleware, cross-site scripting, dan lainnya. Mungkin komponen server adalah sebuah kesalahan.
00:00:20Jadi ini adalah rilis keamanan Next.js, Anda tahu, hanya memperbaiki beberapa masalah biasa di sini
00:00:28yang mereka alami bulan ini dan di bagian bawah tentunya solusinya adalah memperbarui
00:00:32semua versi Next.js Anda dan inilah versi yang terdampak. Perlu dicatat
00:00:36bahwa TanStack tidak terdampak oleh hal ini, saya mungkin bias tapi itu alasan lain menggunakan
00:00:41TanStack bagi saya. Sekarang saya tidak akan membahas semuanya karena kita mungkin akan lama di sini
00:00:44dan saya juga belum menemukan eksploitasi yang berfungsi untuk semuanya, tapi saya ingin menunjukkan satu
00:00:48dari setiap kategori dan kita akan mulai dengan bypass middleware dan proxy, dan yang
00:00:52berhasil saya buat ulang adalah router halaman ini. Jadi kita memiliki bypass proxy middleware di
00:00:56router halaman jika Anda menggunakan i18n dan Anda bisa melihat ini adalah CVE dengan skor
00:01:02keparahan 7,5 dari 10. Ini contoh aplikasi yang rentan, jadi di konfigurasi Next.js saya sudah
00:01:06mengaktifkan i18n dan juga mengatur dua locale yaitu Inggris dan Prancis, lalu saya juga punya file middleware
00:01:12yang sebenarnya sudah diubah namanya menjadi proxy di versi Next.js yang lebih baru untuk mencoba
00:01:16menghindari kebingungan yang akan saya tunjukkan, namun intinya apa yang seharusnya middleware izinkan
00:01:19untuk kita lakukan adalah memodifikasi permintaan masuk, baik itu dengan mengalihkan, menulis ulang,
00:01:24atau menambahkan beberapa header atau hal semacam itu. Dalam kasus saya, saya menggunakannya agar
00:01:28saat kita mencoba mengunjungi halaman /secret, ia akan memeriksa apakah mereka memiliki cookie sesi
00:01:32sehingga mereka sudah login, dan jika tidak, ia akan mengalihkan mereka ke halaman login
00:01:37jadi diharapkan hanya pengguna yang terautentikasi yang bisa melihat halaman rahasia saya.
00:01:41Di bagian bawah kita juga memiliki matcher agar middleware apa pun yang kita terapkan
00:01:45pada halaman rahasia itu juga mencocokkan varian locale-nya karena secara teknis
00:01:50sekarang karena kita punya dua locale, kita punya tiga versi URL ini. Di halaman rahasia itu sendiri
00:01:54saya juga memiliki beberapa server-side props; ini seharusnya diambil dari server pada saat rendering
00:01:58dan sekali lagi karena kita sudah mengatur middleware tersebut, secara teori hanya pengguna yang login yang bisa melihat
00:02:03apa nilai-nilai ini yang kemudian saya gunakan pada halaman itu sendiri seperti email, flag, dan
00:02:07juga headline. Sekali lagi hanya pengguna terautentikasi yang bisa melihat ini. Mari kita
00:02:11uji itu dan hal pertama yang akan saya coba adalah mengakses halaman rahasia itu dan Anda
00:02:16bisa melihat saya dialihkan ke login karena saya tidak login, yang berarti middleware kita berfungsi
00:02:20tapi bagaimana jika kita berubah menjadi peretas ahli? Kita bisa melakukannya dengan cara pertama-tama
00:02:24memeriksa elemen, hal-hal peretasan yang gila, dan kemudian di skrip data next di bawah sini kita perlu mencari
00:02:28ID build kita; dalam kasus saya adalah yang ini, dan kita bisa menyalinnya
00:02:32kemudian kita perlu mengetikkan URL yaitu underscore next slash data slash ID build yang
00:02:37baru saja kita salin dan kemudian halaman yang ingin kita akses titik JSON. Setelah itu dilakukan
00:02:40Anda bisa melihat kita mendapatkan kembali props yang seharusnya berada di balik middleware dan dilindungi
00:02:44yang dalam kasus saya adalah flag, email, headline, juga sesuatu yang menyuruh Anda berlangganan untuk
00:02:48berita pengembang, tutorial, tips, dan trik lainnya. Jadi silakan lakukan itu, saya harap saya sudah membuat Anda terkesan
00:02:52dengan keterampilan peretasan gila saya, tapi mengapa ini sebenarnya terjadi? Yah, yang ini
00:02:56sama mudahnya untuk dijelaskan seperti saat melakukannya karena kita punya halaman rahasia dan beberapa server side props,
00:03:00di Next.js server side props dilayani dari URL yang terlihat seperti ini, tetapi middleware kita
00:03:05seharusnya melindungi rute ini. Masalahnya adalah karena kita menggunakan i18n, kita juga
00:03:09memiliki dua URL lain yaitu varian Inggris dan Prancis, Anda bisa melihat bahwa server side
00:03:13props juga mendapatkan varian Inggris dan Prancis juga, dan Next.js hanya memiliki beberapa kode
00:03:18yang salah yang berarti jika kita mengaktifkan i18n, ia tidak melindungi kasus dasarnya, sehingga
00:03:22ini tidak termasuk dalam matcher tetapi dua lainnya termasuk, jadi versi Inggris dan Prancis dilindungi
00:03:26tetapi bukan kasus dasar dari slash secret. Kita bisa melihatnya dengan cepat jika saya hanya mengubah
00:03:31URL ini ke versi Inggris, saya akan dialihkan ke halaman login. Kerentanan yang sangat sederhana
00:03:35memang, tapi sejujurnya bypass middleware ini sering kali terdengar jauh lebih buruk daripada
00:03:40aslinya; ini tidak bagus tapi Anda tidak seharusnya melindungi banyak hal hanya dengan middleware saja
00:03:44dan Next.js bahkan tidak merekomendasikan Anda melakukannya. Jika Anda memiliki data sensitif
00:03:48dalam server side props tersebut dan Anda tidak memiliki logika otentikasi server, yah saya rasa
00:03:53sebagian masalahnya ada pada Anda juga, jadi mari beralih ke yang lebih merusak yaitu denial of
00:03:56service; ada tiga di antaranya tetapi hanya ada satu yang bisa saya buat ulang dengan andal dan
00:04:01itu adalah yang satu ini yaitu denial of service dengan komponen server dan ini berdampak pada Next.js
00:04:05serta apa pun yang menggunakan paket React server DOM yang pada dasarnya hanya Next.js
00:04:10dan framework lain yang menirunya seperti vinxt dan beberapa fork lainnya. TanStack
00:04:14Start tidak menggunakan ini sehingga tidak rentan. Anda bisa melihat ini juga memiliki tingkat keparahan
00:04:187,5 dari 10. Dengan yang satu ini Anda hanya butuh aplikasi Next.js yang sangat sederhana dan di
00:04:22dalamnya Anda perlu menggunakan server action tetapi sekali lagi itu bisa sangat sederhana. Ini adalah
00:04:25situsnya yang sudah berjalan dan Anda bisa melihat saat saya menyegarkan halamannya hampir
00:04:29tidak ada loading, hampir instan, dan untuk memberi angka nyata di baliknya jika saya mengirim permintaan ini
00:04:34Anda bisa melihatnya selesai dalam 0,02 detik tetapi jika sekarang saya menjalankan eksploitasi saya dan
00:04:39kemudian mengirim permintaan itu lagi, kali ini memakan waktu enam detik dan itu baru dari menjalankan eksploitasi
00:04:42sekali, jadi bayangkan apa yang terjadi jika saya merangkainya. Sekarang untuk memahami eksploitasi ini kita
00:04:46perlu tahu sedikit tentang protokol React Flight yang merupakan format yang digunakan React
00:04:50untuk menserialisasi pohon komponen dan data antara server dan klien. Anda mungkin
00:04:54sebenarnya pernah melihat ini sebelumnya; di halaman ini kita punya formulir yang memiliki server action. Jika saya
00:04:58pergi ke tab network di sini dan mengeklik send, Anda bisa melihat bahwa muatan sebenarnya dikirim
00:05:02sebagai data yang terlihat seperti ini yang tampak seperti omong kosong, dan sama juga untuk
00:05:05responsnya di sini. Jika kita menyalin muatan ini, saya bisa menjelaskan apa yang terjadi saat
00:05:10ia dikirim ke server. Langkah pertama adalah deserialisasi dan itu akan dimulai pada bongkahan 0 di mana kita punya
00:05:16$k1 ini. $k1 ini sebenarnya hanya penunjuk yang mengatakan akan ada beberapa data formulir di sini
00:05:20yang dimulai dengan satu garis bawah, jadi ia akan mengambil semua kunci lain yang kita kirimkan
00:05:24sebagai bagian dari muatan tersebut, ia akan melewati semuanya dan mencari string yang dimulai dengan
00:05:28satu garis bawah dan ia akan tahu ini akan menjadi kuncinya dan ini adalah nilainya. Jadi setelah
00:05:32itu selesai, ia bisa mengatakan kita punya nama, email, pesan, dan ia hanya akan mengubah data ini menjadi
00:05:36objek yang kita miliki di bawah sini. Bagus dan sederhana. Masalah dengan pendekatan ini
00:05:41adalah apa yang terjadi saat kita menskalakannya. Katakanlah saya menambahkan penunjuk lain, kali ini mencari $k2,
00:05:44ini akan mencari semua kunci yang dimulai dengan dua garis bawah. Masalahnya
00:05:48adalah sekarang saat kita berada di $k1, ia akan melewati keenam kunci ini mencari kunci
00:05:52yang dimulai dengan satu garis bawah, dan saat ia ke $k2, ia akan melakukan hal yang sama
00:05:56tetapi mencari kunci yang dimulai dengan dua garis bawah. Jadi kita sekarang melewati 12 kunci
00:06:03secara total. Sekarang itu tidak terlalu buruk, tapi mari kita bawa ini ke titik ekstrem. Jika kita menambahkan 199.999
00:06:07kunci acak ke muatan yang kita kirimkan dan kemudian kita mengubah array kita di nol di sini
00:06:12menjadi $k1, $k2 sampai $k1000, itu berarti ia harus mencari satu garis bawah,
00:06:17dua garis bawah, tiga garis bawah sampai seribu garis bawah di seluruh 200.000
00:06:21kunci yang kita miliki dalam muatan kita, dan itu berarti secara total ia akan melakukan 200 juta perbandingan
00:06:25string. Seperti yang bisa Anda bayangkan, itu akan memblokir thread selama beberapa detik.
00:06:28Ini adalah commit yang saya yakini memperbaiki masalah yang kita alami. Anda bisa melihat ada
00:06:33banyak hal yang terjadi dalam commit ini dan sejujurnya ini agak rumit, tapi saya akan mencoba
00:06:36menjelaskannya sebaik mungkin. Intinya sekarang mereka menggunakan sistem berbasis kursor untuk kuncinya,
00:06:41jadi mereka memuat semua 200.000 kunci yang kita kirimkan dalam muatan kita ke dalam sebuah daftar dan kemudian
00:06:45kita mulai dari nol di sini di mana ia mencari referensi $k1 dan ia mulai menyusuri
00:06:50daftar itu dengan kursor yang tidak bisa mundur. Jadi ia turun ke sini ke $j1, ia melihat itu tidak
00:06:54cocok dengan satu garis bawah yang kita butuhkan, jadi ia ke $j2, itu tidak cocok dengan satu garis bawah
00:07:01juga, jadi ia lanjut terus ke bawah daftar kunci ini sampai ke $j199.999. Setelah
00:07:06mencapai sini, ia menyadari tidak ada kecocokan untuk $k1, jadi ia lanjut ke $k2. Sekarang $k2 mulai mencari
00:07:09dua garis bawah, tapi masalahnya karena ini sistem berbasis kursor dan kursor ini
00:07:14tidak bisa mundur, ia langsung habis di ujung daftar, jadi itu juga akan
00:07:18menjadi tidak terdefinisi dan itu berlanjut sampai ke $k1000. Jadi kali ini kita hanya
00:07:23melewati 200.000 kunci. Intinya perbaikan ini telah mengurangi jumlah operasi dari
00:07:27$k*n di mana $k adalah jumlah referensi $k yang kita punya dan $n adalah jumlah kunci, menjadi
00:07:33hanya $n+k. Jadi dalam kasus kita, kita beralih dari 200.000.000 operasi menjadi 201.000 karena
00:07:37ia masih perlu menyisir semua kunci dan juga referensi $k tersebut. Saya rasa
00:07:41tweet dari Prime ini benar-benar meringkas situasi kita. Membuat protokol sendiri dengan serialisasi
00:07:46sangatlah sulit, jadi tidak mengherankan jika kita melihat banyak masalah ini. Menurut pendapat saya,
00:07:50mereka butuh Claude Mythos untuk meninjau basis kode React dan Next.js. Berikutnya,
00:07:54kita punya CVE dengan tingkat keparahan tertinggi yaitu server-side request forgery dalam
00:07:59aplikasi Next.js. Anda bisa melihat ini diberi peringkat 8,6 dari 10 tetapi perlu juga
00:08:04dicatat bahwa yang satu ini tidak berdampak pada deployment yang dihosting di Vercel, hanya yang dihosting mandiri atau penyedia lain.
00:08:09Eksploitasi ini juga sangat mudah dimanfaatkan. Pertama kita perlu menjalankan server Next.js kita
00:08:14dan sekali lagi ini bisa berupa aplikasi Next.js standar. Anda tidak perlu melakukan modifikasi apa pun.
00:08:18Selanjutnya kita juga butuh server internal. Katakanlah server ini hanya bisa diakses oleh
00:08:23server Next.js dan bukan oleh dunia luar. Katakanlah ini ada di cloud deployment kita.
00:08:26Lalu apa yang akan kita lakukan adalah mengirim permintaan curl sederhana di mana kita mengirim
00:08:31permintaan curl ke aplikasi Next.js kita. Itu tadi ada di port 3002 dan kita katakan bahwa kita ingin
00:08:36target permintaan kita adalah server yang ingin kita akses pada URL localhost tersebut. Jika saya sekarang
00:08:40menekan enter pada ini, Anda bisa melihat apa yang dikembalikan. Sebenarnya itu adalah halaman HTML untuk server Python
00:08:45di mana ia hanya memiliki daftar direktori dasar dan jika saya kembali ke server Python itu sendiri
00:08:49Anda bisa melihat bahwa ada permintaan masuk yang sebenarnya datang dari aplikasi Next.js.
00:08:53Untuk lebih membayangkan apa yang baru saja kita lakukan, katakanlah di dalam garis putus-putus ini adalah deployment Next.js kita
00:08:57jadi kita punya server Next.js dan juga beberapa layanan internal baik itu Redis,
00:09:02database, atau layanan lainnya dan layanan yang satu ini tidak ingin Anda berikan akses ke publik
00:09:06sehingga tidak ada yang bisa mengirim permintaan curl ke sini, itu hanya akan gagal, layanan itu di-firewall dan terkunci
00:09:10dan hanya bisa diakses oleh server Next.js. Apa yang kita lakukan adalah kita hanya mengirim
00:09:15permintaan curl ke server Next.js dan kita bilang hei bisakah kamu mengirim permintaan atas nama kami
00:09:19ke layanan internal dan kita mendapatkan informasi itu kembali, jadi kita sudah melewati firewall itu
00:09:23dengan melewati Next.js yang memang memiliki akses ke layanan internal. Akar penyebab
00:09:28masalah ini juga cukup sederhana, pada dasarnya dalam permintaan curl kita, kita mengirim header upgrade websocket
00:09:32dan saat kita mengirim header ini, apa yang terjadi di Next.js adalah kita sampai ke bagian
00:09:37kode ini dan ini menyelesaikan rute pada URL kita, tetapi URL yang sudah diparsing yang kita dapatkan di sini
00:09:40sebenarnya adalah target permintaan yang kita kirimkan dalam permintaan curl kita, jadi ini akan menjadi
00:09:45target yang kita coba capai di server internal tersebut dan bukan aplikasi Next.js yang sebenarnya.
00:09:49Apa yang terjadi dengan URL yang sudah diparsing ini adalah ia melewati satu pemeriksaan di bawah sini untuk menanyakan apakah
00:09:55URL tersebut punya protokol, tetapi dalam kasus ini jawabannya ya karena kita menggunakan HTTP dan itu adalah protokol
00:09:58jadi ia melanjutkan dan memproksi permintaan itu untuk kita. Perbaikan untuk ini hanya menambahkan dua
00:10:02penjaga baru pada fungsi resolve routes kita yang sebelumnya, sekarang kita mendapatkan boolean finished
00:10:06serta kode status. Apa yang sebenarnya dilakukan fungsi resolve routes ini adalah ia
00:10:11mengambil URL kita dan memproses apakah itu permintaan proksi yang sah berdasarkan rewrite Next.js kita,
00:10:15middleware, dan hal-hal semacam itu; jika tidak, itu berarti finished akan disetel
00:10:20ke false, jadi di bawah sini kita punya pemeriksaan jika finished bernilai true kita bisa lanjut ke langkah berikutnya, jika
00:10:24tidak, disetel ke false sehingga ini tidak akan berjalan yang berarti kita tidak akan menjalankan permintaan proksi kita
00:10:27dan dalam kasus permintaan curl yang kita miliki sebelumnya, itulah tepatnya yang akan
00:10:32terjadi, finished akan disetel ke false. Sekarang jika entah bagaimana finished disetel ke true, pemeriksaan
00:10:36berikutnya adalah kode status, saat resolve routes berjalan kita sebenarnya mendapatkan kode status kembali jika
00:10:41permintaan tersebut adalah permintaan HTTP, jadi kodenya akan 200, 404, apa pun itu, jadi jika ada kode status
00:10:45itu berarti itu bukan permintaan proksi web socket yang valid sehingga ia hanya akan mengabaikan
00:10:49baris ini dan tidak menjalankannya. Saya sudah benar-benar mencoba menyelami masalah ini dalam video ini
00:10:53jadi beri tahu saya jika Anda masih menonton dengan berkomentar sesuatu yang acak, entahlah seperti
00:10:58bar atau semacamnya, dan juga berlangganan jika Anda menghargai konten ini. Kita masih punya dua
00:11:01kategori lagi yang harus dibahas tapi ini harusnya sedikit lebih cepat dan saya akan mulai
00:11:04adalah cache poisoning dalam React server component dan peringkatnya 5,4 dari 10. Untuk membuat ulang
00:11:09ini saya punya aplikasi Next.js tetapi saya juga punya CDN palsu untuk bertindak seolah-olah ini ada
00:11:14di lingkungan yang benar-benar dideploy. Ini berarti jika saya mengunjungi situs saya untuk pertama kalinya pada
00:11:18URL CDN-nya dan kemudian mengeklik browse products lalu kembali dan mengekliknya lagi, pertama kali
00:11:23seharusnya terjadi cache miss dan kemudian berikutnya cache hit. Kita bisa melihat itu terjadi di log
00:11:27di sini, awalnya kita mengalami miss di slash products dengan query string dan kemudian kali berikutnya
00:11:31adalah hit. Apa yang saya lakukan selanjutnya adalah menghapus cache untuk mensimulasikan mungkin cache-nya kedaluwarsa
00:11:35atau hal lainnya dan sekarang saya bisa mengirim permintaan curl ini. Dengan itu kembali ke aplikasi saya,
00:11:39jika saya mengeklik browse products sekarang, Anda bisa melihat kita mendapatkan banyak omong kosong kembali, jadi kita sudah
00:11:44berhasil melakukan serangan cache poisoning. Apa yang saya yakini terjadi di sini adalah saat kita mengirim
00:11:47permintaan curl dengan header react-server-component bernilai satu, URL ini akan mengembalikan data server
00:11:52component-nya, bukannya HTML. Kemudian saat ini perlu di-cache, Next akan melalui
00:11:58sebuah fungsi yang memeriksa apakah itu data server component atau bukan. Jika itu data server component,
00:12:02ia akan menyimpannya dalam cache seperti itu, dan jika bukan, ia akan menyimpannya sebagai HTML. Ini berarti
00:12:07secara teori saat pengguna mencoba mendapatkan versi HTML dari halaman tersebut, misalnya dengan hanya
00:12:11mengeklik tombolnya, ia tidak akan pernah mengembalikan data server component. Masalahnya adalah dalam
00:12:16kasus kita, karena kita memiliki query string di akhir permintaan curl server component kita,
00:12:20ia tidak benar-benar memenuhi persyaratan untuk memeriksa apakah itu server component atau bukan karena
00:12:24itu hanya memeriksa apakah berakhiran .rsc, tetapi versi kita berakhiran dengan query string jadi
00:12:29sekarang ia mengira itu HTML, ia menyimpannya dalam cache sebagai HTML sehingga lain kali pengguna mengeklik
00:12:33tombol itu, mereka sebenarnya mendapatkan data server component kembali karena ia percaya
00:12:37itu adalah HTML. Perbaikan untuk yang satu ini sangatlah sederhana; saat mereka melakukan pemeriksaan apakah
00:12:41berakhiran .rsc, mereka sekarang mengabaikan query string tersebut. Sekarang beralih ke
00:12:46kategori terakhir CVE, kita punya beberapa masalah cross site scripting; ini yang berhasil saya buat ulang,
00:12:50Anda bisa melihat skornya 6,1 dari 10 dan ada cross site scripting pada
00:12:55skrip before-interactive dengan input yang tidak tepercaya. Pada dasarnya itu berarti di Next.js jika saya punya sebuah
00:12:59tag script yang memiliki strategi before-interactive, jika saya kemudian punya atribut lain pada itu yang
00:13:03membutuhkan bentuk konten yang tidak tepercaya, contohnya yang ini berasal dari search params,
00:13:08saya bisa melakukan beberapa cross site scripting, saya bisa melakukannya dengan membuat pengguna mengeklik sebuah tautan seperti
00:13:12ini contohnya, di mana saya sudah menanamkan banyak konten ke dalam search param tersebut; jika seseorang
00:13:16mengeklik tautan itu, inilah yang akan mereka lihat, jadi mereka mungkin mengira mereka harus
00:13:19login kembali ke situs tersebut dan saat mereka mengeklik sign in, Anda bisa melihat di sini bahwa itu adalah formulir
00:13:22login yang sepenuhnya palsu yang disisipkan melalui search param tersebut; ini pada dasarnya memungkinkan penyerang
00:13:26melakukan eksekusi JavaScript pada mesin korban, jadi menurut saya contoh yang lebih realistis
00:13:31adalah mencuri cookie sesi Chrome untuk login ke semua yang Anda punya aksesnya; yang satu ini
00:13:34adalah contoh sederhana dari kesalahan escaping dan kita bisa melihatnya lebih mudah dengan
00:13:39versi yang lebih sederhana ini, tetapi yang saya lakukan dalam search param itu hanyalah saya pertama-tama menutup
00:13:43tag script lalu membuka tag script baru dengan apa pun yang ingin saya jalankan; saat kita menekan
00:13:47enter pada itu Anda bisa melihat saya mendapat peringatan bertuliskan pwned seperti yang saya tunjukkan dengan aplikasi saya;
00:13:51cara kerjanya adalah kita butuh tag script Next.js yang punya strategi before-interactive
00:13:55dan Anda juga menginginkan beberapa atribut pada tag script itu yang mengambil datanya dari suatu sumber
00:13:59yang tidak tepercaya, dalam kasus saya itu berasal dari parameter query; apa yang dilakukan Next.js adalah
00:14:04tag script ini diubah menjadi sesuatu yang seperti ini di mana kita punya dangerouslySetInnerHTML,
00:14:08maksud saya dari namanya saja sudah jelas itu akan berbahaya, dan kita juga punya JSON.stringify.
00:14:12Hal penting yang perlu diketahui tentang JSON stringify adalah ia tidak meng-escape karakter HTML
00:14:17seperti kurung tutup, jadi apa yang sebenarnya terjadi di sini adalah kita mengambil semua tag script
00:14:21yang kita atur di Next.js, ia mencari sumber yang akan diatur di sini dan
00:14:24kemudian sisa propertinya akan berisi data-tracking-id serta nilai yang
00:14:29kita setel di parameter query kita, jadi itu dimasukkan ke dalam JSON stringify; apa yang sebenarnya
00:14:33dirender pada halaman adalah sesuatu seperti ini, jadi kita punya data-tracking-id yang
00:14:37merupakan sisa properti tadi, tetapi kemudian kita juga punya string yang kita masukkan melalui parameter
00:14:41query; jadi jika kita jabarkan apa yang sebenarnya terlihat pada halaman, bentuknya seperti
00:14:45ini, kita punya tag script, kita punya data-tracking-id tetapi kemudian setelah ini kita sebenarnya
00:14:49punya tag script penutup; jadi itu mengakhiri tag script yang coba dilakukan Next.js dan setelah
00:14:53ini kita bisa menjalankan skrip apa pun yang kita mau pada halaman itu, lalu kita juga punya bagian ekstra
00:14:58di akhir sini karena jika kita tidak punya ini, analitik sebenarnya akan dirender pada
00:15:01halaman sebagai teks karena HTML akan melihat ini sebagai teks; jadi bagian ini pada dasarnya hanya menelan
00:15:05teks itu sehingga tidak ada tanda-tanda jelas bahwa sesuatu yang buruk sedang terjadi di halaman itu dan akhirnya
00:15:09begitulah, itu tadi 13 CVE untuk Next.js dan React minggu ini serta bagaimana beberapa di antaranya bekerja dan sejujurnya
00:15:14saya tidak tahu harus berpikir apa tentang ini, saya membencinya dan itu datang dari seseorang yang dua
00:15:18tahunan lalu setiap proyek yang saya kerjakan ada di Next.js dan saya pikir itu adalah yang terbaik dan
00:15:22masa depan, tapi sekarang sepertinya rintangan demi rintangan; rasanya seperti mereka terburu-buru melakukan
00:15:26beberapa hal dan kemudian harus memperbaikinya nanti, secara pribadi sekarang saya benar-benar beralih ke TanStack dan juga
00:15:31Astro saat saya butuh situs berbasis konten; mereka terlihat jauh lebih sederhana bagi saya dan sejujurnya
00:15:35saya juga sangat menyukai apa yang dilakukan Cloudflare belakangan ini, jadi saya perlahan memigrasikan
00:15:39proyek-proyek saya ke sana, tapi saya masih punya sekitar 20 proyek di Vercel dan saya perlu
00:15:43memperbaruinya. Bagaimana menurut Anda, apakah komponen server akan berguna atau kita sudah mencoba dan gagal?
00:15:48Beri tahu saya di kolom komentar di bawah, jangan lupa berlangganan dan seperti biasa, sampai jumpa di
00:15:51video berikutnya.

Key Takeaway

Pembaruan versi Next.js sangat mendesak untuk mengatasi 13 kerentanan keamanan baru yang mencakup risiko kebocoran data internal melalui SSRF dan kelumpuhan server akibat eksploitasi protokol serialisasi React Flight.

Highlights

  • Next.js dan React menghadapi 13 kerentanan CVE baru dengan 6 di antaranya memiliki tingkat keparahan tinggi seperti Denial of Service dan Bypass Middleware.

  • Bypass Proxy Middleware pada Page Router terjadi saat fitur i18n aktif karena sistem gagal melindungi rute dasar (base case) dari akses data JSON melalui URL _next/data.

  • Kerentanan Denial of Service (DoS) pada React Server DOM memungkinkan penyerang memblokir thread utama selama beberapa detik hanya dengan satu permintaan muatan (payload) yang dimanipulasi.

  • Serangan Server-Side Request Forgery (SSRF) dengan skor keparahan 8,6 memungkinkan akses ke layanan internal yang terproteksi firewall melalui header upgrade websocket.

  • Cache Poisoning pada Server Component dapat terjadi ketika permintaan dengan query string diidentifikasi secara keliru sebagai HTML sehingga menyimpan data komponen mentah ke dalam cache publik.

  • Celah Cross-Site Scripting (XSS) ditemukan pada strategi before-interactive di tag script Next.js akibat kegagalan JSON.stringify dalam meng-escape karakter penutup script.

Timeline

Ringkasan 13 Kerentanan Keamanan Baru

  • Terdapat 13 CVE baru yang ditemukan pada ekosistem React dan Next.js tahun ini.
  • Enam dari kerentanan tersebut dikategorikan memiliki tingkat keparahan tinggi.
  • Solusi utama untuk seluruh masalah ini adalah melakukan pembaruan ke versi Next.js terbaru segera.

Daftar kerentanan mencakup masalah kritis seperti Denial of Service (DoS), bypass middleware, dan Cross-Site Scripting (XSS). TanStack Start tidak terdampak oleh masalah ini karena perbedaan arsitektur komponen. Pengguna yang menggunakan hosting mandiri perlu memberikan perhatian lebih pada konfigurasi keamanan mereka.

Bypass Middleware pada Page Router dan i18n

  • Penggunaan i18n pada Page Router memungkinkan bypass middleware melalui URL data build.
  • Middleware gagal melindungi rute dasar (base case) sementara varian locale tetap terlindungi.
  • Data sensitif dalam server-side props dapat terekspos dalam format JSON kepada pengguna yang tidak terautentikasi.

Penyerang dapat mengambil ID build dari skrip halaman dan menyusun URL khusus menggunakan pola _next/data/[build-id]/[page].json untuk melewati pemeriksaan login. Masalah ini berakar pada kode internal Next.js yang tidak memasukkan rute dasar ke dalam matcher saat i18n aktif. Otentikasi tingkat server tetap diperlukan di luar lapisan middleware untuk keamanan yang lebih kuat.

Denial of Service (DoS) pada React Flight Protocol

  • Manipulasi muatan pada Server Action dapat memicu lonjakan waktu proses dari 0,02 detik menjadi 6 detik.
  • Protokol React Flight melakukan perbandingan string berulang yang tidak efisien pada muatan besar.
  • Perbaikan sistem berbasis kursor mengurangi jumlah operasi dari ratusan juta menjadi ratusan ribu.

Eksploitasi ini bekerja dengan mengirimkan ribuan kunci acak dan referensi pointer dalam satu payload. Sebelum diperbaiki, server melakukan pencarian linear berulang untuk setiap pointer di seluruh daftar kunci, yang secara efektif memblokir thread utama. Implementasi sistem kursor satu arah memastikan kursor tidak perlu mundur, sehingga kompleksitas operasi turun drastis menjadi linear.

Eksploitasi SSRF Melalui Header Websocket

  • Header upgrade websocket dapat dimanipulasi untuk memaksa server Next.js mengirim permintaan ke layanan internal.
  • Celah ini memiliki skor keparahan tertinggi sebesar 8,6 dari 10.
  • Layanan yang berada di balik firewall seperti Redis atau database internal dapat diakses oleh penyerang luar.

Dengan mengirimkan permintaan curl yang menyertakan header upgrade websocket dan target URL internal, fungsi resolve routes pada Next.js secara keliru memproses target tersebut sebagai permintaan proksi yang sah. Hal ini memungkinkan penyerang melewati proteksi jaringan luar karena permintaan terlihat datang dari server tepercaya. Perbaikan melibatkan penambahan validasi boolean 'finished' dan pengecekan kode status HTTP untuk memastikan permintaan proksi hanya berjalan pada kondisi yang tepat.

Cache Poisoning dan Cross-Site Scripting (XSS)

  • Header react-server-component yang dikombinasikan dengan query string dapat meracuni cache CDN.
  • Kegagalan escaping pada tag script before-interactive memungkinkan eksekusi JavaScript berbahaya.
  • JSON.stringify tidak secara otomatis mengamankan karakter kurung tutup yang digunakan untuk mengakhiri tag script.

Pada serangan cache poisoning, server menyimpan data komponen mentah ke dalam cache HTML publik karena gagal mengenali ekstensi .rsc yang diikuti query string. Sementara itu, celah XSS terjadi ketika input tidak tepercaya dari parameter query dimasukkan ke dalam atribut skrip. Penyerang dapat menutup tag skrip asli dan menyisipkan skrip baru untuk mencuri cookie sesi pengguna atau menampilkan formulir login palsu.

Community Posts

View all posts