Android Uygulama Sızma Testleri

1. Android İşletim Sistemi

Android sızma testleri yapabilmek için, öncelikle Android işletim sistemini ve yapısını anlamak gerekiyor. Aşağıda Android’in mimarı yapısı bulunmakta:

Screen Shot 2017-04-09 at 14.57.41.png

Alt katmanda çalışan Linux kernel, temel işlevler olan process, hafıza ve cihaz yönetimi gibi etmenleri sağlamakla beraber Android işletim sistemine Linux’ün hali hazırda çok iyi yaptığı ve bünyesinde barındırdığı diğer işlevler olan networking ve driver desteğini de sunmakta.

Bu bağlamda Linux kernel, Android ekosistemine pek çok kilit güvenlik özelliği de getirmekte. Bunlar:

  • Kullanıcı tabanlı izin modeli
  • Process izolasyonu
  • Güvenli IPC (processler arası iletişim)  mekanizması
  • Kernel içerisinde bulunan, Android bünyesinde kullanılmayan kısımların ve potansiyel olarak zafiyet barındırabilecek kısımların çıkarılabilme özelliği

Çoklu kullanıcı yapısına sahip bir işletim sistemi olmasından dolayı Linux kernel’ın temel güvenlik odağı, bu kullanıcıların kaynaklarının birbirinden ayrılmasıdır. Linux güvenliği bir kullanıcı kaynağının diğerinden ayrı tutulmasına dayanır. Bu bağlamda Linux:

  • A kullanıcısının, B kullanıcısının dosyalarını okumasını engeller
  • A kullanıcısının, B kullanıcısına ayrılmış hafızayı kullanmasına izin vermez
  • A kullanıcısının, B kullanıcısına ayrılmış işlemci kaynağını kullanmasına izin vermez
  • A kullanıcısının, B kullanıcısına ait olan cihaz alanını (örn. GPS, bluetooth) kullanmasına izin vermez

Donanım soyutlama katmanı, uygulamalara direkt olarak donanım kaynaklarına erişim imkanı tanır.

Üçüncü katmanda bulunan ve şekilde görünen kütüphaneler, uygulamaların çalışmaları için (örn. Webkit kütüphanesi web tarayıcılar için, SQLite kütüphanesi ise SQL veritabanı için gerekli) gereken temelleri barındırır.

Dalvik Sanal Makinesi, özel olarak Android projesi için geliştirilmiştir ve görevi Android için yazılmış uygulamaların çalıştırılmasıdır. Bir Android cihaz üzerinde çalışan her uygulamanın kendi Dalvik Sanal Makinesi bulunur.

Android Runtime (ART) ise Dalvik’e alternatif olarak 4.4 sürümünde gelmiştir fakat 5.0 ile Dalvik’in yerini almıştır. ART’nin Dalvik’ten farkı içerisinde Garbage Collection ve Ahead-of-time (AOT, vaktinden önce) derleme özeliklerini bulundurmasıdır. Dalvik Sanal Makinesi, Android uygulamalarını kullanıcılar açtığında derlemekteydi. AOT ise, kullanıcı bir Android uygulamasını yüklediği zaman derlemekte.

Uygulama framework’ü uygulama geliştiricilerin uygulamalarında kullanmaları için Java ile yazılmış servisler barındırmakta.

En üst katmanda bulunan Android uygulamaları Java programlama dilinde yazılmakta. Android SDK (yazılım geliştirme kiti) araçları Java dilinde yazılan kodu içerisindeki bütün kaynak dosyalar ve veriler ile APK (Android paketi, .apk) dosyasına çevirir. Bir uygulamanın APK dosyasında o uygulamanın içeriği yer alır ve Android cihazlar bu dosya ile uygulamayı kurarlar.

Screen Shot 2017-04-09 at 14.58.11.png

2. APK Dosya İçeriği

