// CLASSIFIED // OFFENSIVE OPS // YETKİLİ PERSONEL DIŞINA ÇIKMAZ //
SYS ONLINE
SES --------
UPLINK SECURE
COORD --.----°N ---.----°W
----.--.--
--:--:-- UTC
MUCAHIC
// Offensive Operations Division, EST. 2026
EXPOSED BLOG · NOTLAR IoT CLOUD APK REVERSE OPSEC

Bileğindeki Casus:
Ucuz Bir Fitness Saatinin Ağır Faturaları

Charles de Gaulle uçak gemisinin Strava ile deşifre olması bahane, ucuz bir Çin menşeli fitness saatinin APK'sından OSS master key, public bucket, cleartext kullanıcı verileri, JWT token'lar ve GPS koordinatları. Kullanıcı hatası değil, mimari kusur.

Operatör
OP-0042 / MUCAHIC
Yayın
2026.04.02
Okuma
~ 18 DK
Dosya ID
MU-006-WATCH

Mart 2026'da Fransız uçak gemisi Charles de Gaulle'ün Doğu Akdeniz'deki konumu, gemideki bir subayın akıllı saatiyle yaptığı koşuyu Strava'ya yüklemesiyle deşifre oldu. Halka açık hesaba yüklenen GPS verileri, denizin ortasında dairesel bir rota çizerek geminin neredeyse tam koordinatlarını ortaya çıkardı. Bu ilk değildi. 2018'de Strava'nın ısı haritası Ortadoğu'daki gizli ABD üslerini ifşa etmişti. 2023'te bir Rus denizaltı komutanı aynı uygulamadaki koşu rotası takip edilerek suikasta uğramıştı.

Her seferinde aynı zincir: kişisel cihaz → fitness uygulaması → bulut → ifşa.

Ama haber olan hep "kullanıcı hatası" oluyor. Subay profili kapatmayı unutmuş, asker konum paylaşımını kapatmamış. Asıl soru hiç sorulmuyor: Uygulamanın kendisi ne kadar güvenli? Veriler buluta giderken ne oluyor? O buluta başka kim erişebiliyor?

Merak ettim. Hatırlarsanız bir önceki yazılarımda donanım seviyesinde BLE testleri gerçekleştirdiğim bir Çin menşeli fitness saati vardı elimde, zaman kaybetmeden uygulamasına baktım.

Bakalım İçinde Ne Var

Jr iç güdülerime dayanarak (alışılmış çaresizlik) key avına çıktım, dedim ki bir api key bulursak tadından yenmez lakin farklı senaryolar ortaya çıktı. Key parametresini ararken OSS ACCESS KEY adında bir key çıktı. Ne olabilir ki diye araştırdım. OSS, Alibaba Cloud'un bulut depolama servisi imiş Türkiye'deki S3 muadili gibi düşünebilirsiniz. Uygulama bu servisi kullanıyor ve keyler kaynak kodda (bravo çocuklar)

APK içinde bulunan OSS Access Key
// APK / kaynak kodda hardcoded OSS_ACCESS_KEY

Bu üretim ortamının anahtarı. Düz metin. Şifresiz. APK'nın içinde. Az biraz merak eden herkes görebiliyor.

Doğru yapılış şöyle olurdu sanırım*: kullanıcı giriş yapar, sunucu 15 dakika geçerli geçici bir token üretir, kullanıcı bununla bucket'a ulaşır, token expire olur, bitti. Alibaba Cloud'un bu iş için hazır bir servisi bile var (STS). Bakılmamış.

Onun yerine tek bir master anahtar, herkese açık, her zaman geçerli.

OSS master key, herkese açık, sürekli geçerli
// Master key, sürekli geçerli, herkese açık

Notu alıp devam edelim, elbet başka keylerde var derken yine oss keyler ile karşılaşınca işin içinde bir gariplik olduğunu ya da basit düşünerek... İki farklı anahtar çifti. Biri yeni, biri eski. Neyse devam edelim

İkinci anahtar çifti, eski/yeni
// İkinci anahtar çifti, eski / yeni rotation izi

Tamam, bucket'a erişim var diyelim. Veriler elbet cleartext değildir diye düşündüm ve şifreleme mantığını ararken şöyle bir şey ile karşılaştım.

Şifreleme key ve cKey (IV) tanımı kaynak kodda
// "key" ve "cKey" (IV), her ikisi de APK içinde

"key" şifreleme anahtarı. "cKey" ise IV, Initialization Vector, yani her şifrelemeyi birbirinden farklı kılmak için kullanılan rastgele değer. İkisi de aynı. İkisi de APK'nın içinde.

IV'nin amacı, aynı veriyi her şifreleyişte farklı sonuç üretmek. Aynı değeri kullanırsan bu güvence ortadan kalkar. Ama daha önemlisi: anahtar zaten dışarıda, IV zaten dışarıda. Şifre var görüntüsü, şifrenin anahtarı da hediye.

