Series · 1 partsiOS Security BoundariesPart 1 · You are here
- 1Uzantı Sandbox'taydı. Paylaşımlı Konteyner Sınırı Hâlâ Aşıldı: iOS App GroupsYou are here
60 saniyede iOS sınırları
Bir iOS uygulaması birbirinden bağımsız olarak çalıştırılan birden fazla hedef (target) barındırabilir: Ana uygulama, bir Share uzantısı (Share extension), bildirim servisi uzantısı (Notification Service Extension), bir widget, bir App Clip, bir File Provider uzantısı veya sistem tarafından tanımlanmış başka bir uzantı noktası (extension point). Bu hedefler birlikte imzalanır ve tek bir ürün olarak teslim edilir; ancak çalışma zamanında (runtime) tek bir sürece veya ortak özel bir konteynere dönüşmezler.
Bu izolasyon son derece güçlü bir varsayılandır. Sistem, bir uzantıyı yalnızca tanımlı görevi için başlatır ve ana uygulamanın talebine aracılık eder. Kapsayıcı uygulama (containing app) ile uzantı birbirlerinin özel uygulama konteynerlerini doğrudan açamazlar.
App Groups mekanizması bu noktada bilinçli bir istisna yaratır. Aynı App Group entitlement’ına sahip hedefler; cihaz üzerinde paylaşılan bir konteyneri, paylaşılan ayarları (UserDefaults) ve desteklenen yapılandırmalarda paylaşılan Keychain ögelerini okuyup yazabilirler. Bu tasarım oldukça kullanışlıdır, ancak güvenlik anlamı sıklıkla yanlış yorumlanır:
Entitlement, yalnızca imzalanmış bir hedefin paylaşılan ad alanına erişebileceğini kanıtlar. Oraya yazılan her değerin her tüketici açısından güvenilir olduğunu kanıtlamaz.
Bu nedenle bir sızma testi şu dört unsuru birlikte haritalandırmalıdır: Paylaşılan durumu kim üretebilir, ne saklanabilir, başka bir hedef bunu ne zaman tüketir ve bu tüketici hangi etkiyi yaratabilir? Hata genellikle “sandbox çöktü” şeklinde ortaya çıkmaz. Hata, meşru bir veri paylaşım mekanizmasının sessizce bir yetkilendirme mekanizmasına dönüştürülmesidir.
Tek ürün, birden fazla güvenlik süjesi
Apple’ın uzantı mimarisi, her uzantıyı ayrı bir ikili dosya (binary) olarak ele alır. Bir host uygulaması, uzantıyı sistem tarafından tanımlanan bir uzantı noktası üzerinden çağırır; bu sırada ana uygulama arka planda çalışmıyor dahi olabilir. Geliştiricinin dolaylı veri alışverişine ihtiyacı olduğunda, ürün açıkça bir App Group yapılandırmasını devreye sokar.
Bu durum hiyerarşik bir yapıdan ziyade bir çizge (graph) ilişkisi doğurur:
Host uygulama, ana kapsayıcı uygulama ve uzantı birbirinden farklı rollere sahiptir. “Host”, uzantıyı o anda ekranda gösteren veya çağıran uygulamadır. “Containing app”, uzantıyı dağıtmak için paketleyen ana uygulama paketidir. Bu rollerin karıştırılması hatalı test senaryolarına yol açar; çünkü uzantı host tarafından kontrol edilen girdileri alırken, kapsayıcı uygulama ile yalnızca belirli bir durumu paylaşır.
App Groups neleri sağlar — neleri sağlamaz?
com.apple.security.application-groups entitlement’ı, bir hedefin katılabileceği grupları listeler. Apple, iOS App Group tanımlayıcılarını benzersiz olacak şekilde kaydeder. Grup üyeliği şunları sağlayabilir:
- Disk üzerinde paylaşılan bir konteyner dizini;
- Paylaşılan bir
UserDefaultspaketi; - Uzantı destekli arka plan veri transferleri (background transfer) için ortak bir konum;
- Desteklenen süreçler arası iletişim (IPC) mekanizmaları;
- App Group tanımlayıcısının bir Keychain access group olarak kullanılması.
Bu garantiler önemlidir. Rastgele üçüncü taraf bir uygulama, çalışma zamanında bu entitlement’ı kendi kendine üreterek başka bir ekibin kayıtlı grubuna dahil olamaz. Hedeflerin hangilerinin gruba katılabileceğini kod imzalama ve provisioning profilleri belirler.
Ancak grup üyeliği kasıtlı olarak kaba taneciklidir (coarse-grained). Beş farklı hedef aynı grubu paylaşıyorsa platform; account.json dosyasını yalnızca ana uygulamanın güncellemesi gerektiğini, pending-message.plist dosyasını yalnızca bildirim uzantısının yazabileceğini veya widget’ın yalnızca salt okunur bir kopya alması gerektiğini bilemez. Dosya sistemi düzeyinde, yetkilendirilmiş her üye paylaşılan konteyner üzerinde okuma ve yazma hakkına sahiptir.
Uygulamanın semantik bir politika eklemesi gereken yer tam olarak burasıdır:
| Platform gerçeği | Yanıt bekleyen uygulama sorusu |
|---|---|
| Hedef imzalanmış ve grup için yetkilendirilmiştir | Bu hedef, bu nesne için onaylanmış bir üretici midir? |
| Paylaşılan dosya grup konteynerinin içindedir | Formatı, sahibi, sürümü, boyutu ve durum geçişi geçerli midir? |
| Keychain ögesi erişilebilir bir access group’tadır | Bu hedef aynı kimlik bilgisine veya anahtar materyaline erişmeli midir? |
| Data Protection dosyayı diskte şifreler | Doğru cihaz kilit durumunda ve doğru iş akışında mı erişilebilir haldedir? |
| Bir arka plan transferi gruba veri yazmıştır | Yanıt doğrulanmış mıdır ve işlemi başlatan hesap ile taleple eşleşmekte midir? |
Şifreleme, sandbox ve kod imzalama; uygulama paylaşılan veri hakkında yanlış kararlar alsa bile işlevini sürdürür. Bir güvenlik raporu, platform kontrolünün aşıldığını iddia etmek yerine, uygulamanın doğrulamakta başarısız olduğu değişmez kuralı (invariant) açıkça tanımlamalıdır.
İmzalı hedef envanteriyle başlayın
En kullanışlı ilk analiz çıktısı bir URL scheme listesi değildir; hedef-entitlement matrisidir. Müşteri tarafından sağlanan bir .ipa dosyasının yetkili denetimi için, arşivi izole bir çalışma alanında açın ve uygulamayı cihazda başlatmadan önce her çalıştırılabilir dosyanın envanterini çıkarın.
Salt okunur örnekler:
unzip -q CustomerApp.ipa -d extracted
find extracted/Payload -type d -name '*.appex' -print
find extracted/Payload -type f -perm -111 -print
codesign -d --entitlements :- extracted/Payload/CustomerApp.app
codesign -dvvv extracted/Payload/CustomerApp.app
Entitlement denetimini her bir .appex ve gömülü çalıştırılabilir dosya için tekrarlayın. Orijinal IPA dosyasının hash değerini, çıkarılan hedefin yolunu ve imzalama çıktısını saklayın. Bir uzantının entitlement’larını asla ana uygulamadan yola çıkarak varsaymayın.
En azından şunları kaydedin:
| Hedef | Extension point | App Groups | Keychain grupları | Korunan kaynaklar | Girdiler | Çıktılar |
|---|---|---|---|---|---|---|
| Ana uygulama | application | tam tanımlayıcılar | tam tanımlayıcılar | tanımlı yetenekler | kullanıcı, linkler, ağ | dosyalar, sırlar, istekler |
| Share uzantısı | share | tam tanımlayıcılar | tam tanımlayıcılar | host tarafından sağlanan ögeler | uzantı bağlamı | paylaşılan taslaklar |
| Bildirim servisi | notification service | tam tanımlayıcılar | tam tanımlayıcılar | kullanılıyorsa ağ | APNs payload’u | render edilen içerik, önbellek |
| Widget | widget | tam tanımlayıcılar | tam tanımlayıcılar | timeline verisi | paylaşılan snapshot | UI yansıması |
| File Provider | file provider | tam tanımlayıcılar | tam tanımlayıcılar | belge domain’i | uzak/yerel ögeler | paylaşılan dosya durumu |
Buradaki amaç asimetriyi ortaya çıkarmaktır. Küçük bir uzantı güvenilmeyen zararlı içerikleri ayrıştırırken; kimliği doğrulanmış ağ oturumlarına, özel kullanıcı verilerine veya daha güçlü işlevsel yetkilere sahip bir ana uygulama ile yazılabilir ortak bir konteyneri paylaşıyor olabilir.
Paylaşılan her nesneyi bir protokol gibi ele alın
Paylaşılan bir plist dosyası veya SQLite satırı ilk bakışta sıradan bir depolama gibi görünebilir. Oysa bağımsız olarak zamanlanan süreçler arasında bu nesne bir protokoldür. Üreticileri, tüketicileri, bir şeması, sıralama kuralları ve hata işleme davranışları vardır.
Güvenilir bir paylaşılan nesne normalde şunlara ihtiyaç duyar:
- Katı bir şema ve açık bir sürüm numarası;
- Dizeler, koleksiyonlar, dosyalar ve çözümlenen (decode edilen) payload’lar için sınır kontrolleri;
- Yalnızca nesnenin kendisinden alınmayan bir hesap veya kiracı (tenant) bağlamı;
- Tüketicinin doğrulayabileceği bir durum makinesi (state machine) geçişi;
- Beklenen kök dizine sabitlenmiş güvenli dosya yolu inşası;
- Atomik değiştirme veya veritabanı işlem (transaction) semantiği;
- İş akışının ihtiyaç duymadığı sembolik linklerin (symlink) veya dosya türlerinin reddedilmesi;
- Eski niyetlerin iki kez işlenmesini engelleyen tazelik veya replay kuralı;
- İşlemin doğuracağı sonuçların ağırlığına yetecek güçte bir kaynak kanıtı (provenance).
Bir uzantının kavramsal olarak şu iş kaydını yazdığını düşünün:
{
"operation": "upload",
"account": "A-104",
"relativePath": "Exports/report.pdf",
"destination": "case-781"
}
Ana uygulama “bu dosya App Group dizinimizde var” olgusunu karşıya yüklemeyi (upload) gerçekleştirmek için bir yetki olarak yorumlamamalıdır. Aktif hesabı kendi güvenilir oturum durumundan türetmeli, dosya yolunu beklenen kök altında çözümlemeli, desteklenmeyen nesne türlerini reddetmeli, hedefi güvenlik politikasına bağlamalı ve tekrar oynatmayı (replay) tespit edilebilir kılmalıdır. Paylaşılan nesne niyeti taşıyabilir; ancak yetkiyi kendisi üretemez.
Keychain paylaşımı bir yetenek kararıdır
iOS’ta bir uygulama kendi Keychain ögelerine ve imzalı entitlement’ları ile kendisine tanınan access group’lardaki ögelere erişebilir. Bir Keychain ögesi tek bir access group’a aittir. Bir hedef gerekli entitlement’a sahip değilse platform erişimi engeller.
Bu güçlü bir sınırdır; ancak grubun kapsamını tasarım belirler. Aynı access group’un bir widget’a, bildirim uzantısına, App Clip’e ve ana uygulamaya verilmesi, her bir hedefe o gruptaki tüm ögeleri sorgulama teknik imkanını tanır. İnceleme, yalnızca Xcode’un bu yeteneği sağlayıp sağlamadığına değil, hedeflerin gerçekten aynı sırra ihtiyaç duyup duymadığına odaklanmalıdır.
Şu soruları birbirinden ayırın:
- Erişilebilirlik (Reachability): Hangi imzalı hedefler access group’a hitap edebilir?
- Öge konumu: Hangi spesifik ögeler özel bir grup yerine bu paylaşılan gruba yazılmıştır?
- Erişim koşulları (Accessibility): Öge hangi cihaz ve kimlik doğrulama koşulları altında döndürülebilir?
- Kullanım amacı: Hedef ham kimlik bilgisine mi ihtiyaç duymaktadır, yoksa sadece türetilmiş dar bir sonuca mı?
- İptal (Revocation): Oturumu kapatma, hesap değiştirme, uygulamanın silinmesi veya uzantının devre dışı bırakılması durumunda paylaşılan kimlik bilgilerine ne olur?
kSecAttrAccessible ve erişim kontrol bayrakları, bir ögenin cihaz durumuna ve kullanıcı kimlik doğrulamasına bağlı olarak ne zaman erişilebilir olacağını yönetir. Ancak yetkilendirilmiş gereksiz geniş hedef kümesini daraltmaz. Tersine, dar bir access group da uygunsuz kilit durumunda erişilebilir kalan bir ögeyi güvenli kılmaz. Her iki boyut da kanıt matrisinde yer almalıdır.
Yaşam döngüsü saldırı yüzeyinin parçasıdır
Uzantılar kısa ömürlüdür ve bir isteği tamamladıktan sonra sistem tarafından sonlandırılabilirler. Kapsayıcı uygulama ve uzantı ayrıca paylaşılan konteynere farklı zamanlarda erişebilirler. Bu durum, tamamen etkileşimli bir testin gözden kaçıracağı ara durumlar yaratır:
- Ana uygulama askıya alınmışken (suspended) uzantının veri yazması;
- Eski bir uzantı kalıntısı dururken ana uygulamanın şemayı yükseltmesi;
- Kuyruğa alınan bir işin üretilmesi ile tüketilmesi arasında hesabın değişmesi;
- Oturum kapatıldıktan sonra bir arka plan URL oturumunun tamamlanması;
- İki sürecin aynı paylaşılan ayarları veya veritabanı kaydını eşzamanlı güncellemesi;
- Gruptaki bir uygulama silinirken diğerinin yüklü kalmaya devam etmesi;
- Cihaz kilit geçişleri sırasında korunan verinin erişilebilir veya erişilemez hale gelmesi.
Bunları rastgele yarış durumu (race condition) denemeleri olarak değil, durum geçişleri olarak test edin. Müşteri tarafından onaylanmış bir test cihazında sentetik hesaplar ve hassas olmayan test verileri kullanın. Ön koşulu, üreticiyi, nesne hash’ini, zaman damgalarını, kilit durumunu, tüketen süreci ve ortaya çıkan etkiyi kayıt altına alın.
Savunulabilir bir test sırası
1. Kapsamı ve test düzlemlerini belirleyin
Yalnızca müşteri tarafından sağlanan bir derlemeyi, onaylanmış bundle tanımlayıcılarını, test hesaplarını ve atanmış bir test cihazını kullanın. Hangi gözlemlerin statik inceleme, Simülatör, normal bir fiziksel cihaz ve enstrümante edilmiş araştırma cihazları üzerinden mümkün olduğuna karar verin. Simülatör davranışını asla donanım tabanlı bir Keychain veya fiziksel cihaz Data Protection sonucu gibi sunmayın.
2. Hedefleri ve geçerli entitlement’ları envanterleyin
İmzalı dosyalardan hedef matrisini çıkarın. Provisioning profilindeki niyet ile her bir çalıştırılabilir dosyanın üzerindeki entitlement’ları karşılaştırın. Paylaşılan her bir App Group ve Keychain access group alanını vurgulayın, ardından tüm üyelerini listeleyin.
3. Paylaşılan nesneleri sınıflandırın
Paylaşılan her dosya, veritabanı, ayar paketi, arka plan oturumu ve Keychain ögesi için şunları kaydedin:
- Üretici hedefler ve tüketici hedefler;
- Verinin gizli, yetkili mi yoksa yalnızca bir önbellek mi olduğu;
- Beklenen şema ve boyut;
- Hesap ve cihaz durumu bağlamı;
- Bozulma, değiştirme, tekrar oynatma, silme veya gecikmenin yaratacağı etki.
4. Tek seferde tek bir kontrollü mutasyon uygulayın
Zararsız sentetik değerlerle başlayın: bozuk sürümler, boyutu aşılmış ancak sınırlandırılmış alanlar, bayatlamış bir hesap tanıtıcısı, beklenmeyen bir göreli dosya yolu veya tekrarlanan bir iş tanımlayıcısı. Gerçek kullanıcı verilerine karşı asla yıkıcı işlemler test etmeyin. Tüketicinin bir ağ, hesap, dosya veya kriptografik etki yaratmadan önce isteği reddedip reddetmediğini gözlemleyin.
5. Yaşam döngüsü sınırları boyunca tekrarlayın
İlgili olduğu durumlarda aynı sınırlandırılmış testi askıya alma, yeniden başlatma, cihaz kilitleme/açma, hesap değiştirme ve arka plan işlemi tamamlanması sonrasında tekrarlayın. Ulaşılan sonuç, davranışı değiştiren tam durum geçişini açıkça adlandırmalıdır.
6. Etkiyi ve düzeltmeyi kanıtlayın
Yazılabilir paylaşılan bir dosyanın varlığı tek başına beklenen platform davranışıdır, bir güvenlik açığı değildir. Kanıt, kontrollü mutasyonu yetkisiz veya güvensiz bir tüketici etkisine doğrudan bağlamalıdır. İyileştirme sonrasında aynı testi tekrarlayın ve reddedilme durumunu, olayın kayda geçtiğini ve önceki yan etkinin ortadan kalktığını gösterin.
Yaygın yanlış pozitifler (False Positives)
“Uzantı App Group konteynerini okuyabiliyor”
Bu durum grup üyeliğinin zaten beyan edilmiş varlık nedenidir. Yalnızca üyelik gerekenden daha geniş olduğunda, hassas nesneler yanlış ad alanına konulduğunda veya bir tüketici başka bir üyenin verisine yetki sınırlarının ötesinde güvendiğinde bir bulguya dönüşür.
“Paylaşılan dosya uygulama tarafından şifrelenmemiş”
iOS Data Protection mekanizması dosyalar ve veritabanları için donanım destekli platform şifreleme sınıfları sağlar. Asıl anlamlı soru hangi sınıfın uygulandığı, verinin ne zaman erişilebilir olduğu, yedeklemelerin ve senkronizasyonun durumu ve yetkili bir hedefin sistem veriyi döndürdükten sonra açık metni (plaintext) kötüye kullanıp kullanamayacağıdır.
“Bir Keychain sorgusu iki farklı hedeften de başarılı dönüyor”
Bu başarı, paylaşılan bir access group’un tasarlanmış olağan sonucu olabilir. Bir etki atfetmeden önce ögeyi, grubu, hedef kümesini, erişilebilirlik sınıfını, kullanıcı varlığı gereksinimini ve iş gerekçesini ortaya koyun.
“Uzantı paketi uygulamanın içinde yer alıyor, dolayısıyla güvenilir bir girdidir”
Kod imzalı ürünün bir parçasıdır; ancak uzantı başka bir host uygulamadan, bir bildirim payload’ından, bir belge sağlayıcıdan veya ağ içeriğinden gelen verileri ayrıştırıyor olabilir. İmzalanmış kod bile saldırgan tarafından yönlendirilen bir durumun üreticisine dönüşebilir.
“Yalnızca Jailbreak ile elde edilen erişim, prodüksiyonda sömürülebilirliği kanıtlar”
Bir araştırma cihazı uygulama detaylarını ortaya çıkarabilir ve hipotez kurmaya yardımcı olabilir. Ancak yetkisiz standart bir prodüksiyon uygulamasının aynı sınırı aşabileceğini kanıtlamaz. Gözlem düzlemini ve eksik olan ön koşulları raporda açıkça belirtin.
Kanıt matrisi
| İddia | Minimum kanıt | Güçlü kanıt | Yalnızca buna dayanarak iddia etmeyin |
|---|---|---|---|
| Bir hedef bir App Group’a aittir | O hedeften alınan geçerli imzalı entitlement | Provisioning profili karşılaştırması ve kontrollü konteyner erişimi | Paylaşılan her nesnenin hassas veya güvensiz olduğu |
| Bir uzantı paylaşılan bir alanı yönetir | Kontrollü sentetik yazma ve nesne farkı (diff) | Nesne hash’i ve zaman damgaları içeren üretici izi | Ayrıcalıklı bir etkinin ortaya çıktığı |
| Tüketici güvensiz ortak duruma güveniyor | Tekrarlanabilir bir mutasyonun tüketici kararını değiştirmesi | Üreticiyi, nesneyi, tüketiciyi ve etkiyi bağlayan tam iz | Sandbox kaçışı veya keyfi kod çalıştırma |
| Keychain kapsamı gerekenden daha geniştir | Access-group üyeliği ve erişilebilen test ögesi | Hedef-öge bazında gereklilik analizi ve kilit durumu sonuçları | İlgisiz üçüncü taraf uygulamalarca sızdırılabileceği |
| Data Protection davranışı zayıftır | Fiziksel cihazda belgelenmiş kilit durumu ve dosya sınıfı sonucu | Tekrarlanan soğuk/kilitli/açık durum ölçümleri | Sadece Simülatörden alınan donanım davranışı |
| Arka plan tamamlama oturum kapatmayı aşıyor | Oturum kapatmadan önce başlatılan ve sonrasında tüketilen transfer | Hesaba bağlı istek/yanıt izi ve düzeltme tekrarı | Kanıt olmaksızın gerçek müşteri verisinin sızdığı |
| Düzeltme çalışıyor | Orijinal senaryonun yan etki doğurmadan reddedilmesi | Negatif testler, telemetri ve regresyon kapsamı | Tüm paylaşılan konteyner risklerinin yok edildiği |
İyileştirme nasıl kurgulanmalıdır?
En güçlü düzeltme genellikle hem üyeliği hem de anlamsal yetkiyi daraltır:
- Her hedefe yalnızca ihtiyaç duyduğu App Group ve Keychain gruplarını tanımlayın.
- Başka bir hedef ham nesneye gerçekten ihtiyaç duymadıkça kimlik bilgilerini özel alanda tutun.
- Her hedefi tek bir evrensel gruba koymak yerine, paylaşılan ad alanlarını amaca göre bölün.
- Grup dosyalarını güvenilmeyen protokol mesajları gibi ele alın: katı şema, sınırlar, sürümleme, hesap bağlama, dizin hapsetme, tazelik ve atomik durum geçişleri.
- Daha yüksek yetkiye sahip bir tüketicinin yetkilendirmeyi kendi güvenilir durumundan türetmesini sağlayın.
- Widget’lar ve uzantılar için mümkün olan en küçük veri yansımasını saklayın.
- Oturum kapatma, hesap değiştirme ve üyelik güncellemelerinde paylaşılan durumu temizleyin veya yenileyin.
- Sırları kaydetmeden üreticiyi, nesneyi, kararı ve etkiyi birbirine bağlayacak yeterli tanımlayıcıları günlüğe kaydedin.
- Kilit durumu ve arka plan oturum davranışlarını fiziksel bir cihazda test edin.
- Doğrulanan her sınır hatası için bir regresyon test senaryosu saklayın.
Bazen doğru tasarım yeni bir doğrulama kontrolü eklemek değildir. Paylaşılan sırrı tamamen kaldırmak, yazılabilir bir iş dosyasını dar kapsamlı bir aracı işlemle değiştirmek ya da bir uzantıya hiçbir yetki türetemeyecek salt okunur bir veri projeksiyonu sunmaktır.
Sonuç
iOS sandbox mekanizması kritik bir soruyu yanıtlar: Bu çalıştırılabilir dosya hangi kaynaklara erişebilir? App Groups ve Keychain access groups ise bir başkasını yanıtlar: Hangi imzalı hedefler seçilen kaynakları kasıtlı olarak paylaşabilir? Ancak bu mekanizmaların hiçbiri uygulamanın iş mantığı kurallarını bilemez.
Bu nedenle savunulabilir güvenlik sorusu şudur:
Daha düşük bağlama sahip bir üretici, paylaşılan bir ad alanına veri yazıp; başka bir hedefin kaynak, durum ve yetkilendirmeyi bağımsız olarak doğrulamaksızın bu veriyi daha yüksek sonuçlar doğuran bir etkiye dönüştürmesine neden olabilir mi?
Bu soru tek bir uzantı türünün ötesine geçer. Widget’lara, bildirimlere, App Clip’lere, File Provider’lara, arka plan transferlerine ve gelecekteki Apple platform hedeflerine de uygulanabilir. Ayrıca bu araştırma serisine kararlı bir metodoloji kazandırır: Çalıştırılabilir dosyayı haritalandırın, entitlement’larını çıkarın, paylaşılan nesneyi takip edin ve nihai etkiyi kanıtlayın.
Kaynaklar
- Apple Platform Security: App security overview
- Apple Platform Security: App protection and App Groups
- Apple Developer: App Groups entitlement
- Apple Developer: Configuring App Groups
- Apple Developer: Sharing keychain items among apps
- Apple Developer: Restricting keychain item accessibility
- Apple Developer: App Extension architecture
- Apple Developer: Sharing data with a containing app
- Apple Developer:
sharedContainerIdentifier
Bu teknik not ne kadar güncel?
En son kaynak incelemesi, içerik güncellemesi veya yayın tarihi gösterilmektedir.
Birincil kamu kayıtları kontrol edildi. Ortama özgü davranış, ayrıca yeniden üretilmedikçe iddianın dışındadır.
- support.apple.com · web ↗
- support.apple.com · web ↗
- developer.apple.com · com.apple.se…ication-groups ↗
- developer.apple.com · configuring-app-groups ↗
- developer.apple.com · sharing-acce…ection-of-apps ↗
- developer.apple.com · restricting-…-accessibility ↗
- developer.apple.com · ExtensionOverview ↗
- developer.apple.com · ExtensionScenarios ↗
- developer.apple.com · sharedcontaineridentifier ↗
