giriiş
Bu yazı, Singapur ve Malezya’da kullanılan bir E-Cüzdan uygulaması olan Razer Pay Android uygulamasının hacklenmesiyle ilgilidir. Yalnızca SSL sabitlemeyi veya kök tespitini atlamak için olduğunu düşündüğüm bir araç olan Frida da dahil olmak üzere bazı ilginç tekniklerin kullanımı nedeniyle blog yazmaya değecek ilginç bir yolculuktu.
Bu yazıda, diğer kullanıcıların sohbet mesajlarını okumaktan, kullanıcının banka hesaplarını silmekten, kullanıcının özel bilgilerini toplamaktan ve hatta diğer kullanıcıların hesaplarından para çalmaktan, uygulamayı tehlikeye atmak için Frida’yı nasıl kullanabileceğimi göstereceğim.
TL;DR
Razer Pay uygulaması, istek yüklerinin tahrif edilmesini önlemek için imzalardan yararlandı. Sunucuya iletilen her GET ve POST isteği, hesaplanmış bir imza alanıyla korunuyordu.
İstek parametrelerini değiştirmeye yönelik herhangi bir girişim, hata yanıtıyla sonuçlanacaktır. Ancak APK dosyasında tersine mühendislik yapılarak ve doğru yöntemler belirlenerek, değiştirilen veriler için yeni imzaların hesaplanması mümkün oldu. Yeni imzaların yeniden hesaplanmasını otomatikleştirmek için Frida’nın kullanımı birleştirildiğinde, çok sayıda IDOR sorununun belirlenmesi mümkün oldu.
Arka plan
Katılacağım programları seçerken, kopyalardan kaçınmak için normalde giriş engeli daha yüksek olan programları seçmeyi severim. Razer, Hackerone platformuna katılmaya karar verdiğinde Razer Pay uygulaması gözüme çarptı. Bunun nedeni, kayıt için Malezya veya Singapur cep telefonu numarasının gerekli olmasıydı. Avustralya’da yaşadığım için Malezya/Singapur cep telefonu numaralarım yoktu. Ancak Malezya’da yaşayan ve test için bazı Malezya numaralarının kaynağına yardım etmeye istekli bazı arkadaşlarım ve aile üyelerim vardı. Birçok böcek ödülü avcısının çoğunlukla bu dirence sahip olacağını bildiğimden, bu uygulamayı derinlemesine incelemeye karar verdim 🙂
Burp kullanarak trafiğe proxy uygulayarak bu uygulamayı analiz etmeye başladım ve birçok parametrenin değiştirilemeyeceğini hemen fark ettim. Bunun nedeni her istekteki imza alanıdır. İlk aklıma gelen, başka bir kullanıcı hesabını kayıt edip, sadece o kullanıcının yapabileceği bir işlem için aynı payloadı kopyalayıp, bunu ilk kullanıcının oturumunda gerçekleştirmekti. Ancak imza aynı zamanda ikinci kullanıcının oturum kimlik doğrulama başlığına göre hesaplandığından bu başarısız oldu.
İmzaların nasıl hesaplandığını bulmaya kararlıydım. Bu yüzden uygulamayı kullanarak kaynak koda dönüştürdüm apktool ve kullan Jadx-Gui uygulamanın nasıl çalıştığını anlamak için API uç noktalarını aramaya başladım ve “MD5Encode” adlı yöntemle izini sürdüm. Adı “MD5 karma” algoritmasını öneriyordu ancak yüke MD5 ekleyerek doğru imzayı hiçbir zaman hesaplayamadım (belki de yanlış sıradaydılar veya MD5’in normal uygulaması değildi).
Başka kullanıcının banka hesabını silme
Vazgeçmeden tüm Java kodunu kopyalayıp imza hesaplamasını çevrimdışı yapmaya karar verdim. Benim IDE seçimim şuydu: Fikrini anlıyorum. Bu noktada daha önceki kaynak kod analizime dayanarak “MD5Encode” metoduna ekleyeceğim doğru parametre değer dizisini biliyordum. Kodun derlenmesini sağlamak için bazı küçük ayarlamalar yapılması gerekiyordu (kod karartması nedeniyle) ancak çok da zor değildi. Daha önce yönteme yaptığım mevcut bir istek için aynı parametre değerlerini yerleştirmek aynı imzayı verdi, bu yüzden doğru yolda olduğumu biliyordum!
Geliştiricilerin IDOR’lara bağlı olma ihtimalinin yüksek olduğunu düşündüğüm için IDOR’ları test etmek istedim. signatures
parametre değerinin değiştirilmesine karşı koruma sağlar. Test ettiğim bu özel API’de /deleteBankAccount
bir dizi öngörülebilir işaretin imzalarını hesapladım id
değerler ve bunlara karşılık gelenler signature
değer. Daha sonra şunu seçtim id
(banka kimliği) sahibi olduğum ve yükü teslim ettiğim ikinci bir hesap için.
Bu işe yaradı ve başka bir kullanıcımın banka hesabını silebildim! Edepsiz…
Frida’yı kurtarmaya
Bu noktada IDOR’a karşı savunmasız olan ancak imza alanı tarafından korunan başka API uç noktalarının da olması gerektiğini biliyordum. Daha önce yaptığım saldırının aynısını tekrarlamaya çalıştım ama hiçbir şey işe yaramadı. Bunun nedeni, diğer API uç noktalarının farklı algoritma kullanması ve acı verici bir şekilde gizlenmiş olmasıdır. Kod derlemesi başarısız oldu ve karmaşık kodun sorunlarını gidermek için çok zaman harcıyordum.
Burası Frida’nın kurtarmaya geldiği yer. Frida tüm ağır işleri yaptığı için harikaydı ve tek yapmam gereken, bağlamak istediğim doğru yöntemi belirlemekti. Doğru yöntemi bağlayıp Frida’ya yeni imzaları hesaplamak için ihtiyaç duyduğu gerekli değerleri sağlayarak işleri hızlı bir şekilde otomatikleştirip doğru imzayı almayı başardım.
// frida.js - Use this for recalculating signature for adding user to other people's chatgroup
console.log("Starting...")
Java.perform(function () {
var MD5 = Java.use('com.mol.molwallet.view.MD5')
MD5.MD5Encode.implementation = function (arg)
{
console.log("Hooking class MD5 - method MD5Encode")
//Extra step - calculate new signature
var ret_value = this.MD5Encode("groupId=1x9&userIds=95xxx7&token=b6fxxxd3-2xxc-4xxf-bxx7-7fxxxxa6")
console.log("[+] signature= " + ret_value)
//Call method with original arguments so app doesn't crash ..
var ret_value = this.MD5Encode(arg) //original value
console.log("original ARG: " + arg)
return ret_value;
}
})
Frida’yı çalıştırmak için root erişimine sahip olmam gerekiyordu (Sunucu tarafındaki bir sorunu test ettiğim ve bir saldırganın saldırıyı gerçekleştirmek için kolayca root erişimli bir cihazı kullanabileceği için bu önemli değildi). Mobil cihazda frida sunucusunu başlatmak için aşağıdaki komutlar kullanıldı.
$ adb shell
# sudo su
# /data/local/tmp/frida-server
Farklı bir terminal sekmesinde Frida betiğini çalıştırmak için aşağıdaki komutları çalıştırdım.
$ frida -l frida.js -U com.mol.molwallet
Mobil uygulamaya göz atarken, “MD5Encode” bağımlı yöntemini kullanan herhangi bir eylem, yüklenen betiği çalıştırıyordu. Sonuç olarak geçerli bir talepte bulunmak için ihtiyacım olan doğru imzayı alabildim. Bu spesifik örnekte, davet edilmediğim bir sohbet grubuna kendimi ekleyebildim. Bunun etkisi, diğer kullanıcıların sohbet mesajlarını görebilmem ve en kötüsü, bir grup sohbetinde üyeler arasında paylaşılan sahiplenilmemiş parayı çalabilmemdir.
Durulayın ve tekrarlayın
Savunmasız olan diğer tüm API uç noktaları için aynı tekniği Frida ile tekrarladım. Bazı yüksek etkili sorunlar arasında, kullanıcılar arasında veya bir grup içinde ne kadar kırmızı paketin (paranın) paylaşıldığının numaralandırılması, diğer kullanıcıların işlem ayrıntılarının ve kişisel bilgilerinin görüntülenmesi ve değiştirilmesi yer alır.
Son düşünceler
Bu sorunların bildirilmesi karşılığında alınan toplam ödül yaklaşık 6.000 dolardı. Razer ekibiyle yapılan açıklama ve ödül süreci, yanıt verilmemesi nedeniyle zaman zaman sinir bozucuydu. Bazen bir yanıt için birden fazla takibimi veya unutulmuş ödül ödülleriyle ilgili takiplerimi okuduğumda utanıyorum. Ancak sorunların çoğu yakın zamanda çözüldü ve edindiğim deneyimler ışığında kişisel olarak bu programa ileriye dönük olarak ara vermeye karar verdim.