APK dosyası aşağıdaki dizinleri içerir:

  • AndroidManifest.xml: AndroidManifest.xml dosyası sisteme uygulamada bulunan üst seviye bileşenler ile (örn. Aktiviteler, servisler, yayın alıcılar ve içerik sağlayıcılar) ne yapması gerektiğini söyler. Ayrıca, bu dosyanın içerisinde uygulamanın çalışması için gerekli izinler de yer alır. Binary formatındaki XML dosyası, apktool gibi araçlarla okunabilir formata getirilebilir.
  • META-INF dizini
    • MANIFEST.MF: Manifest dosyası
    • CERT.RSA: Uygulamanın sertifikası
    • CERT.SF: MANIFEST.MF dosyasının Kaynak listesi ve SHA-1 hashleri
  • lib: Derlenmiş kodun yazılım katmanına özgü olan tarafını içerisinde barındırır:
    • armeabi: ARM tabanlı işlemciler için derlenmiş kod
    • armeabi-v7a: ARMv7 ve üstü tabanlı işlemciler için derlenmiş kod
    • x86: X86 için derlenmiş kod
    • mips: MIPS işlemcisi için derlenmiş kod
  • res: resources.arsc dosyasına derlenmemiş olan kaynakları tutar
  • assets: Uygulama öğelerini (assets) tutar. AssetManager ile çağırılabilir
  • classes.dex: Dalvik Sanal Makinesi ile anlaşılabilir olan dex dosya formatı
  • resources.arsc: Kaynakların derlenmeden önceki hallerini tutar (örn. Binary XML)

3. Uygulama bileşenleri (App components)

Uygulama bileşenleri bir uygulamanın temelini oluşturur. Her bileşen sistemin uygulamaya girebilmesi için bir kapı görevi görebilir. Her bileşen kendi içinde görevini yapar ve görevleri kendilerine özeldir, uygulamanın nasıl davranacağını şekillendirir. Bir uygulamanın dört bileşeni aşağıdaki gibidir:

3.1. İçerik Sağlayıcı (Content Provider)

  • İçerik sağlayıcı bir uygulamadan diğerine istek üzerine veri yollar
  • Bu veriler bir dosya sisteminde, SQLite veritabanında, web sunucu üzerinde ya da uygulamanın erişebildiği başka bir depolama alanında tutulabilir
  • Başka uygulamalar içerik sağlayıcı üzerinden uygulama içerisindeki verileri sorgulayabilir veya değiştirebilir (eğer içerik sağlayıcı buna izin veriyorsa)
  • İçerik sağlayıcı bir uygulamanın başka uygulamalar ile veri paylaşmasını sağlar
  • Veritabanı fonksiyonlarına benzeyen dört adet işlevi bulunur
    • insert()
    • update()
    • delete()
    • query()

3.2. Aktivite (Activity)

Basitçe aktivite, arayüzü olan bir ekran olarak tanımlanabilir. Örnek olarak; giriş ekranı bir aktivitedir. Giriş ekranından sonra gelen ekran da kendi başına bir aktivitedir.

3.3. Servisler (Services)

Servis, bir uygulamadaki uzun süren operasyonlar ya da uzaktaki processlerin işlerini yürüten ve arkadan çalışan bir bileşendir. Örnek olarak; kullanıcı başka bir uygulama kullanıyorken arkada müzik çalması.

3.4. Yayın Alıcılar (Broadcast receiver)

  • Yayın alıcılar sistem üzerinde yapılan yayınları almaya yararlar.
  • Yayınların büyük bir kısmı sistem tarafından yapılır. (örn. Ekran kapandı, resim çekildi, şarj azaldı)
  • Uygulamalar da yayın yapabilirler. (örn. Veri indiriliyor ve başka uygulamaların da kullanımına hazır)
  • Yayın alıcılar arayüz ekranı olarak görünmeseler de, bildiri (notification) olarak kullanıcıya görünebilir
  • Genel kullanım olarak, diğer bileşenler için bir geçit görevi görür. Örnek olarak; bir uygulama düşük şarj için bir yayın alıcı tanımlayabilir ve böyle bir yayın aldığında bu bilgiye göre davranışını değiştirebilir

