Android, uygulama güvenliği sorunlarının sıklığını ve etkisini önemli ölçüde azaltan yerleşik güvenlik özelliklerine sahiptir. Sistem, uygulamalarınızı genellikle varsayılan sistem ve dosya izinleriyle oluşturup güvenlikle ilgili zor kararlar vermekten kaçınabileceğiniz şekilde tasarlanmıştır.
Aşağıdaki temel güvenlik özellikleri güvenli uygulamalar oluşturmanıza yardımcı olur:
- Uygulama verilerinizi ve kod yürütmenizi diğer uygulamalardan ayıran Android uygulaması korumalı alanı.
- Kriptografi, izinler ve güvenli ara işlem iletişimi (IPC) gibi ortak güvenlik işlevlerinin sağlam uygulamalarına sahip bir uygulama çerçevesi.
- Yaygın bellek yönetimi hatalarıyla ilişkili riskleri azaltmak için adres alanı düzeni rastgele hale getirme (ASLR), no-execute (NX),
ProPolice, safe_iop,
OpenBSD
dlmalloc
vecalloc
ve Linuxmmap_min_addr
gibi teknolojiler. - Kayıp veya çalınmış cihazlardaki verileri korumak için etkinleştirilebilen şifrelenmiş dosya sistemi.
- Sistem özelliklerine ve kullanıcı verilerine erişimi kısıtlamak için kullanıcı tarafından verilen izinler.
- Uygulama verilerini uygulama bazında kontrol etmek için uygulama tanımlı izinler.
Bu sayfadaki Android güvenliğiyle ilgili en iyi uygulamalar hakkında bilgi sahibi olmanız önemlidir. Bu uygulamaları genel kodlama alışkanlıkları olarak izlemek, kullanıcılarınızı olumsuz etkileyen güvenlik sorunlarının yanlışlıkla oluşmasını önlemenize yardımcı olur.
Veri depolama
Android'deki bir uygulamanın en yaygın güvenlik sorunu, cihaza kaydettiğiniz verilerin diğer uygulamaların erişimine açık olup olmamasıdır. Cihaza veri kaydetmenin üç temel yolu vardır:
- Dahili depolama
- Harici depolama
- İçerik sağlayıcılar
Dahili depolama
Varsayılan olarak, dahili depolama alanında oluşturduğunuz dosyalara yalnızca uygulamanız erişebilir. Android bu korumayı uygular ve çoğu uygulama için yeterlidir.
IPC dosyaları için kullanımdan kaldırılan MODE_WORLD_WRITEABLE
ve MODE_WORLD_READABLE
modlarını kullanmaktan kaçının. Belirli uygulamalara veri erişimini sınırlama imkanı sağlamaz ve veri biçimi üzerinde herhangi bir kontrol sağlamaz. Verilerinizi diğer uygulama işlemleriyle paylaşmak istiyorsanız bunun yerine, diğer uygulamalara okuma ve yazma izinleri sunan ve duruma göre dinamik izin izinleri verebilen bir içerik sağlayıcı kullanabilirsiniz.
Hassas verilere yönelik ek koruma sağlamak için Güvenlik kitaplığını kullanarak yerel dosyaları şifreleyebilirsiniz. Bu önlem, kayıp bir cihazın dosya sistemi şifrelemesi olmadan korunmasını sağlayabilir.
Harici depolama
SD kartlar gibi harici depolama alanlarında oluşturulan dosyalar tüm dünyada okunabilir ve yazılabilir. Harici depolama, kullanıcı tarafından kaldırılabileceğinden ve herhangi bir uygulama tarafından değiştirilebileceğinden, hassas olmayan bilgileri yalnızca harici depolama kullanarak depolayın.
Harici depolama alanındaki dosyaları daha güvenli bir şekilde okumak ve yazmak için
EncryptedFile
sınıfını sunan Güvenlik kitaplığını kullanabilirsiniz.
Harici depolamadaki verileri işlerken güvenilmeyen kaynaklardan gelen verilerde olduğu gibi giriş doğrulamasını gerçekleştirin. Yürütülebilir dosyaları veya sınıf dosyalarını dinamik yüklemeden önce harici depolamada saklamayın. Uygulamanız harici depolama alanından yürütülebilir dosyalar alıyorsa dinamik yüklenmeden önce dosyaların imzalandığından ve kriptografik olarak doğrulandığından emin olun.
İçerik sağlayıcılar
İçerik sağlayıcılar, kendi uygulamanızla sınırlandırılabilen veya diğer uygulamaların erişimine izin vermek için dışa aktarılabilen bir yapılandırılmış depolama mekanizması sunar.
Başka uygulamaların ContentProvider
öğenize erişmesini sağlamak istemiyorsanız uygulama manifest dosyasında
android:exported=false
olarak işaretleyin. Aksi takdirde, diğer uygulamaların depolanan verilere erişmesine izin vermek için android:exported
özelliğini true
olarak ayarlayın.
Diğer uygulamalar tarafından kullanılmak üzere dışa aktarılan bir ContentProvider
oluştururken, okuma ve yazma için tek bir izin
veya okuma ve yazma için ayrı izinler belirtebilirsiniz.
İzinlerinizi, görevi tamamlamak için
gereken izinlerle sınırlandırın. Yeni işlevleri kullanıma sunmak için sonradan izin eklemenin, bunları kaldırıp mevcut kullanıcıları etkilemekten genellikle daha kolay olduğunu unutmayın.
Yalnızca kendi uygulamalarınız arasında veri paylaşımı için bir içerik sağlayıcı kullanıyorsanız android:protectionLevel
özelliğini signature
koruması olarak ayarlanmış şekilde kullanmanızı öneririz.
İmza izinleri kullanıcı onayı gerektirmez. Bu nedenle, verilere erişen uygulamalar aynı anahtarla imzalandığında daha iyi bir kullanıcı deneyimi ve içerik sağlayıcı verilerine daha denetimli erişim sağlar.
İçerik sağlayıcılar, android:grantUriPermissions
özelliğini bildirerek ve bileşeni etkinleştiren Intent
nesnesinde FLAG_GRANT_READ_URI_PERMISSION
ile FLAG_GRANT_WRITE_URI_PERMISSION
işaretlerini kullanarak daha ayrıntılı erişim de sağlayabilir. Bu izinlerin kapsamı,
<grant-uri-permission>
öğesi ile daha da sınırlandırılabilir.
Bir içerik sağlayıcıya erişirken güvenilir olmayan kaynaklardan olası SQL yerleştirmeyi önlemek için query()
, update()
ve delete()
gibi parametreleştirilmiş sorgu yöntemleri kullanın. selection
bağımsız değişkeni, yönteme gönderilmeden önce kullanıcı verileri birleştirilerek oluşturulduysa parametre haline getirilmiş yöntemlerin yeterli olmayacağını unutmayın.
Yazma izni konusunda yanlış bir kanıya varamazsanız.
Yazma izni, reklam öğesi WHERE
yan tümceleri kullanılarak ve sonuçların ayrıştırılmasıyla bazı verilerin onaylanmasını mümkün kılan SQL ifadelerine olanak tanır. Örneğin, bir saldırgan yalnızca telefon numarası zaten varsa bir satırı değiştirerek arama kaydında belirli bir telefon numarasının olup olmadığını kontrol edebilir. İçerik sağlayıcı verileri tahmin edilebilir bir yapıya sahipse yazma izni, hem okuma hem de yazma sağlamaya eşdeğer olabilir.
İzinler
Android, uygulamaları birbirine karşı korumalı hale getirdiğinden uygulamaların kaynakları ve verileri açık bir şekilde paylaşması gerekir. Bunu, kamera gibi cihaz özelliklerine erişim de dahil olmak üzere temel korumalı alan tarafından sağlanmayan ek özellikler için gereken izinleri beyan ederek yaparlar.
İzin istekleri
Uygulamanızın istediği izin sayısını en aza indirin. Hassas izinlere erişimi kısıtlamak, bu izinlerin yanlışlıkla hatalı kullanımı riskini azaltır, kullanıcıların uygulamayı daha fazla benimsemesini sağlar ve uygulamanızı saldırganlara karşı daha savunmasız hale getirir. Genellikle, uygulamanızın çalışması için gerekli olmayan izinleri istemeyin. Uygulamanızın izin beyan etmesi gerekip gerekmediğini değerlendirme ile ilgili kılavuzu inceleyin.
Mümkünse uygulamanızı herhangi bir izin gerektirmeyen bir şekilde tasarlayın. Örneğin, benzersiz bir tanımlayıcı oluşturmak amacıyla cihaz bilgilerine erişim istemek yerine uygulamanız için bir UUID oluşturun (kullanıcı verileri ile ilgili bölüme bakın). Harici depolama alanı kullanmak (izin gerektirir) yerine verileri dahili depolamada depolamayı da tercih edebilirsiniz.
Uygulamanız, izin istemenin yanı sıra, güvenlik açısından hassas IPC'yi korumak için ContentProvider
gibi başka uygulamalara açık olan IPC'yi korumak için <permission>
öğesini kullanabilir.
İzinler kullanıcılar için kafa karıştırıcı olabileceğinden, genel olarak, mümkün olduğunda kullanıcı tarafından onaylanan izinler dışında erişim denetimlerini kullanmanızı öneririz. Örneğin, tek bir geliştirici tarafından sağlanan uygulamalar arasında IPC iletişimi izinlerinde imza koruma düzeyini kullanabilirsiniz.
İzinle korunan verileri sızdırmayın. Bu durum, yalnızca uygulamanızın bu verilere erişim izni olduğu için kullanılabilen IPC üzerinden verileri açığa çıkardığında meydana gelir. Uygulamanızın IPC arayüzünün istemcileri, aynı veri erişimi iznine sahip olmayabilir. Bu sorunun sıklığı ve potansiyel etkileri hakkında daha fazla ayrıntıyı USENIX'te yayınlanan Permission Re-Delegation: Attacks and Defenses (İzin Yeniden Delemi: Attacks ve Savunmalar) adlı araştırma makalesinde bulabilirsiniz.
İzin tanımları
Güvenlik gereksinimlerinizi karşılayan en küçük izin grubunu tanımlayın. Sistem tanımlı izinler birçok durumu kapsadığından çoğu uygulama için yeni bir izin oluşturulması nispeten yaygındır. Uygun olduğunda mevcut izinleri kullanarak erişim kontrolleri yapın.
Yeni bir izne ihtiyacınız varsa görevinizi bir imza koruma düzeyiyle tamamlayıp tamamlayamayacağınızı düşünün. İmza izinleri kullanıcıya şeffaftır ve yalnızca izin kontrolünü gerçekleştiren uygulamayla aynı geliştirici tarafından imzalanan uygulamaların erişmesine izin verir.
Yine de yeni bir izin oluşturulması gerekiyorsa <permission>
öğesini kullanarak bu izni uygulama manifest dosyasında beyan edin. Yeni izni kullanan uygulamalar, manifest dosyalarına <uses-permission>
öğesi ekleyerek bu izni referans alabilir. Ayrıca, addPermission()
yöntemini kullanarak izinleri dinamik olarak da ekleyebilirsiniz.
Tehlikeli koruma düzeyiyle bir izin oluşturursanız göz önünde bulundurmanız gereken birtakım karmaşıklıklar vardır:
- İzinde, kullanıcıya alması gereken güvenlik kararını kısa ve öz bir şekilde açıklayan bir dize olmalıdır.
- İzin dizesi birçok farklı dilde yerelleştirilmelidir.
- Bir izin kafa karıştırıcı olduğu veya riskli olarak algılandığı için kullanıcılar bir uygulamayı yüklememeyi tercih edebilirler.
- İzni oluşturan kullanıcı yüklenmediğinde uygulamalar izni isteyebilir.
Bunların her biri, geliştirici olarak sizin için teknik olmayan önemli bir zorluk oluşturur ve kullanıcılarınızın kafasını karıştırır. Bu nedenle, tehlikeli izin düzeyinin kullanılmasını önermeyiz.
Ağ Oluşturma
Ağ işlemleri, kullanıcıya özel olabilecek verilerin aktarılmasını içerdiğinden güvenlik açısından doğası gereği risk taşır. Kullanıcılar, özellikle de ağ işlemleri gerçekleştirirken mobil cihazların gizliliğiyle ilgili endişeler giderek artıyor. Bu nedenle uygulamanızın, kullanıcı verilerini her zaman güvende tutmak için tüm en iyi uygulamaları takip etmesi çok önemlidir.
IP ağ iletişimi
Android'de ağ iletişimi, diğer Linux ortamlarından önemli ölçüde farklı değildir. En önemli husus, hassas veriler için uygun protokollerin kullanıldığından emin olmaktır (ör. güvenli web trafiği için HttpsURLConnection
). Mobil cihazlar sıklıkla herkese açık kablosuz hotspot'lar gibi güvenli olmayan ağlara bağlandığından, sunucuda HTTPS'nin desteklendiği her yerde HTTP üzerinden HTTPS kullanın.
Kimliği doğrulanmış, şifrelenmiş yuva düzeyinde iletişim, SSLSocket
sınıfı kullanılarak kolayca uygulanabilir. Android cihazların kablosuz ağ kullanarak güvenli olmayan kablosuz ağlara bağlanma sıklığı göz önünde bulundurulduğunda, ağ üzerinden iletişim kuran tüm uygulamalar için güvenli ağ kullanımı kesinlikle teşvik edilmektedir.
Bazı uygulamalar hassas IPC'yi işlemek için localhost ağ bağlantı noktalarını kullanır. Bu arayüzlere cihazdaki diğer uygulamalar tarafından erişilebildiğinden, bu yaklaşımı kullanmayın. Bunun yerine, kimlik doğrulamanın mümkün olduğu durumlarda (ör. Service
ile) bir Android IPC mekanizması kullanın.
Spesifik olmayan IP adresine (INADDR_ANY
) bağlanmak, geri dönüş kullanmaktan daha kötüdür. Çünkü bu, uygulamanızın herhangi bir IP adresinden istek almasına olanak tanır.
HTTP'den veya güvenli olmayan diğer protokollerden indirilen verilere güvenmediğinizden emin olun. Buna WebView
içindeki girişlerin doğrulanması ve HTTP'ye karşı yayınlanan amaçlara verilen tüm yanıtlar dahildir.
Telefon ağı
Kısa Mesaj Hizmeti (SMS) protokolü temel olarak kullanıcılar arası iletişim için tasarlanmıştır ve veri aktarmak isteyen uygulamalar için uygun değildir. SMS sınırlamaları nedeniyle, kullanıcı cihazında bir web sunucusundan uygulamanıza veri mesajları göndermek için Firebase Cloud Messaging (FCM) ve IP ağını kullanmanızı öneririz.
SMS'in ağda veya cihazda ne şifrelendiğini ne de güçlü bir şekilde doğrulanmadığını unutmayın. Özellikle SMS alıcıları, SMS’i uygulamanıza kötü amaçlı bir kullanıcı göndermiş olabilecek şekilde beklemelidir. Hassas komutlar gerçekleştirmek için kimliği doğrulanmamış SMS verilerine güvenmeyin.
Ayrıca, SMS'in ağda adres sahteciliğine ve/veya müdahaleye tabi olabileceğini de unutmayın. Android destekli cihazın kendisinde, SMS mesajları yayın amaçları olarak iletilir. Böylece, READ_SMS
iznine sahip diğer uygulamalar tarafından okunabilir veya yakalanabilirler.
Giriş doğrulaması
Yetersiz giriş doğrulaması, hangi platformda çalıştıklarından bağımsız olarak uygulamaları etkileyen en yaygın güvenlik sorunlarından biridir. Android, uygulamaların giriş doğrulama sorunlarına maruz kalma olasılığını azaltan platform düzeyinde karşı önlemler alır. Mümkün olduğunda bu özellikleri kullanmanızı öneririz. Ayrıca, giriş doğrulama sorunu olasılığını azaltmak için tür açısından güvenli diller kullanmanızı öneririz.
Yerel kod kullanıyorsanız dosyalardan okunan, ağ üzerinden alınan veya IPC'den alınan tüm veriler güvenlik sorununa yol açabilir. En yaygın sorunlar arabellek taşması, boşaltıldıktan sonra kullanım ve tek tek yapılan hatalardır. Android, bu hataların kötüye kullanımını azaltan ASLR ve Veri Yürütme Önleme (DEP) gibi çeşitli teknolojiler sunar, ancak temel sorunu çözmez. İşaretçileri dikkatli bir şekilde kullanarak ve arabellekleri yöneterek bu güvenlik açıklarını önleyebilirsiniz.
JavaScript ve SQL gibi dinamik, dize tabanlı diller de çıkış karakterleri ve komut dosyası yerleştirme nedeniyle giriş doğrulama sorunlarına tabidir.
SQL veritabanına veya içerik sağlayıcıya gönderilen sorgulardaki verileri kullanıyorsanız SQL yerleştirme işlemi sorun oluşturabilir. En iyi savunma, içerik sağlayıcılarla ilgili bölümde açıklandığı gibi, parametreye dayalı sorgular kullanmaktır. İzinlerin salt okuma veya salt yazma ile sınırlandırılması, SQL yerleştirmeden kaynaklanan zarar olasılığını da azaltabilir.
Bu bölümde açıklanan güvenlik özelliklerini kullanamıyorsanız iyi yapılandırılmış veri biçimleri kullandığınızdan ve verilerin beklenen biçime uyduğunu doğrulayın. Belirli karakterleri engellemek veya karakterlerin değiştirilmesi etkili bir strateji olsa da, bu teknikler pratikte hataya açıktır. Bu nedenle, mümkün olduğunda bunlardan kaçınmanızı öneririz.
Kullanıcı verileri
Genel olarak, kullanıcı verilerinin güvenliği için en iyi yaklaşım, hassas veya kişisel kullanıcı verilerine erişen API'lerin kullanımını en aza indirmektir. Kullanıcı verilerine erişiminiz varsa mümkünse verileri saklamaktan veya aktarmaktan kaçının. Uygulama mantığınızın, karma veya geri alınamayan bir veri biçimi kullanılarak uygulanıp uygulanamayacağını düşünün. Örneğin, uygulamanız e-posta adresini iletmekten veya saklamaktan kaçınmak için e-posta adresinin karmasını birincil anahtar olarak kullanabilir. Böylece verilerin yanlışlıkla açığa çıkma ve saldırganların uygulamanızı suistimal etme olasılığı azalır.
Uygulamanız şifreler veya kullanıcı adları gibi kişisel bilgilere erişirse bazı yargı alanlarında, bu verileri kullanımınızı ve depolamanızı açıklayan bir gizlilik politikası sağlamanız gerekebileceğini unutmayın. Kullanıcı verilerine erişimi en aza indirmek için güvenlikle ilgili en iyi uygulamaları izlemek de uyumluluğu kolaylaştırabilir.
Ayrıca uygulamanızın, kişisel bilgileri (ör. reklamcılık için üçüncü taraf bileşenler veya uygulamanız tarafından kullanılan üçüncü taraf hizmetleri) istemeden diğer taraflara ifşa edip edemeyeceğini de göz önünde bulundurun. Bir bileşenin veya hizmetin neden kişisel bilgi gerektirdiğini bilmiyorsanız bunu sağlamayın. Genel olarak, uygulamanızın kişisel bilgilere erişimini azaltmak, bu alanda sorun çıkma olasılığını azaltır.
Uygulamanızın hassas verilere erişmesi gerekiyorsa uygulamayı bir sunucuya iletmeniz gerekip gerekmediğini veya işlemi istemcide çalıştırıp çalıştıramayacağınızı değerlendirin. Kullanıcı verilerini iletmemek için istemcide hassas veriler kullanan herhangi bir kod çalıştırabilirsiniz. Ayrıca, kullanıcı verilerini gereğinden fazla izin veren IPC, herkesin yazabileceği dosyalar veya ağ yuvaları üzerinden cihazdaki diğer uygulamalara yanlışlıkla ifşa etmediğinizden emin olun. Aşırı serbest IPC, izne korunan verilerin sızdırılmasına yönelik özel bir durumdur. Bu durum, İzin istekleri bölümünde ele alınmaktadır.
Genel Olarak Benzersiz Tanımlayıcı (GUID) gerekiyorsa büyük ve benzersiz bir sayı oluşturun ve bu sayıyı depolayın. Kişisel bilgilerle ilişkilendirilebilecek telefon numarası veya IMEI gibi telefon tanımlayıcıları kullanmayın. Bu konu, benzersiz tanımlayıcılar için en iyi uygulamalar ile ilgili sayfada daha ayrıntılı olarak ele alınmaktadır.
Cihaz üzerindeki günlüklere yazarken dikkatli olun.
Android'de, günlükler paylaşılan bir kaynaktır ve READ_LOGS
iznine sahip uygulamalar tarafından kullanılabilir.
Telefon günlüğü verileri geçici olsa ve yeniden başlatma sırasında silinse de, kullanıcı bilgilerinin uygunsuz bir şekilde günlüğe kaydedilmesi kullanıcı verilerinin yanlışlıkla diğer uygulamalara sızdırılmasına neden olabilir. Kimliği tanımlayabilecek bilgileri (PII) günlüğe kaydetmemenin yanı sıra, üretim uygulamalarında günlük kullanımını sınırlandırın. Bunu kolayca uygulamak için hata ayıklama bayraklarını ve kolayca yapılandırılabilen günlük düzeylerine sahip özel Log
sınıflarını kullanın.
Web Görünümü
WebView
, HTML ve JavaScript içerebilen web içeriklerini kullandığından, uygunsuz kullanım,
siteler arası komut dosyası çalıştırma (JavaScript yerleştirme) gibi yaygın web güvenliği sorunlarına yol açabilir. Android, WebView
işlevselliğini uygulamanızın gerektirdiği minimum işlevle sınırlandırarak bu olası sorunların kapsamını daraltmak için çeşitli mekanizmalara sahiptir.
Uygulamanız bir WebView
içinde doğrudan JavaScript kullanmıyorsa setJavaScriptEnabled()
çağrısını yapmayın.
Bazı örnek kodlar bu yöntemi kullanır. Bunu kullanan örnek kodu bir üretim uygulamasında başka bir amaçla kullanırsanız gerekli değilse bu yöntem çağrısını kaldırın. Varsayılan olarak WebView
JavaScript'i yürütmez. Bu nedenle, siteler arası komut dosyası oluşturmak mümkün değildir.
JavaScript'in normalde Android uygulamalarına ayrılmış işlemleri çağırmasına olanak tanıdığından addJavaScriptInterface()
hizmetini özellikle dikkatli bir şekilde kullanın. Bunu kullanırsanız addJavaScriptInterface()
öğesini yalnızca tüm girişlerin güvenilir olduğu web sayfalarına gösterin. Güvenilmeyen girişe izin verilirse güvenilmeyen JavaScript, uygulamanızda Android yöntemlerini çağırabilir. Genel olarak, addJavaScriptInterface()
uygulamasının yalnızca uygulama APK'nızda yer alan JavaScript'e maruz kalmasını öneririz.
Uygulamanız hassas verilere WebView
ile erişiyorsa yerel olarak depolanan tüm dosyaları silmek için clearCache()
yöntemini kullanabilirsiniz. Ayrıca, bir uygulamanın belirli bir içeriği önbelleğe almaması gerektiğini belirtmek için no-store
gibi sunucu tarafı üst bilgileri de kullanabilirsiniz.
Android 4.4'ten (API düzeyi 19) daha eski platformlara sahip cihazlar, birkaç güvenlik sorununa sahip olan bir webkit
sürümünü kullanır.
Geçici bir çözüm olarak, uygulamanız bu cihazlarda çalışıyorsa WebView
nesnelerinin yalnızca güvenilir içeriği görüntülediğini onaylamalıdır. Uygulamanızın SSL'deki olası güvenlik açıklarına maruz kalmadığından emin olmak için SSL açıklarından korumak için güvenlik sağlayıcınızı güncelleme bölümünde açıklandığı şekilde güncellenebilir güvenlik Provider
nesnesini kullanın. Uygulamanızın açık web'den içerik oluşturması gerekiyorsa en son güvenlik yamalarıyla güncel kalmasını sağlamak için kendi oluşturucunuzu sağlayabilirsiniz.
Kimlik bilgisi istekleri
Kimlik avı saldırılarını daha kolay anlaşılır hale getirmek ve başarı ihtimalini azaltmak için kullanıcı kimlik bilgilerinin istenme sıklığını en aza indirin. Bunun yerine bir yetkilendirme jetonu kullanın ve yenileyin.
Mümkün olduğunda kullanıcı adlarını ve şifreleri cihazda saklamayın. Bunun yerine, ilk kimlik doğrulamasını kullanıcı tarafından sağlanan kullanıcı adı ve şifreyi kullanarak yapın, ardından kısa ömürlü, hizmete özgü bir yetkilendirme jetonu kullanın.
Birden fazla uygulamanın erişebileceği hizmetlere AccountManager
kullanarak bağlanmanızı öneririz. Mümkünse bulut tabanlı bir hizmeti çağırmak ve şifreleri cihazda depolamamak için AccountManager
sınıfını kullanın.
Account
almak için AccountManager
kullandıktan sonra, kimlik bilgilerini yanlışlıkla yanlış uygulamaya iletmemek için kimlik bilgilerini iletmeden önce CREATOR
kullanın.
Kimlik bilgileri yalnızca oluşturduğunuz uygulamalar tarafından kullanılıyorsa AccountManager
öğesine erişen uygulamayı checkSignatures()
kullanarak doğrulayabilirsiniz.
Kimlik bilgisini yalnızca bir uygulama kullanıyorsa depolama için KeyStore
de kullanabilirsiniz.
Kriptografi
Android, veri yalıtımı, tam dosya sistemi şifrelemesini destekleme ve güvenli iletişim kanalları sağlamanın yanı sıra, kriptografi kullanarak verileri korumak için çok çeşitli algoritmalar sağlar.
Yazılımınızın hangi Java Kriptografi Mimarisi (JCA) güvenlik sağlayıcılarını kullandığını öğrenin. Kullanım alanınızı destekleyebilecek mevcut çerçeve uygulamasının en üst düzeyini kullanmaya çalışın. Uygunsa Google tarafından sağlanan sağlayıcıları Google tarafından belirtilen sırada kullanın.
Yerel dosyaları daha güvenli bir şekilde okumak ve yazmak için Güvenlik kitaplığını kullanın.
Bilinen bir ağ konumundan güvenli bir şekilde dosya almanız gerekiyorsa basit bir HTTPS URI'si yeterli olabilir ve kriptografi bilgisi gerektirmez. Güvenli bir tünele ihtiyacınız varsa kendi protokolünüzü yazmak yerine HttpsURLConnection
veya SSLSocket
kullanmayı düşünün. SSLSocket
kullanıyorsanız ana makine adı doğrulaması yapmadığını unutmayın. SSLSocket
ürününün doğrudan kullanılmasıyla ilgili uyarılar konusuna bakın.
Kendi protokolünüzü uygulamanız gerektiğini fark ederseniz kendi kriptografik algoritmalarınızı uygulamayın. Cipher
sınıfında sağlanan AES ve RSA uygulamaları gibi mevcut şifreleme algoritmalarından yararlanın. Ayrıca, aşağıdaki en iyi
uygulamaları da izleyin:
- Ticari amaçlarla 256 bit AES kullanın. (Mümkün değilse 128 bit AES kullanın.)
- Eliptik eğri (EC) kriptografisi için 224 veya 256 bit ortak anahtar boyutlarını kullanın.
- CBC, TO veya GCM engelleme modlarını ne zaman kullanacağınızı öğrenin.
- TO modunda IV/sayaç yeniden kullanımından kaçının. Bunların kriptografik olarak rastgele olduğundan emin olun.
- Şifreleme kullanırken CBC veya TO modunu aşağıdaki işlevlerden biriyle kullanarak bütünlüğü uygulayın:
- HMAC-SHA1
- HMAC-SHA-256
- HMAC-SHA-512
- GCM modu
KeyGenerator
tarafından oluşturulan şifreleme anahtarlarını başlatmak için güvenli bir rastgele sayı oluşturucu (SecureRandom
) kullanın.
Güvenli bir rastgele sayı oluşturma aracıyla oluşturulmayan anahtarın kullanılması, algoritmanın gücünü önemli ölçüde zayıflatır ve çevrimdışı saldırılara izin verebilir.
Bir anahtarı tekrar kullanım için depolamanız gerekiyorsa şifreleme anahtarlarının uzun vadeli olarak depolanmasını ve alınmasını sağlayan KeyStore
gibi bir mekanizma kullanın.
İşlemler arası iletişim
Bazı uygulamalar, ağ yuvaları ve paylaşılan dosyalar gibi geleneksel Linux tekniklerini kullanarak IPC'yi uygulamaya çalışır. Ancak bunun yerine, IPC için Service
ve BroadcastReceiver
ile Intent
, Binder
veya Messenger
gibi Android sistem işlevlerini kullanmanızı öneririz.
Android IPC mekanizmaları, IPC'nize bağlanan uygulamanın kimliğini doğrulamanıza ve her IPC sistemi için güvenlik politikası belirlemenize olanak tanır.
Güvenlik unsurlarının çoğu IPC mekanizmaları arasında paylaşılır.
IPC mekanizmanız başka uygulamalar tarafından kullanılmak üzere tasarlanmamışsa bileşenin manifest öğesinde (ör. <service>
öğesi için) android:exported
özelliğini false
olarak ayarlayın. Bu, aynı UID içinde birden fazla işlemden oluşan uygulamalar için veya geliştirmenin ilerleyen aşamalarında işlevi gerçekten IPC olarak göstermek istemediğinize ancak kodu yeniden yazmak istemediğinizde faydalıdır.
IPC'nize diğer uygulamalar tarafından erişilebiliyorsa <permission>
öğesini kullanarak bir güvenlik politikası uygulayabilirsiniz. IPC, size ait olan ve aynı anahtarla imzalanmış uygulamalar arasındaysa android:protectionLevel
içinde signature
düzeyinde bir izin kullanın.
Etkinlikler
Etkinlikler ve yayın alıcıları için intent, Android'de eşzamansız IPC için tercih edilen mekanizmadır.
Uygulama gereksinimlerinize bağlı olarak sendBroadcast()
, sendOrderedBroadcast()
veya belirli bir uygulama bileşeni için açık bir niyet kullanabilirsiniz. Güvenlik nedeniyle, açık amaçlar tercih edilir.
Dikkat: Bir Service
öğesine bağlamak için amaç kullanıyorsanız uygulamanızı güvende tutmak için açık olmayan bir amaç kullanın. Bir hizmeti başlatmak için dolaylı niyet kullanmak güvenlik açısından bir tehlikedir. Çünkü hangi hizmetin amaca yanıt vereceğinden emin olamazsınız ve kullanıcı hangi hizmetin başladığını göremez. Android 5.0 (API düzeyi 21) sürümünden itibaren, dolaylı bir amaçla bindService()
yöntemini çağırırsanız sistem bir istisna oluşturur.
Unutmayın, sıralanan yayınlar bir alıcı tarafından kullanılabilir, bu nedenle tüm uygulamalara teslim edilmeyebilir. Belirli bir alıcıya teslim edilmesi gereken bir niyet gönderiyorsanız alıcının adını belirten açık bir intent kullanmanız gerekir.
Bir amacın gönderenleri, yöntem çağrısıyla boş olmayan bir izin belirterek alıcının izne sahip olduğunu doğrulayabilir. Yalnızca bu izne sahip uygulamalar amacı alır. Bir yayın amacı içindeki veriler hassas ise, kötü amaçlı uygulamaların uygun izinler olmadan bu mesajları almak için kaydolamadığından emin olmak için izin uygulamayı düşünebilirsiniz. Bu tür durumlarda bir yayını yükseltmek yerine doğrudan alıcıya çağırmayı da düşünebilirsiniz.
Not: Amaç filtreleri güvenlik özellikleri değildir. Bileşenler açık niyetlerle çağrılabilir ve intent filtresine uyacak verilere sahip olmayabilir. Verinin çağrılan alıcı, hizmet veya etkinlik için doğru şekilde biçimlendirildiğinden emin olmak amacıyla amaç alıcınızda giriş doğrulaması yapın.
Hizmetler
Service
, genellikle diğer uygulamaların kullanacağı işlevleri sağlamak için kullanılır. Her hizmet sınıfının manifest dosyasında karşılık gelen bir <service>
bildirimi olmalıdır.
Varsayılan olarak hizmetler dışa aktarılmaz ve başka bir uygulama tarafından çağrılamaz. Ancak hizmet bildirimine herhangi bir intent filtresi eklerseniz bu bildirim varsayılan olarak dışa aktarılır. İstediğiniz gibi davrandığından emin olmak için android:exported
özelliğini açıkça bildirmeniz en iyisidir.
Hizmetler, android:permission
özelliği kullanılarak da korunabilir. Böylece diğer uygulamaların hizmeti başlatabilmesi, durdurabilmesi veya bağlanabilmesi için kendi manifest dosyalarında karşılık gelen bir <uses-permission>
öğesini tanımlaması gerekir.
Not: Uygulamanız Android 5.0 (API düzeyi 21) veya sonraki sürümleri hedefliyorsa arka plan hizmetlerini yürütmek için JobScheduler
kullanın.
Bir hizmet, kendisine yapılan IPC çağrılarını izinlerle ayrı ayrı koruyabilir. Bu, çağrının uygulanmasından önce checkCallingPermission()
işlevi çağrılır. Gözetime daha az açık oldukları için manifest dosyasında bildirimsel izinleri kullanmanızı öneririz.
Dikkat: İstemci ve sunucu izinlerini karıştırmayın. Çağrılan uygulamanın uygun izinlere sahip olduğundan ve çağrı yapan uygulamaya aynı izinleri verdiğinizden emin olun.
Binder ve Messenger arayüzleri
Android'de RPC stili IPC için tercih edilen mekanizma Binder
veya Messenger
kullanmaktır. Gerekirse uç noktaların karşılıklı kimlik doğrulamasını sağlayan iyi tanımlanmış arayüzler sağlarlar.
Uygulama arayüzlerinizi, arayüze özgü izin kontrolleri gerektirmeyen bir şekilde tasarlamanızı öneririz. Binder
ve Messenger
nesneleri uygulama manifest dosyasında tanımlanmadığından bunlara doğrudan bildirim temelli izinler uygulayamazsınız. Genellikle, uygulandıkları Service
veya Activity
için uygulama manifestinde belirtilen izinleri devralırlar. Kimlik doğrulama ve/veya erişim denetimleri gerektiren bir arayüz oluşturuyorsanız bu denetimleri Binder
veya Messenger
arayüzünde kod olarak açıkça eklemeniz gerekir.
Erişim denetimleri gerektiren bir arayüz sağlıyorsanız arayanın gerekli izne sahip olup olmadığını doğrulamak için checkCallingPermission()
kullanın. Uygulamanızın kimliği diğer arayüzlere aktarıldığından, bu özellikle çağrı yapan kişi adına bir hizmete erişmeden önce önemlidir. Bir Service
tarafından sağlanan arayüzü çağırıyorsanız ilgili hizmete erişim izniniz yoksa bindService()
çağrısı başarısız olabilir.
Harici bir işlemin uygulamanızla etkileşim kurmasına izin vermeniz gerekiyor ancak bunun için gerekli izinlere sahip değilse clearCallingIdentity()
yöntemini kullanabilirsiniz. Bu yöntem, çağrıyı uygulamanız harici bir arayan yerine uygulamanız yapıyormuş gibi uygulamanızın arayüzüne gerçekleştirir.
Arayan izinlerini daha sonra restoreCallingIdentity()
yöntemiyle geri yükleyebilirsiniz.
Bir hizmetle IPC gerçekleştirme hakkında daha fazla bilgi edinmek için Sınır Hizmetleri sayfasını inceleyin.
Yayın alıcıları
BroadcastReceiver
, Intent
tarafından başlatılan eşzamansız istekleri işler.
Varsayılan olarak alıcılar dışa aktarılır ve başka bir uygulama tarafından çağrılabilir. BroadcastReceiver
başka uygulamalar tarafından kullanılmak üzere tasarlanmışsa uygulama manifestindeki
<receiver>
öğesini kullanarak alıcılara güvenlik izinleri uygulamak isteyebilirsiniz. Bu durum, uygun izinlere sahip olmayan uygulamaların BroadcastReceiver
öğesine amaç göndermesini engeller.
Dinamik olarak yüklenen kodla güvenlik
Uygulama APK'nızın dışından kod yüklenmesini kesinlikle önermiyoruz. Bu yöntem, kod yerleştirme veya kod üzerinde değişiklik yapma nedeniyle uygulamada güvenlik ihlali olasılığını artırır. Ayrıca, sürüm yönetimi ve uygulama testi açısından karmaşık hale getirir ve bir uygulamanın davranışını doğrulamayı imkansız hale getirerek bazı ortamlarda yasaklanabilir.
Uygulamanız kodu dinamik olarak yüklüyorsa unutulmaması gereken en önemli nokta, dinamik olarak yüklenen kodun, uygulama APK'sı ile aynı güvenlik izinleriyle çalıştığıdır. Kullanıcı, kimliğinizi temel alarak uygulamanızı yüklemeye karar verir ve dinamik olarak yüklenen kod da dahil olmak üzere uygulama içinde çalıştırılan tüm kodları sağlamanızı bekler.
Birçok uygulama, güvenli olmayan konumlardan kod yüklemeye çalışır. Örneğin, şifrelenmemiş protokoller üzerinden ağdan veya harici depolama gibi herkesin yazabileceği konumlardan indirilebilir. Bu konumlar, ağdaki bir kişinin aktarılan içeriği değiştirmesine veya kullanıcının cihazındaki başka bir uygulamanın cihazdaki içeriği değiştirmesine olanak tanıyabilir. Bununla birlikte, doğrudan APK'nızın içine dahil edilen modüller diğer uygulamalar tarafından değiştirilemez.
Bu durum, kodun yerel kitaplık veya DexClassLoader
kullanılarak yüklenen bir sınıf olması fark etmeksizin geçerlidir.
Sanal makinede güvenlik
Dalvik, Android'in çalışma zamanı sanal makinesidir (VM). Dalvik özel olarak Android için geliştirildi ancak diğer sanal makinelerdeki güvenli kodla ilgili endişelerin çoğu Android için de geçerli. Genel olarak, sanal makineyle ilgili güvenlik sorunları konusunda endişelenmenize gerek yoktur. Uygulamanız güvenli bir korumalı alanda çalıştığı için sistemdeki diğer işlemler kodunuza veya özel verilerinize erişemez.
Sanal makine güvenliği hakkında daha fazla bilgi edinmek istiyorsanız konuyla ilgili mevcut literatürü inceleyin. En popüler kaynaklardan ikisi şunlardır:
Bu belgede, Android'e özgü veya diğer sanal makine ortamlarından farklı alanlar ele alınmaktadır. Diğer ortamlarda sanal makine programlama konusunda deneyimli geliştiriciler için Android için uygulama yazma konusunda farklı olabilecek iki genel sorun vardır:
- JVM veya .NET çalışma zamanı gibi bazı sanal makineler, kodu temel işletim sistemi özelliklerinden ayıran bir güvenlik sınırı görevi görür. Android'de Dalvik sanal makinesi bir güvenlik sınırı değildir. Uygulama korumalı alanı işletim sistemi düzeyinde uygulanır. Böylece Dalvik, herhangi bir güvenlik kısıtlaması olmadan aynı uygulamadaki yerel kodla birlikte çalışabilir.
- Mobil cihazların depolama alanının sınırlı olması nedeniyle, geliştiricilerin modüler uygulamalar oluşturmak ve dinamik sınıf yüklemesini kullanmak istemeleri yaygın bir durumdur. Bu işlemi yaparken hem uygulama mantığını aldığınız kaynağı hem de yerel olarak depoladığınız kaynağı göz önünde bulundurun. Güvenli olmayan ağ kaynakları veya harici depolama gibi doğrulanmamış kaynaklardan dinamik sınıf yüklemeyi kullanmayın, çünkü bu kod kötü amaçlı davranışlar içerecek şekilde değiştirilmiş olabilir.
Yerel kodda güvenlik
Genel olarak, uygulama geliştirme için Android NDK ile yerel kod yerine Android SDK'sını kullanmanızı öneririz. Yerel kodla oluşturulan uygulamalar daha karmaşıktır, daha az taşınabilirdir ve arabellek taşması gibi yaygın bellek bozulması hatalarını içerir.
Android, Linux çekirdeği kullanılarak geliştirilmiştir ve Linux geliştirme güvenliği en iyi uygulamaları hakkında bilgi sahibi olmak, özellikle yerel kod kullanıyorsanız faydalıdır. Linux güvenlik uygulamaları bu belgenin kapsamı dışında olsa da en popüler kaynaklardan biri Güvenli Programlama HOWTO - Güvenli Yazılım Oluşturma başlıklı makaledir.
Android ve çoğu Linux ortamı arasındaki önemli farklardan biri uygulama korumalı alanıdır. Android'de, yerel kodla yazılanlar da dahil olmak üzere tüm uygulamalar uygulama korumalı alanında çalışır. Linux hakkında bilgisi olan geliştiriciler için bu çözüm, her uygulamaya çok sınırlı izinlere sahip benzersiz bir Kullanıcı Tanımlayıcı'nın (UID) verildiğini bilmektir. Bu konu, Android Güvenliğine Genel Bakış bölümünde daha ayrıntılı olarak ele alınmaktadır. Yerel kod kullanıyor olsanız bile uygulama izinleri hakkında bilgi sahibi olmanız gerekir.