In the name of Allah, the Most Gracious, the Most Merciful.
I. TL;DR
Kemudahan dalam melakukan penerimaan pembayaran dari hasil penjualan secara online tentu menjadi impian bagi para penjual. Demi mewujudkan kemudahan ini, Tokopedia pun mengeluarkan salah satu fitur berupa “Tambah Rekening Bank” yang dapat digunakan untuk menerima hasil pembayaran setelah seluruh proses transaksi kepada pembeli dilakukan (dalam hal ini setelah pembeli menerima barang dan mengkonfirmasi penerimaan barang dimaksud). Dalam prosesnya, fitur ini sendiri dapat digunakan oleh pengguna untuk menambahkan lebih dari satu rekening yang dapat digunakan sebagai “penerima” pembayaran.
Selain menambah daftar rekening bank ke dalam akun pribadi, tentunya para pengguna pun diizinkan untuk menghapus rekening bank yang dikira tidak akan digunakan olehnya lagi untuk melakukan transaksi. Di dalam prosesnya, penghapusan akun ini sendiri telah dilindungi dengan token (umumnya sering dikaitkan dengan CSRF Token) sehingga tanpa mengetahui dan menggunakan nilai token dari pengguna, maka proses penghapusan ini tidak akan pernah dapat terjadi.
Akan tetapi permasalahan pun muncul ketika token dari setiap pengguna dapat digunakan untuk pengguna lainnya. Dengan kata lain, Tokopedia belum menerapkan pembatasan sesi terhadap token yang di-generate secara otomatis dari sistem untuk setiap penggunanya. Dengan memanfaatkan kerentanan ini, maka seorang Attacker akan dapat menghapus seluruh rekening terdaftar yang telah dimasukan oleh para penggunanya.
II. INTRODUCTION
2.1. Nama Pengguna VS Nama Pemilik Rekening
Terdapat dua perbedaan yang cukup nyata dalam menanggapi konteks user enumeration pada laporan ini. Pada dasarnya, user enumeration memang sangat memungkinkan untuk dilakukan pada situs Tokopedia hanya dengan mengunjungi portal https://www.tokopedia.com/people/X dengan X merupakan parameter yang dapat digantikan dengan angka. Sebagai contoh, nilai 11339854 merupakan nilai yang menandakan bahwa akun ini milik pengguna dengan username “yongki”. Seperti yang terlihat, setiap pengguna bahkan penjual dapat dengan bebas menggunakan nama apapun sebagai username nya sehingga “username enumeration” tentu tidak akan menjadi hal yang significant untuk dibahas.
Akan tetapi, hal ini akan berbeda bila dilarikan terhadap nama pemilik rekening bagi para penjual. Karena nama ini akan menjadi hal yang cukup penting dan tidak dapat ditutupi demi kelancaran proses transfer setelah barangnya berhasil dijual.
Secara singkat, nama pengguna dapat dipalsukan namun nama pemilik rekening akan sulit (bukan tidak dapat) dipalsukan bagi para penjual yang ingin memanfaatkan kemudahan penerimaan pembayaran.
2.2. Cross Site Request Forgery (CSRF) Token VS Tokopedia’s Token
Secara umum, CSRF merupakan suatu serangan yang “memaksa” seorang pengguna untuk melakukan sesuatu yang pada dasarnya “tidak diinginkan” di dalam suatu aplikasi berbasis web dengan memanfaatkan keadaan diri korbannya yang sedang dalam keadaan memiliki otorisasi (login). Umumnya serangan jenis ini dapat dimanfaatkan karena tidak terdapatnya suatu proses autentikasi dalam melakukan suatu perubahan atau tidak terdapatnya token yang unik yang diberikan izin untuk memproses hal dimaksud (token bersifat unik ini biasanya diberikan supaya pengguna tidak lagi dipersulit dengan mengetikan kata sandi untuk perubahan yang tidak terlalu significant).
Di dalam situs Tokopedia, setiap perubahan yang dilakukan oleh pengguna baik itu mengubah profile, menambah daftar rekening, menambah daftar alamat, ataupun menghapus daftar yang ditambahkan selalu disertai dengan token yang di-generate secara otomatis oleh sistem. Perbedaannya, ketika penambahan suatu rekening dan mengubah profile, pengguna diharuskan memasukan kata sandi ataupun mengirimkan OTP terlebih dahulu.
III. SUMMARY OF ISSUE
Seperti yang telah disampaikan pada point sebelumnya, permasalahan keamanan pada laporan ini berkaitan dengan kerentanan yang “mengizinkan” seorang Attacker untuk dapat menghapus seluruh rekening terdaftar yang telah didaftarkan oleh para penggunanya (terutama penjual) di situs Tokopedia. Perlu menjadi catatan bahwa “keuntungan” di dalam pemanfaatan kerentanan ini yaitu Attacker tidak memerlukan interaksi dari pengguna karena mereka hanya perlu mengganti acc_id saja dengan nilai yang mereka inginkan. Dalam konteks lain, pemanfaatan kerentanan ini pun dapat memberikan informasi kepada Attacker berupa nama pemilik rekening yang terdaftarkan.
IV. INFORMATION AND SITUATION OF THIS POC
Untuk dapat memahami dengan baik akan permasalahan yang ada, pada bagian ini akan disampaikan kembali secara spesifik mengenai beberapa informasi yang berkaitan dengan proses yang berjalan secara umum dari aplikasi maupun akar dari permasalahan yang ada.
Saat seorang member mencoba menghapus rekening terdaftarnya, maka secara tidak langsung member dimaksud mengirimkan dua request, yaitu request untuk menghapus dan request untuk konfirmasi penghapusan.
Adapun request yang dikirimkan terkait proses penghapusan yaitu sebagai berikut:
GET /ajax/people-4.pl?action=show_dialog_delete_bank_account&acc_id=XXXXXXX&v=YYYYYYYYYYYYY HTTP/1.1 Host: www.tokopedia.com Connection: close Cache-Control: max-age=0 Accept: text/html, */*; q=0.01 X-Requested-With: XMLHttpRequest User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.116 Safari/537.36 DNT: 1 Referer: https://www.tokopedia.com/people/ZZZZZZZ/bank Accept-Encoding: gzip, deflate, sdch, br Accept-Language: en-US,en;q=0.8 Cookie: some of cookies value here
Table 1 Request for Deleting
Sedangkan untuk request yang dikirimkan terkait proses konfirmasi penghapusan yaitu sebagai berikut:
POST /ajax/people-4.pl HTTP/1.1 Host: www.tokopedia.com Connection: close Content-Length: 133 Accept: application/json, text/javascript, */*; q=0.01 Origin: https://www.tokopedia.com X-Requested-With: XMLHttpRequest User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.116 Safari/537.36 Content-Type: application/x-www-form-urlencoded; charset=UTF-8 DNT: 1 Referer: https://www.tokopedia.com/people/ZZZZZZZ/bank Accept-Encoding: gzip, deflate, br Accept-Language: en-US,en;q=0.8 Cookie: some of cookies value here token=1ccf5fa39f76a4e7a8f4cb3be53ed6ba&acc_id=XXXXXXX&counter=&click_name=submit&action=event_dialog_delete_bank_account&use_master=1
Table 2 Request for Deleting Confirmation
Setelah pengguna memilih pilihan “Ya”, maka secara otomatis rekening yang telah didaftarkan pun terhapus.
V. STEP TO REPRODUCE
5.1. Tentukan dan pastikan akun yang ingin dihapus nomor rekeningnya. Dalam konteks ini, Attacker (Yongki) ingin menghapus nomor rekening terdaftar di akun Dicky yang terdapat pada acc_id “3631290”. Langkah ini dapat dilakukan dengan mengirim request sesuai “table 1” bab IV.
Ketika proses ini dilakukan, maka response pun akan dikirimkan oleh server berupa nama pemilik rekening dan token yang dapat digunakan untuk menghapus akun terkait.
Pada gambar sebelah kiri, terlihat bahwa Attacker (dalam hal ini yongki) berusaha untuk mengakses nomor rekening milik Dicky yang terletak pada acc_id 3631290. Ketika request ini dikirimkan, maka server akan memberikan response kepada pengguna berupa “nama pemilik rekening” dan value dari “token” yang dapat digunakan untuk menghapus akun dimaksud (gambar kanan).
5.2. Setelah itu, Attacker hanya perlu untuk mengirimkan request seperti yang tampak pada “table 2” bab IV dengan menggunakan value dari token yang telah diperoleh oleh Attacker.
Seperti yang terlihat pada gambar 5, saat penghapusan dengan acc_id 3631290 dengan akun “Nama Korban” dilakukan, server mengirimkan respon yang menandakan seakan akun milik Attacker sendiri lah yang terhapus. Namun pada kenyataannya tidak demikian, karena yang terhapus justru akun milik korban yang dituju, yaitu akun rekening milik Dicky dengan nama pemilik rekening “Nama Korban”.
Penjelasan dari situasi ini dapat dilihat lebih jauh pada video yang telah di-upload yang link nya juga disertakan di dalam laporan ini (Bab V).
* Gambar 6 diambil dari video.
VI. ADDITIONAL INFORMATION
Untuk dapat memaksimalkan informasi yang disampaikan pada laporan ini, berikut ini terlampir beberapa kondisi tambahan yang perlu diperhatikan:
6.1. Satu request token hanya dapat digunakan satu kali saja. Jadi untuk menghapus nomor rekening yang lain, maka seorang Attacker perlu untuk men-generate request token miliknya lagi untuk digunakan ke akun yang dituju. Permasalahan di sini dari sudut pandang pribadi adalah:
- 6.1.1. Seorang Attacker dapat men-generate sendiri suatu token yang dapat digunakan untuk menghapus rekening terdaftar dari akun lain. Dengan kata lain, tidak terdapat pembatasan sesi saat Attacker mencoba mengakses acc_id milik pengguna lain;
- 6.1.2. Atau token yang di-generate sendiri oleh seorang Attacker dapat digunakan untuk menghapus rekening terdaftar mana pun. Dengan kata lain, token ini tidak spesifik untuk dirinya sendiri, melainkan dapat digunakan untuk pihak lain.
6.2. Secara umum, proses request untuk penghapusan dilakukan dengan alur sebagai berikut:
Namun pada kondisi saat ini, alur yang ada dapat dimanipulasi sedemikian rupa seperti yang telah dijelaskan sebelumnya sehingga menjadi seperti gambar berikut:
6.3. Sebelum proses penghapusan, Attacker dapat terlebih dahulu melihat mengenai “ketersediaan” dari nomor rekening milik pengguna. Proses ini dapat dilakukan dengan mengirim request seperti yang telah ditampilkan pada “table 1” bab IV yang tentunya disertai dengan penggantian nilai dari acc_id (XXXXXXX);
6.4. PoC Video (Unlisted at Youtube): https://youtu.be/IS1yJxCRgbo
VII. RECOMMENDATION
Dalam hal ini, memastikan bahwa setiap token hanya berfungsi untuk akun itu sendiri (tidak dapat digunakan oleh pengguna lain) tentu akan menjadi rekomendasi yang dapat diterapkan untuk menutupi kerentanan yang ada.
Kemudian terkait User’s Bank Account Enumeration, Tokopedia dapat menerapkan kendali sesi supaya setiap akun tidak dapat melihat informasi sensitif akun lainnya.