3.5. Bileşen Aktivasyonu

  • 3 bileşen; aktivite, servis ve yayın alıcı, eşzamanlı olmayan mesajlar tarafından aktifleştirilir (intent)
  • Intentler, uygulama çalışırken, bağımsız bileşenleri birbirine bağlar. Bu bileşen uygulama bünyesinde de olabilir, başka uygulamaların bileşenleri de olabilir

4. Android tarafında Uygulama Güvenliği

4.1. Android izin modeli

Varsayılan olarak, Android işletim sistemi içerisindeki bazı API’lar korumalıdır ve sadece işletim sistemi tarafından erişilebilir. Bunlar:

  • Kamera
  • GPS
  • Bluetooth
  • Telefon
  • SMS/MMS
  • Network/veri bağlantıları

Eğer bir uygulama bu API’lardan bir ya da birden fazlasına erişmek istiyorsa, bu isteğini AndroidManifest.xml dosyasında belirtir. Play store’dan indirilen bir uygulama kurulurken istenen izinlere bakıldığında bunlar görülebilir ve eğer izin verilmezse uygulama kurulmaz. Eğer kullanıcı izin verirse, işletim sistemi uygulamaya bu API’lara erişme izni verir.

Aşağıda Subway Surfers oyunun istediği izinleri görebilirsiniz

Screen Shot 2017-04-09 at 14.58.43.png

Bir oyunun fotoğraflarıınıza, tarayıcı geçmişinize, kullanıcı hesaplarınıza vs. erişmek istemesi normal mi? Bir uygulamayı kurarken bunlara dikkat edilmesinde fayda var.

4.2. Uygulama İmzalama

  • Android, bir uygulamanın kurulmadan önce dijital olarak imzalanmasını istemektedir. Bu imza ile uygulamanın geliştiricisini tanır
  • Bir uygulamayı bir cihazda çalıştırabilmek için, o uygulamanın imzalı olması gerekmektedir. Bir uygulama kurulurken, paket yöneticisi (packet manager) uygulamanın imzalı olup olmadığını kontrol eder
  • Uygulamalar, yazarı tarafından üretilen anahtarlarla imzalanabileceği gibi bir CA (Certificate Authority, sertifika otoritesi) tarafından da imzalanabilir
  • Uygulama imzalama bir uygulamanın diğer uygulamalara erişimini kısıtlamak için (IPC hariç) ve cihaza indirilirken/kurulurken uygulama üzerinde değişiklik yapılmadığından emin olmak için kullanılır

4.3. Uygulama Doğrulaması

  • Android 4.2 ve sonrasında uygulama doğrulaması bulunmaktadır. Kullanıcılar “uygulamayı doğrula” seçeneğini seçebilir ve uygulamaların yüklenmeden önce doğrulanmasını isteyebilir
  • Uygulama doğrulaması kullanıcıları imzasız uygulama yükleyebilme olasılığından kurtarır

4.4. Android Sandbox

  • Her Android uygulaması, cihaza kurulduktan sonra kendi sandboxına sahip olur: Android işletim sistemi çok kullanıcılı bir yapıya sahiptir ve her uygulamanın kendi kullanıcısı vardır
  • Varsayılan olarak, sistem her uygulamaya özel Linux kullanıcı ID’si verir. (Bu ID sadece sistem tarafından bilinir, uygulamalar tarafından bilinmez) Daha sonra sistem bu ID üzerinden kendi uygulama dosyalarına erişim izni tanımlar. Böylece uygulama, kendi dosyalarına erişebilir hale gelir
  • Her uygulamanın kendi sanal makinesi (VM, virtual machine) bulunur. Böylece her uygulama kendi kodunu diğer uygulamalardan izole bir şekilde çalıştırır
  • Varsayılan olarak, her uygulama kendi Linux process’i içerisinde çalışır. Android bu process’i uygulama içerisindeki her hangi bir uygulama bileşeninin çalışması gerektiği zaman başlatır ve bu bileşene artık ihtiyaç duyulmadığında veya sistemin başka uygulamalar için hafızada yer açması gerektiğinde kapatır