PoC yazıp test edelim:

Şifre çözme PoC çıktısı
// PoC, hardcoded key + IV ile decrypt

Şimdiye kadar bulduklarım statik analizdi. Peki uygulama çalışırken ağ trafiğini okuyabilir miyim?

network_security_config.xml dosyasına bakalım.

network_security_config.xml, cleartextTrafficPermitted true
// network_security_config.xml, cleartextTrafficPermitted="true"

İki problem. Birincisi: cleartextTrafficPermitted="true" uygulama şifresiz HTTP bağlantısı kurabiliyor. Kaynak kodda HTTP endpoint'ler mevcut:

Kaynak kodda http:// endpoint örnekleri
// HTTP endpoint, oturum token'ı URL'de

Oturum token'ı. URL'de. HTTP üzerinden. Düz metin gidiyor. E tamam peki bu uygulamayı bağlarken benim gariban telefonumdan birkaç izin almıştı onlara bakalım

AndroidManifest, uygulamanın istediği izinler
// AndroidManifest, istenen izinler (SMS dahil)

Fitness saatine SMS okuma izni neden lazım? Cevap: saate SMS bildirimi iletmek için uygulamanın tüm SMS'lerinizi okuması gerekiyormuş. Mantıkla götürürseniz mektubu kapıcıya teslim ettirmek için ev anahtarınızı veriyorsunuz. İyiymiş :p

allowBackup="true" da var. Bu ne demek? USB kablo, bir bilgisayar, şu komut: adb backup -apk -nosystem com.uygulama.paketi Uygulamanın tüm veritabanı, kayıtlı parolalar, oturum token'ları kopyalanır. Fiziksel erişim yeterli. Kilidi açık bir telefon, meraklı bir eller… bitti.

allowBackup=true ayarı
// allowBackup="true", adb backup ile tüm DB sızar

Az buçuk ne olduğunu anladık şu buckete bir bakalım artık

Peki Bu Bucket'ta Gerçekten Ne Var?

Şimdiye kadar her şey teoriydi. Test etmem gerekiyordu. APK'dan aldığım anahtarlarla Python oss2 kütüphanesi üzerinden bağlandım:

Python oss2 ile bucket bağlantısı kuran PoC kodu
// Python oss2, bucket'a erişim PoC

Erişim onaylandı. Bucket'ın içini listeledim:

Bucket içindeki klasör listesi
// Bucket içeriği, blood_oxygen / heart_rate / sport / sleep / step / weight / temperature / cdn

blood_oxygen/ heart_rate/ sport/ sleep/ step/ weight/ temperature/ ve cdn.

Başlayalım bakalım verileri kontrol etmeye. İlk olarak kandaki oksijen değerlerini okuyabiliyor muyuz ona bakalım.

Blood oxygen verisi, okunabilir hâlde
// blood_oxygen/, ham veri ön izleme

Hatırlarsa bu veriler şifreli mi değil mi diye bir şüpheye düşmüştük içerisini bir okuyalım şifreliyse elimizdeki key ile deneme yapabiliriz.

Veriler şifresiz olarak akıyor
// Veriler şifresiz akıyor, user ID, MAC, ölçüm değerleri açık

Akıyor maşallah 😊 Veriler şifreli değil. Her kayıtta kullanıcı ID'si, cihaz MAC adresi ve ölçüm değerleri açık okunuyor. sport/ ve sleep/ klasörlerine geçtim.

Sport verileri neymiş onlara bir bakalım

Sport verisi, konum ve hız
// sport/, konum (GPS) ve hız bilgisi

Sport verileri konum ve hız bilgisini içeriyor.

Bucket içindeki sport verisi detay
// sport/ devam, rotalar açıkta

ups

İşler garipleşiyor. İçerideki klasör yapısını bir listeleyelim.

Bucket klasör yapısı, derin liste
// Bucket / klasör yapısı, derin liste

CDN tarafını bir kontrol edelim;

CDN klasörü içeriği
// cdn/, profil görselleri vb.

İçeriklerinde uygulamada kullanılan profil resimleri mevcut;

Kullanıcı profil resimleri
// cdn/, kullanıcı profil resimleri

Feedback klasörü biraz garip duruyor,

feedback klasörü
// feedback/, "geri bildirim" zipleri

İçerikler ne alemde bir bakalım.

feedback içindeki zip dosyalarından örnek
// feedback/logs/, sıkıştırılmış debug logları

Log var... İndirip incelesek fena olmaz.

Log dosyalarını indirme
// 17.800 zip dosyası, herkes erişebiliyor

