- Dalam peninjauan backend aplikasi kencan mobile Feeld, ditemukan 8 kerentanan, termasuk paparan profil, pembacaan dan modifikasi pesan, serta akses ke lampiran chat. Semua kecuali yang pertama termasuk dalam kategori Broken Access Control di OWASP Top 10
- Pengguna dasar hanya melihat informasi terbatas di layar aplikasi, tetapi saat respons diperiksa lewat proxy, mereka dapat menerima informasi setingkat premium seperti usia, jarak, foto profil, dan streamUserId dari pengguna yang memberi “Like”
- Beberapa kerentanan saling berlanjut dengan cara mengambil identifier seperti streamUserId, profileId, messageId, dan channelID dari respons API lain lalu memasukkannya sebagai parameter permintaan, sehingga cakupan akses meluas ke pesan, match, profil, Like, hingga pengiriman chat milik orang lain
- Masalah pada lampiran chat terkonfirmasi pada foto biasa, foto terbatas 5–15 detik, video biasa, dan video sekali putar; sebagian URL Cloudinary dan Stream CDN dapat diakses tanpa autentikasi
- FORTBRIDGE mengungkapkan isu ini kepada Feeld pada 8 Maret 2024, dan setelah Feeld beberapa kali meminta penundaan publikasi, Feeld menjawab pada 16 Agustus 2024 bahwa mereka telah menerapkan perubahan untuk memitigasi temuan yang tersisa; blog dipublikasikan pada 10 September 2024
Cakupan kerentanan yang ditemukan di Feeld
- Targetnya adalah Feeld, aplikasi kencan mobile yang mirip Tinder dan Bumble, yang menyediakan filter berdasarkan jarak, usia, gender, pasangan, dan lokasi
- Pengguna premium juga dapat mencari berdasarkan jenis kink, skenario threesome/group, dan jenis hubungan yang diminati
- Ada 8 kerentanan yang ditemukan dalam peninjauan keamanan
- Paparan informasi profil kepada pengguna non-premium
- Membaca pesan orang lain
- Akses tanpa autentikasi ke lampiran foto dan video chat
- Menghapus, memulihkan, dan mengubah pesan orang lain
- Memperbarui informasi profil orang lain
- Menerima “Like” dari profil pengguna arbitrer
- Mengirim pesan ke chat orang lain
- Melihat match orang lain
- Semua isu selain yang pertama termasuk dalam kategori Broken Access Control di OWASP Top 10
Informasi profil yang terekspos kepada pengguna non-premium
- Saat pengguna dasar melihat pengguna yang menyukainya dari menu Likes di aplikasi, hanya nama dan foto buram yang ditampilkan
- Jika permintaan dan respons dicegat dengan alat proxy seperti Burp, respons tersebut berisi informasi dengan tingkat yang sama seperti pengguna premium
- Usia
- Jarak
- Foto profil lengkap
- streamUserId
- Foto profil disimpan di
res.cloudinary.comdan dapat diakses tanpa autentikasi - streamUserId yang diperoleh dari respons dapat digunakan kemudian dalam kerentanan untuk membaca pesan orang lain
Masalah kontrol akses pada pesan dan match
- Untuk membaca pesan orang lain, diperlukan streamUserId milik korban, dan nilai ini terekspos di beberapa permintaan API
- Contoh alurnya adalah mendapatkan streamUserId pengguna target dari respons permintaan GraphQL
DiscoverProfiles, lalu memasukkan nilai tersebut ke kondisimemberpada permintaan channel chat - Dengan mencari
"text"dalam respons, jumlah dan isi pesan yang dikirim dan diterima korban dapat dilihat - Dengan pendekatan yang sama, messageId yang melekat pada setiap pesan juga dapat diperoleh, dan nilai ini digunakan untuk menghapus, memulihkan, dan mengubah pesan
- Jika parameter
profileIdyang rentan padaChatListQuerydiubah, match milik pengguna lain dapat dilihat- Informasi yang dapat diperiksa mencakup imaginaryName, usia, foto, gender, sexuality, status, dan tanggal lahir
Akses tanpa autentikasi ke lampiran chat
- Lampiran yang dibagikan di chat terbagi menjadi foto dan video
- Foto dapat berupa foto biasa yang dapat diputar/dilihat atau foto terbatas 5–15 detik
- Video dapat berupa video biasa yang dapat diputar atau video sekali putar
- Foto biasa diunggah dari aplikasi Feeld ke
api.cloudinary.com, dan photo_id dikembalikan dalam respons- Setelah itu foto disalin ke
feeld.codan disajikan kepada pengguna yang terautentikasi - Jalur berbentuk
cdn/chat-attachment/<receiver_profileId>/<photo_id>atau<sender_profileId>/<photo_id>digunakan - Bagian profileId pada jalur tersebut bahkan jika dipersingkat menjadi string arbitrer minimal 1 karakter, foto tetap dikembalikan kepada pengguna terautentikasi
- Jalur dengan
/v1/di depannya mengembalikan URL foto asli yang tersimpan di Cloudinary, dan URL tersebut dapat diakses tanpa autentikasi
- Setelah itu foto disalin ke
- Foto dengan batas waktu menggunakan parameter tambahan seperti
visibilityMilliseconds:15000saat diunggah- Endpoint untuk penerima menghapus foto 5–15 detik setelah diakses sehingga tidak lagi dapat diakses
- Endpoint yang menggunakan profileId pengunggah terus mengembalikan foto kepada pengguna terautentikasi bahkan setelah 5–15 detik
- Jalur
/v1/mengembalikan URL Cloudinary, dan URL tersebut dapat diakses tanpa autentikasi
- Untuk video, baik video biasa maupun video sekali putar, URL disertakan dalam pesan chat
- Video biasa diunggah ke
us-east.stream-io-cdn.com - Video sekali putar menggunakan alur unggah di sisi
chat.stream-io-api.com - Jika penyerang mendapatkan URL lewat kerentanan pembacaan pesan sebelumnya dan mengganti
u0026menjadi&, video dapat dilihat tanpa autentikasi
- Video biasa diunggah ke
- Video sekali putar dapat diputar ulang oleh penyerang, tetapi di aplikasi penerima ditampilkan sebagai
video expiredsetelah ditonton sekali
Manipulasi pesan, perubahan profil, dan pemalsuan Like
- Di endpoint
chat.stream-io-api.com/messages/<messageId>, metode DELETE dan PUT dapat digunakan untuk menangani pesan orang lain - Pesan yang dihapus terlihat sebagai
This message was deleteddi chat, tetapi jika penyerang memanggil permintaan DELETE yang sama, pesan aslinya dapat dikembalikan - Penyerang dapat mengubah pesan menggunakan messageId meskipun bukan peserta chat
- Saat korban mengetuk notifikasi, korban akan melihat pesan yang telah diubah
- Di bawah pesan ada tanda
edited, tetapi tidak ditampilkan siapa yang mengubahnya - Nama akun tidak unik dan dapat diedit
- Jika parameter
idyang rentan pada permintaan GraphQLProfileUpdatediubah menjadi ID korban, informasi profil seperti nama, sexuality, usia, dan bio dapat diperbarui - Pada permintaan GraphQL
ProfileLike, saat login sebagai profile#1, dapat dibuat seolah-olah profile#2 mengirim “Like” ke profile#3- Dalam contoh, setelah mengirim Like dari profil arbitrer ke profil sendiri, Like tersebut muncul di daftar Likes akun premium
Mengirim pesan ke chat orang lain
- Penyerang dapat mengirim pesan ke chat orang lain meskipun bukan peserta chat
- Nilai yang diperlukan adalah channelID yang diperoleh lewat kerentanan pembacaan pesan sebelumnya
- Jika mengirim permintaan POST ke jalur
channels/messaging/<channelID>/message, pesan akan ditambahkan ke channel tersebut - Korban menerima notifikasi dan dapat memeriksa pesan tersebut
- Sistem menampilkan notifikasi seolah berasal dari nama penyerang, tetapi penyerang dapat mengubah nama profil dan nama tidak bersifat unik
Linimasa pengungkapan
- 8 Maret 2024, FORTBRIDGE mengungkapkan semua isu kepada Feeld
- Pada hari yang sama, Feeld meminta informasi akun yang digunakan untuk pengujian
- 2 April 2024, FORTBRIDGE meminta pembaruan, dan Feeld menyatakan sedang melakukan investigasi serta meminta publikasi ditahan
- 28 Mei 2024, Feeld menerapkan beberapa perbaikan dan meminta penundaan hingga 2 minggu untuk memastikan apakah temuan telah terselesaikan
- 8 Juni 2024, 3 bulan berlalu sejak email pengungkapan awal
- 15 Juli 2024, Feeld menjawab bahwa sebagian isu membutuhkan perbaikan yang lebih kompleks
- 4 Agustus 2024, Feeld meminta agar publikasi ditahan sampai item yang tersisa diselesaikan
- 16 Agustus 2024, Feeld menjawab bahwa mereka telah menerapkan perubahan untuk memitigasi temuan yang tersisa
- 8 September 2024, 6 bulan berlalu sejak pengungkapan awal
- 10 September 2024, blog dipublikasikan
- Pada Agustus 2025, riset tersebut dipresentasikan di DEF CON 33
1 komentar
Komentar Hacker News
Tampaknya pemeriksaan otorisasi hanya diimplementasikan di frontend, dan sepertinya bukan cuma satu-dua endpoint, melainkan hampir di seluruh sistem
Secara konsep ini kesalahan yang mudah dihindari, tetapi saya sudah terlalu sering melihat kesalahan serupa sampai rasanya sulit percaya orang masih melakukannya
Solusi “periksa semua otorisasi di backend” terasa mirip dengan nasihat untuk buffer overflow: “tambahkan pemeriksaan batas di semua tempat”. Komunitas secara umum tahu apa yang harus dilakukan, tetapi membuat semua orang menerapkannya secara konsisten tidaklah mudah
Sebaliknya, pemeriksaan otorisasi terjadi di batas tertentu dan berkaitan dengan cara aplikasi dirancang. Setiap kali saya punya pengaruh terhadap cara proyek dikembangkan, saya selalu ngotot agar pengembangan API backend dipisahkan dengan jelas dari kode klien frontend. Dari pengalaman, itu jauh lebih mudah untuk mencegah dan menguji masalah seperti ini, dan API untuk developer juga muncul “gratis”. Sejujurnya itu alasan utama saya menyukai pendekatan ini
Saya tahu karena pemilik akun lamp menghubungi saya dan bilang semua datanya tiba-tiba hilang. Setelah melihat log, ternyata Google Bot mengklik semua tautan “Delete” di layar admin internal. Itu bisa terjadi karena JavaScript bersifat opt-in. Saya menelepon developernya dan menjelaskan apa yang telah dia lakukan, dan hari itu saya kehilangan banyak kepercayaan pada orang-orang web
Setiap kali melihatnya saya tandai, tetapi cukup mengkhawatirkan karena sering kali hampir tidak ada pemikiran tentang cakupan API klien
Saya ingin menyalahkan junior, no-code, atau kode AI, tetapi saya juga malas seperti mereka jadi akhirnya cuma bisa geleng-geleng kepala
Ini alasan yang sangat bagus untuk tidak memasukkan data pribadi yang akurat, misalnya tanggal lahir
Aplikasi kencan memang tampaknya suka meminta informasi seperti itu, tetapi sebaiknya jangan diberi data yang asli. Lebih baik masukkan nilai yang berbeda sekitar satu tahun dari tanggal ulang tahun sebenarnya
Aplikasi kencan ini memang tidak terlalu terkenal, tetapi menargetkan orang dengan preferensi lain seperti BDSM, group sex, serta pengguna queer. Di banyak wilayah dunia, informasi seperti ini sangat sensitif, tak perlu dijelaskan lagi
Minggu ini aplikasi ini banyak muncul di media karena katanya menghasilkan banyak uang
https://www.theguardian.com/technology/article/2024/sep/08/t...
Mengingat kategorinya sebagai aplikasi, ini kegagalan setingkat kelalaian pidana
Ancaman penjara di AS dan UE, asuransi terkait data, dan biaya asuransi data tampaknya satu-satunya pencegah yang efektif. Kalau fotonya bukan sesuatu yang layak diunggah ke LinkedIn, biayanya harus dibuat sangat mahal
Tentu saja insentifnya juga tidak boleh mendorong penutupan-nutupi
Dunia dating online memang kacau balau. Hanya ada 2–3 perusahaan yang bisa dibilang punya layanan berguna, dan perusahaan-perusahaan itu jahat, tidak kompeten, atau keduanya
Mungkin sekarang kita butuh sesuatu seperti layanan dating federatif open source. Setidaknya sesuatu yang tidak menjual data, tidak membocorkan foto telanjang, dan tidak membuat orang dipukuli, diperkosa, atau dibunuh. Tentu itu tidak semudah diucapkan
ActivityPub sebenarnya sudah punya struktur yang bisa memungkinkan ini lewat publikasi record Person. Terutama jika kebutuhan non-monogami, non-heteroseksual, dan nonkonformitas gender dijadikan prioritas, ruang untuk berinovasinya sangat besar
Hanya saja, aplikasi dating memang bidang yang sangat sulit ditembus. Agar berguna, harus ada akumulasi pengguna dalam jumlah tertentu di wilayah tertentu, dan begitu dimonetisasi, aplikasi itu hampir pasti menjadi kurang berguna. Ada alasan kenapa okcupid rusak setelah berhenti bersifat nirlaba
Lalu ada juga masalah moderasi
Kalau seseorang ingin mengubah bentuk analog itu menjadi salinan digital, itu hak pribadi mereka, tetapi mereka harus paham bahwa tidak ada sistem yang cukup aman untuk benar-benar mencegah kebocoran dan penyebaran, dan tidak akan pernah ada
Terutama orang muda sering tidak mempertimbangkan akibat jangka panjang dan rasa malu yang bisa sangat mungkin muncul. Menyediakan fitur seperti itu hanya mengundang konsekuensi negatif
Ini benar-benar mengerikan. Jelas mereka sama sekali tidak memikirkan keamanan
Saya developer game, dan perusahaan kami menghabiskan lebih banyak upaya untuk menjaga game tetap adil daripada perusahaan ini untuk menjaga penggunanya tetap aman. Mereka pantas dihancurkan lewat gugatan
Bahkan sebelum sadar aplikasinya penuh bug, saya sudah sangat heran melihat bagian minat yang sama sekali tidak memberi konteks apa pun. Misalnya hampir semua orang mencantumkan Domination atau Submission sebagai minat, tetapi tidak ada konteks sama sekali tentang peran apa yang mereka inginkan. Kalau mereka tidak paham betapa mendasarnya kekeliruan ini dalam scene tersebut, artinya mereka memang tidak paham apa pun secara umum
Pesan dan foto privat adalah persoalan yang berbeda
Kalau mau bicara provokatif, ini adalah masalah GraphQL
GraphQL memungkinkan frontend melakukan kueri data. Kedengarannya keren, tetapi dari sisi backend ini sangat tidak transparan, dan biasanya diimplementasikan dengan library pihak ketiga yang sama sekali tidak paham kontrol akses
Jika kontrol akses tidak diimplementasikan di database itu sendiri, akan sangat sulit bagi kode backend untuk mengurai kueri GraphQL dan menentukan record mana yang harus dikembalikan atau dibatasi. Melakukannya di database bukan pilihan terburuk, dan jelas lebih baik daripada melakukannya di frontend
Untuk mengimplementasikan kontrol akses yang benar di backend, Anda harus memahami kuerinya, memahami skema database, lalu membuat model, kelas, fungsi, dan sebagainya untuk menilai apakah “jika user_id adalah XXX, apakah gambar ini boleh dilihat dalam konteks ini atau tidak”. Di GraphQL, jauh lebih mudah mengimplementasikannya di frontend, jadi jelas itulah yang mereka lakukan
Ini bukan berarti implementasi GraphQL-nya bagus, atau bahwa masalahnya sepenuhnya hanya ada pada GraphQL. Maksudnya, GraphQL mencoba menghilangkan kebutuhan backend untuk memahami kueri, sehingga situasi keamanan yang kompleks seperti ini menjadi lebih sulit, dan akibatnya kesalahan seperti ini jadi lebih mudah terjadi
[0] Misalnya, gambar tertentu bisa diakses publik di profil pengguna, tetapi hanya terlihat oleh orang yang match, atau hanya dalam konteks chat (kecuali grup chat), atau sama sekali tidak bisa diakses oleh pengguna yang diblokir. Satu kasus ini saja sudah bisa menimbulkan banyak edge case yang rumit
Tidak perlu menyentuh AST atau memahami konteks kueri lainnya. Resolver yang mengambil foto tinggal menjawab, “apakah pengguna ABC boleh melihat foto pengguna XYZ?” Jika tidak efisien, Anda bisa melakukan prefetch sebagian data atau memakai dataloader
Namun, ceritanya berbeda jika Anda memakai library ajaib yang mengubah GraphQL menjadi SQL
https://hasura.io/docs/2.0/security/allow-list/
Ide sederhananya adalah mengimplementasikan otorisasi di model data. Jadi GraphQL mendelegasikan
getdanlistke model resource yang dapat mengimplementasikan otorisasi sesuai konteks permintaan[1] https://www.apollographql.com/docs/apollo-server/security/au...
[2] https://docs.graphene-python.org/projects/django/en/latest/a...
Ini adalah pengungkapan yang bertanggung jawab dan penuh pertimbangan sampai tingkat yang mengejutkan
Tidak terlalu mengejutkan. Saya memang memakainya, tetapi saya akan menggambarkannya sama tidak kompetennya dengan aplikasi bank saya. Mungkin malah lebih buruk, dan nyaris tidak pernah berfungsi dengan benar
Saya tidak mengerti bagaimana mereka bisa membuatnya seperti ini
Melihat aplikasi ini dan Fetlife, tampak jelas komunitas-komunitas itu punya masalah besar karena tetap bertahan pada aplikasi pertama yang muncul, tak peduli kualitasnya
Lalu belum lama ini mereka menjalankan flag day dengan merilis aplikasi baru dan server baru ke semua orang sekaligus, dan sebagian besar bahkan tidak bisa login. Yang berhasil login pun, jika mereka pelanggan berbayar, kehilangan manfaat premium mereka, like dan chat menghilang, dan seterusnya. Saya sendiri akhirnya tidak bisa login dan pada titik itu meninggalkan aplikasinya
Saya jujur heran para peneliti bisa menahan diri selama ini sebelum mengungkapkannya
Kalau startup buruk seperti ini diberi waktu 6 bulan untuk menutup celah privasi separah ini, mereka pada dasarnya tetap dibiarkan menyalahgunakan privilese untuk mengumpulkan informasi seperti itu. Menurut saya, beri waktu 2 bulan lalu ungkapkan. Mereka harus belajar bahwa informasi pribadi orang bukan sesuatu yang bisa dipertaruhkan seenaknya
Contoh: https://news.ycombinator.com/item?id=41517747