Bu şekilde Android “en az ayrıcalık” (principle of least privilege) ilkesini uygular. Her uygulama sadece işini yapmak için gerekli olaşan bileşenlere erişebilir. Bu yapı, uygulamaların sistem üzerinde yetkileri olmadıkları yerlere erişmelerini engelleyen güvenli bir yapı oluşturur. Android uygulamaları kendi sandboxlarında çalıştığından diğer uygulamaları etkileyemeseler de, biden fazla Android uygulaması aynı kullanıcı ID’sine sahip olabilir (aynı dijital imza ile imzalanmış olmaları gerekiyor) ve aynı Dalvik Sanal Makinesini paylaşabilir.

5. DIVA üzerinde örnek sızma testi

5.1. DIVA Nedir?

DIVA (Damn insecure and vulnerable App) içerisinde zafiyet barındıracak şekilde oluşturulmuş bir Android uygulamasıdır. Bu uygulamanın amacı Android uygulamalarında bulunan ve zayıf/güvenlik düşünülmeden yapılan programlamadan dolayı doğan zafiyetleri göstermektir.

010616_2323_crackingdam1

Aşağıdaki bütün testlerde dex2jar ve JD-GUI kullanacağım. Bunların yanında testlerde size yardımı çok dokunacak olan drozer öğrenmekte de fayda var.

Aşağıdaki örnekler DIVA içerisindeki örneklerden sadece bazılarıdır, kalan örnekleri de yapmanızı şiddetle tavsiye ederim.

5.2. Güvenli olmayan kayıt tutma

Uygulamanın 1. adımı olan güvenli olmayan kayıt tutma ekranı aşağıdaki gibidir.

010616_2323_crackingdam5

Burada, girilen kredi kartı bilgisinin kayıtlarda gözüküp gözükmediği ve kodlamada nerede hata yapıldığını bulmamız gerekmekte.

Bunun için, dex2jar ile APK’yı .jar dosyasına çevirip JD-GUI ile kodları inceleyebiliriz.

Fakat öncelikle, adb (Android Debugger Bridge) logcat komutu ile Android cihaz üzerindeki kayıtları açtıktan sonra kredi kartı olarak girilen değeri kayıtlarda incelememiz gerek:

D/MobileDataStateTracker( 469): default: setPolicyDataEnable(enabled=true)
D/LightsService( 469): Excessive delay setting light: 86ms
D/dalvikvm( 1695): GC_CONCURRENT freed 136K, 6% free 3845K/4060K, paused 7ms+4ms, total 93ms
E/diva-log( 1695): Error while processing transaction with credit card: 0000000000
E/SoundPool( 469): error loading /system/media/audio/ui/Effect_Tick.ogg

Kırmızı işaretli yer, kullanıcının girdiği kredi kartı numarasıdır. Uygulamanın kodu bu bağlamda zafiyet içermekte ve kullanıcının hassas bilgilerini kayıtlara yazmaktadır.

JD-GUI ile inceleme yapıldığında aşağıdaki kod parçacığının bu zafiyete yol açtığı görülmekte:

010616_2323_crackingdam6

Log.e(“diva-log”, “Error while processing transaction with credit card: ” + localEditText.getText().toString())

5.3. Kodun içine gömülmüş hassas bilgiler 

2. adımda, uygulamanın içine gömülmüş bazı bilgiler bulmamız istenmekte. Uygulama geliştiricilerin sıkça yaptığı, uygulamala kodlarının içinde bıraktıkları hassas bilgiler (örn. Parolalar, şifreleme için kullanılan anahtarlar vs.) zafiyetlere yol açmaktadır.

010616_2323_crackingdam7

JD-GUI ile inceleme yapıldığında aşağıdaki kod parçacığının gizli bir anahtar içerdiği görülmekte:

010616_2323_crackingdam8

Uygulama ekranında kullanıcıdan istenen değere ‘vendorsecretkey’ yazıldığında, uygulama kullanıcıya erişim yetkisi vermektedir.

010616_2323_crackingdam9

5.4. Uygulama bünyesinde tutulan verilen