Daha detay lazım eski loğlardan ziyade güncel loğlara erişmeye çalışalım. İçerikleri de önemli tabi. u klasörde 17.800 zip dosyası var. Uygulama, kullanıcı "geri bildirim gönder" butonuna bastığında cihazın log dosyalarını sıkıştırıp bu bucket'a yüklüyor. Bucket public. Yani bu log dosyaları herkese açık.

Her zip'in içinde iOS debug logları var, production uygulamada debug seviyesi loglama açık bırakılmış. Uygulamanın yaptığı her HTTP isteği ve sunucudan gelen her yanıt loglanıyor. OKHTTP interceptor filtresiz çalışıyor.

Ne anlama geliyor? Kullanıcı login olduğunda şu log satırı oluşuyor:

Login isteğinin body'si log dosyasında
// Login, düz metin parola log dosyasında

Bu, login isteğinin body'si. Düz metin. Şifresiz. Log dosyasında.

Ardından sunucunun yanıtı:

Sunucudan dönen JWT yanıtı log içinde
// Sunucu yanıtı, JWT token log içinde

1-5 Nisan 2026 arasındaki logları incelediğimde tablo netleşti. Beş günlük veri içinde 23 benzersiz kullanıcı e-postası, birden fazla kullanıcıya ait düz metin şifre, 16 adet aktif JWT token, 47 benzersiz kullanıcı ID'si ve 13 farklı cihaz MAC adresi vardı.

Log analiz özeti, sızdırılan veri tipleri
// Log analizi, 5 gün, 23 e-posta, 16 JWT, 47 user ID

Bir saldırganın bu verilere ulaşmak için yapması gereken tek şey: APK'daki anahtarla bucket'a bağlanmak, feedback/logs/ prefix'iyle dosyaları listelemek, zip'leri indirmek. Yazının başından bu yana anlattığım zincir burada tamamlanıyor.

E peki benim gariban telefonumdan aldığı SMS ve arama bildirimleri ve diğer izinler…. Onlar da kurban oldu mu acaba? Loglarda SMS ve arama bilgilerine dair log bulamadım fakat saatin özelliklerinde olan acil aramalara kaydedilen kişilerin logları ilettiğini gördüm.

Acil arama kişileri için log girdisi
// Acil arama kişileri, BLE write komutu logu

Decode etmek gerekirse:

writeBytes 设置联系人姓名 >>>>>> ab0014ffa200416264756c617a697a20536e6664006f7368

设置联系人姓名 = "kişi adını ayarla" (Çince)

Bu bir Bluetooth write komutu. Yapısı şöyle:

BLE write komutu yapısı, telefon numarası decode
// BLE write, telefon numarasının nibble decode'u

Telefon için: ab 00 09 ff a3 00 09 19 96 xx xx xx

Her byte'ı ikiye böl (high nibble + low nibble) → 09 19 96 xx xx xx091996xxxxxxx

Sonuç, kişi adı ve telefon numarası elde edildi
// Decode, kişi adı + telefon numarası dışarıda

SMS ve diğer app lerin içeriğini loglamıyormuş. Derin bir oh. Lakin hangi uygulamadan ne kadar bildirim geldiğini logluyor :D

Charles de Gaulle'e Dönelim

Yazının başında anlattığım olayı hatırlayın. Subay profili kapatmayı unutmuş, GPS verisi sızdı. Şimdi farklı bir senaryo kuralım. Subay profili kapatmayı unutmadı. Ama saatinin uygulaması, hardcoded credentials'larla Shenzhen'deki bir bucket'a her aktiviteyi otomatik yüklüyor. Bucket'a kimin erişebildiğini bilmiyor. Uygulamanın APK'sını indirip jadx çalıştıran biri anahtarı zaten aldı. Kullanıcı hatası yok. Gizlilik ayarı yanlış değil. Uygulama, tasarımı gereği sızdırıyor.

Bu sefer manşet "subay konum paylaşımını kapatmayı unuttu" değil. Manşet yok zaten. Kimse fark etmiyor.

Neden Önemli?

"Benim verilerim kim ister ki" diyebilirsiniz. Bu soruyu ordunun sorusu olarak düşünün. Binlerce personelin bileğinde ucuz akıllı saat var. Her sabah güzergahları, her gece uyku düzenleri, her aktivitede GPS koordinatları bir yere gidiyor. O yere kimin erişebildiğini kimse sorgulamadı.

Tekrar: bu bulgu tek bir uygulamada. Bu kategorideki onlarca uygulamanın büyük çoğunluğu aynı mimariye sahip.

OPSEC bugün sadece "telefonu bırak" meselesi değil. Bileğinizdekini de düşünmeniz gerekiyor.

sürekli bağlı olduğun bir dünyada yalnız kalmak sadece bir illüzyondur

sevgilerle.

// RAPOR SONU, MUCAHIC / OP-0042 / 2026.04.02