1 poin oleh GN⁺ 2024-09-13 | 1 komentar | Bagikan ke WhatsApp
  • 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.com dan 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 kondisi member pada 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 profileId yang rentan pada ChatListQuery diubah, 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.co dan 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
  • Foto dengan batas waktu menggunakan parameter tambahan seperti visibilityMilliseconds:15000 saat 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 u0026 menjadi &, video dapat dilihat tanpa autentikasi
  • Video sekali putar dapat diputar ulang oleh penyerang, tetapi di aplikasi penerima ditampilkan sebagai video expired setelah 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 deleted di 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 id yang rentan pada permintaan GraphQL ProfileUpdate diubah 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

 
GN⁺ 2024-09-13
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

    • Menurut saya keduanya tidak sama. Pemeriksaan buffer overflow adalah detail implementasi dan bahasa yang sangat spesifik, dan bisa muncul di mana saja dalam codebase
      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
    • Kalau sampai bingung soal ini, Anda tidak seharusnya menyentuh kode sisi server
    • Dulu saya pernah menangkap web developer yang melakukan autentikasi frontend dengan dialog JavaScript biasa. Password-nya ditaruh di JS lalu cuma dibandingkan secara sederhana
      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
    • Menurut saya hal seperti ini sangat mudah terjadi ketika backend memakai “API DB otomatis”. Contohnya saya langsung teringat beberapa konfigurasi GraphQL otomatis
      Setiap kali melihatnya saya tandai, tetapi cukup mengkhawatirkan karena sering kali hampir tidak ada pemikiran tentang cakupan API klien
    • Sayangnya ini cukup umum di aplikasi mobile. Polanya seperti, “masa pengguna akan membongkar aplikasi mobile sedetail itu?”
      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...

    • Belakangan ini kita sering melihat bahwa membuat sesuatu yang buruk jauh lebih menghasilkan uang daripada membuat sesuatu yang baik
    • The Guardian perlu melihat ini
  • Mengingat kategorinya sebagai aplikasi, ini kegagalan setingkat kelalaian pidana

    • Saya pernah jadi kontraktor murahan itu. Para atasan tidak peduli pada apa pun selain tenggat dan bug yang terlihat oleh reviewer klien
      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
    • Jadi ini benar-benar bukan lelucon. Kerentanan seperti ini bahkan sudah memalukan 10 tahun lalu
  • 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

    • Sudah bertahun-tahun saya memikirkan sesuatu seperti itu, tetapi saya tidak punya cukup dopamin cadangan untuk membangunnya sambil tetap bekerja penuh waktu
      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
    • Menurut saya foto telanjang sebaiknya tetap berada dalam bentuk analog. Dengan begitu distribusinya bisa dikendalikan hampir sepenuhnya dan secara mutlak
      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

    • Bukan cuma keamanan, rasanya mereka tidak memikirkan apa pun
      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
    • Perlu diingat bahwa profil di aplikasi kencan pada prinsipnya memang bisa diakses semua orang. Saat membuka aplikasi, profil langsung muncul. Tidak ada hal seperti ACL
      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

    • Cukup mudah. Lindungi setiap resolver yang mengambil data seperti endpoint REST, lalu gunakan daftar allow list untuk kueri yang menambahkan item selama build CI
      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
    • Di GraphQL, Anda harus mendefinisikan izin akses per atribut, atau melakukan pra-kompilasi kueri lalu memasukkannya ke allow list. Selain itu, data akan bocor
      https://hasura.io/docs/2.0/security/allow-list/
    • Library GraphQL pihak ketiga yang layak pakai seharusnya mengimplementasikan ACL dalam suatu bentuk. Tampaknya yang paling populer juga begitu [1] [2]
      Ide sederhananya adalah mengimplementasikan otorisasi di model data. Jadi GraphQL mendelegasikan get dan list ke 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...
    • Saat memakai HotChocolate, saya tidak pernah mengalami masalah ini. Anda bisa dengan mudah memberi aturan otorisasi pada entitas atau properti entitas, dan semuanya ditangani otomatis. Ini juga bisa diterapkan pada mutation
  • Ini adalah pengungkapan yang bertanggung jawab dan penuh pertimbangan sampai tingkat yang mengejutkan

    • Apakah tangkapan layar menu “Discover profiles” dan daftar like itu menyertakan profil nyata? Kalau ya, meskipun wajahnya disamarkan, itu tetap cukup tidak bertanggung jawab
    • Tindakannya tidak sesuai dengan ucapannya
  • 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

    • Saat saya memakainya pun aplikasinya sangat buruk. Kalau bukan kebocoran memori aneh atau masalah privasi, biasanya UX-nya yang diimplementasikan dengan sangat payah
      Melihat aplikasi ini dan Fetlife, tampak jelas komunitas-komunitas itu punya masalah besar karena tetap bertahan pada aplikasi pertama yang muncul, tak peduli kualitasnya
    • Saat saya memakainya, komunitasnya bagus, tetapi aplikasinya tidak pernah ditulis dengan benar
      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