Uygulamanın bu kısmında bulunan bölümler, kullanıcı adı ve parolaların saklanmasıyla alakalı yapılan yanlışları göstermektedir. Hassas bilgiler asla SharedPreferences’a, açık olarak SQLite veritabanına veya her hangi bir txt dosyasına yazılmamalıdır. Aşağıda bu kısımdan bir bölüm görülmekte:

010716_1841_crackingdam2

Kullanıcı adı ve parola SECRET:SECRET olarak verilmiş ve kaydedilmiştir. Uygulama bizden bu hassas bilgiyi bulmamızı istemektedir. Uygulamanın jar dosyalarını JD-GUI ile açıp incelediğimizde, parolaların sdcard altında (getExternalStorageDirectory) /.uinfo.txt olarak tutulduğu görülmektedir.

010716_1841_crackingdam9

root@generic:/ # cd /mnt/sdcard
root@generic:/mnt/sdcard # ls -l .uinfo.txt
rwxrwx— root sdcard_r 14 2016-01-05 23:57 .uinfo.txt
root@generic:/mnt/sdcard #
root@generic:/mnt/sdcard # cat .uinfo.txt
SECRET:SECRET

Görüldüğü üzere, hassas bilgiler herkesin erişimine açık olan /sdcard dizininde tutulmakta ve kolayca erişilebilmekte.

5.5. Girdi alanları

Uygulamanın bu bölümünde girdi alanından her hangi bir kullanıcı adı bilmeden/girmeden bütün kullanıcı bilgilerine ulaşılması istenmektedir.  Uygulama kodunu incelendiğimizde girdi alanının her hangi bir şekilde kontrolden geçirilmediği görülmekte:

010816_2033_crackingdam4

010816_2033_crackingdam7

Cursor localCursor = this.mDB.rawQuery(“SELECT * FROM sqliuser WHERE user = ‘” + localEditText.getText().toString() + “‘”, null);

kod satırından da görüldüğü üzere girdi alanı SQL enjeksiyonuna açık.

010816_2033_crackingdam6

5.6. Erişim kontrol

Uygulamanın bu bölümünde üyelik almadan Tveeter API bilgilerine ulaşılması istenmekte.

012016_2302_crackingdam5

AndroidManifest.xml dosyasına bakıldığında ilgili aktivitenin intent-filter ile korunmaya çalıştığı görülüyor.


Intent-filter bir aktiviteyi erişilmekten koruyamaz çünkü bir uygulama bileşeni intent-filter ile kullanıldığında dışarı açılmış olur. (publicly exported) Dışarı açılmış bir aktivite başka her hangi bir uygulama tarafından çağırılabilir.

$ adb shell am start -n jakhar.aseem.diva/.APICreds2Activity -a jakhar.aseem.diva.action.VIEW_CREDS2

komutunu çalıştırdığımızda karşımıza ilgili ekran gelmekte fakat PIN kodu istemektedir:

012016_2302_crackingdam6

JD-GUI ile uygulama kodlarını incelediğimizde üyelik kontrolünün

boolean bcheck = i.getBooleanExtra(getString(R.string.chk_pin),true);

parametresiyle yapıldığı görülmekte.

012016_2302_crackingdam7

Strings.xml incelendiğinde chk_pin değerinin check_pin olduğu görülmekte. Chk_pin değerinin kontrolünün yapıldığı kod parçası ise kaynak kodlarında biraz gezildiğinde aşağıdaki gibi görülebilir:

012016_2302_crackingdam9

chk_pin değerine göre API bilgileri görülebilmekte. Eğer kullanıcı kayıt olmuşsa check_pin false olarak ayarlanıyor. Fakat kullanıcı kayıtlı değilse ve check_pin true olarak gelirse her hangi bir kontrol yapılmıyor.

$ adb shell am start -a jakhar.aseem.diva.action.VIEW_CREDS2 -n jakhar.aseem.diva/.APICreds2Activity –ez check_pin false

komutuyla uygulamaya check_pin değeri yollanarak PIN kodu bypass edilebilir:

012016_2302_crackingdam10

6. Referanslar

https://github.com/payatu/diva-android

https://developer.android.com/guide/components/fundamentals.html

https://source.android.com/devices/tech/security/overview/app-security.html