60 saniyede bulut IAM saldırı yolları
Bulut IAM mimarisi, hangi kimliklerin (principals) hangi kaynaklar üzerinde hangi eylemleri gerçekleştirebileceğine karar verir. Bir yetki yükseltme (privilege escalation) yolu, tek tek bakıldığında son derece makul görünen birden fazla iznin bir araya gelerek tek bir kimliğe hiç kimsenin amaçlamadığı bir güç vermesiyle ortaya çıkar. Bu nedenle politikaları tek tek incelemek asıl saldırı yolunu tamamen gözden kaçırabilir.
Bulut güvenlik değerlendirmelerinden tertemiz çıkan raporlar beni her zaman daha çok endişelendirir. Ortamın kesinlikle güvensiz olduğunu düşündüğüm için değil; temiz bir taramanın gerçekte neyi ölçtüğünü bildiğim için. Bir CSPM (Cloud Security Posture Management) aracı, her IAM politikasını bir kural kümesine göre, her seferinde tek bir politika olacak şekilde puanlar. Yetki yükseltme ise tek bir politika değildir. Birden fazla politikanın arasından geçen bir saldırı yoludur ve bu politikaların neredeyse tamamı tek başlarına tamamen savunulabilirdir.
Tarayıcı izinleri okur. Saldırı ise izinlerin arasındaki boşluklardan inşa edilir.
Identity vs Resource: Kimsenin okumadığı tersine çevirme
IAM’de “bu kimlik bu işlemi yapabilir” demenin iki yolu vardır. Herkesin okuduğu yol identity policy’dir; yani kullanıcıya veya role eklenen ve neleri yapabileceğini listeleyen doküman. Herkesin gözden kaçırdığı yol ise resource policy’dir; yani bucket’a, kuyruğa veya role eklenen ve kendisine kimlerin dokunabileceğini listeleyen doküman.
Bunlar sadece farklı görünmekle kalmaz; birbirinin tam zıddı yönleri işaret ederler.
Bir identity policy “bu rol şu rolü devralabilir (assume edebilir)” der. Hedef roldeki güven politikası (trust policy) olan resource policy ise “şu kimlik beni devralabilir” der. Erişim, bu iki politikanın kesişimidir. Üstelik bunlardan biri kimliğin sahibi olan ekip tarafından değil, kaynağın sahibi olan ekip tarafından yazılır. Yetki yükseltmenin saklandığı yer tam olarak bu ayrımdır; çünkü kimliğin politikasını puanlayan bir CSPM aracı, sorunun diğer yarısını sormak için kaynağın politikasını asla açıp bakmaz.
Bu durum Kerberos delegasyon notundaki yapıyla birebir aynıdır: İzin hedef üzerinde saklanır ve kararı hedef verir. Bir dizinde bunu bir nesneye kimin yazabileceğini sorarak bulursunuz. Bir bulut hesabında ise bunu güven politikalarında, kaynak politikalarında ve hiç envanterini çıkarmadığınız KMS anahtar politikalarında kimlerin adının geçtiğini sorarak bulursunuz.
Politika taramasından sağ çıkan zincirler
Bir tarayıcı * üzerinde * yetkisi tanımlayan bir politikayı anında işaretler. Oysa gerçek bir hesapta neredeyse hiçbir şey bu kadar kaba değildir. Asıl tehlikeli yetkiler dar kapsamlı, sıradan ve sıkıcıdır; yalnızca sırayla okunduklarında ilgi çekici hale gelirler.
iam:CreatePolicyVersion. Kimlik, müşteri tarafından yönetilen bir politikanın (customer-managed policy) yeni bir sürümünü yayınlayabilir. Eğer bu politika daha üst düzey bir role bağlıysa, kimlik o üst düzey rolün ne yapmaya yetkili olduğunu tamamen yeniden yazabilir — hem de o role, rolün güven politikasına veya tarayıcının baktığı herhangi bir şeye hiç dokunmadan. Versiyonlama özelliği tam da politikaların güncellenebilmesi için vardır; bu yüzden bu izni içeren bir tanımlama rutin bir sistem yönetimi gibi görünür.
iam:UpdateAssumeRolePolicy. Güven politikasına (trust policy) yazma erişimi, kimin o role dönüşebileceğini doğrudan kontrol etmek demektir. PassRole iznine bile ihtiyaç duymaz. Kimlik, güven dokümanını kendisini hedef gösterecek şekilde yeniden yazar, rolü devralır ve artık o rolün sahip olduğu tüm yetkilere kavuşur. Rolün kendi izin politikası hiçbir zaman değiştirilmediği için, üretilecek herhangi bir uyarı kimsenin izlemediği önemsiz bir kimliğe yazılır.
Hesaplar arası (cross-account) güven üzerinden sts:AssumeRole. Buluttaki en güvenilir pivot noktası ve işaretlenme olasılığı en düşük olanıdır; çünkü bu güven ilişkisi bilerek ve isteyerek kurulmuştur. A hesabındaki bir rol, B hesabındaki bir kimliğe güvenir. B hesabını ele geçirdiğinizde A hesabına giden yol zaten açılmış, belgelenmiş ve onaylanmıştır. Tarayıcı buna yanlış diyemez; sistem bizzat bu şekilde tasarlanmıştır.
Tersten okunan iam:PassRole. PassRole herkesin bildiği bir izindir ve herkes bildiği için genellikle kontrol kuralı mevcuttur. Taramalardan sağ çıkan sürüm ise dolaylı olanıdır: Bir role politika bağlayabilen (attach) ve ardından o rolü bir servise devredebilen (pass) bir kimlik. İki izin de tek başına tehlikeli değildir. Ancak bir araya geldiklerinde saldırgan tarafından yazılmış bir politikaya sahip bir rol üretirler. İki ifade asla aynı politika dokümanında yer almadığından, tekil politika denetimlerinin hiçbiri bu ikisini bir arada göremez.
Tarayıcı neden bunu göremiyor?
Bir CSPM anlık görüntü (snapshot) aracıdır. Tek bir politikayı açar, tek bir kuralı uygular ve tek bir karar üretir. Bir yetki yükseltme zinciri ise bir çizge (graph) problemidir — BloodHound bağlantı ömrü notundaki argümanın aynısıdır; ancak buradaki bağlantılar (edges) ACL’ler yerine güven ilişkileridir ve çizge tek bir dizin yerine hesaplar arasına yayılır.
Bir principal mapper tam olarak bu boşluğu doldurur. Çizgeyi oluşturur (kim neyi devralabilir, hangi güven politikasında kimin adı geçiyor, her rol neyi bağlayabilir ve devredebilir) ve ardından BloodHound’un bir Active Directory domain’inde gezindiği gibi çizgeyi analiz eder:
# Mevcut kimlik bilgilerinden hesabın principal çizgesini oluşturun.
$ pmapper graph create --config config.json
# Bir CSPM'in asla sormadığı soru: Bu spesifik kimlik gerçekte nereye ulaşabilir?
$ pmapper query "who can do s3:GetObject with admin"
$ pmapper query "preset privesc *"
privesc önayarı işin asıl değerli yarısıdır. Aşırı izin verilmiş politikaları listelemez. Zincirleri listeler; bir kimliği bulunduğu yerden olmaması gereken yere taşıyan izin dizilimlerini gösterir. Farklı belgelerdeki iki ifadenin bir AssumeRole ile birbirine bağlanması, politika puanlama raporlarında asla görünmeyen ancak bir çizge sorgusunda tek adımda ortaya çıkan tipik bir örnektir.
Anlık görüntü yerine bir yol olarak test etmek
Verimli bir bulut testi * aramasıyla başlamaz. Belirli bir kimlikten (saldırganın ilk adımda ele geçirebileceği makul bir rolden) başlar ve o kimliğin yalnızca kalıcı izinleri kullanarak adım adım neye dönüşebileceğini sorgular.
# Hesaptaki her güven politikasını listeleyin — çoğu taramanın atladığı kaynak tarafı.
$ aws iam list-roles --query 'Roles[].{Role:RoleName,Trust:AssumeRolePolicyDocument}'
# Ardından tek bir hesabın taramasının dışında yaşayan hesaplar arası (cross-account) yüzey.
$ aws organizations list-accounts --query 'Accounts[].Id'
Hesaplar arası soru, tek hesaplı bir CSPM’in yapısal olarak yanıtlayamayacağı bir sorudur. A hesabından B hesabına olan güven A’da saklanır ancak yarattığı risk B’de yaşar. B ile sınırlandırılmış hiçbir araç A’da yaşayan bir politikayı asla işaretlemez. Biri tüm organizasyon genelinde doğrudan güven çizgesini sorgulamak zorundadır; aksi takdirde ortamdaki en güvenilir pivot noktası yapısal olarak görünmez kalır.
Kanıt matrisi (Evidence matrix)
| Sinyal | Neyi kanıtlar | Negatif kontrol | Savunucu doğrulaması |
|---|---|---|---|
| Kimlik izni ve hedef güven/kaynak politikası geçişe izin veriyor | Kimlik sınırı aşabilir; iki doküman da bunu tek başına kanıtlayamaz | Bir test rolünde bir tarafı kaldırın ve rol devralmanın reddedildiğini teyit edin | İlişkinin her iki tarafına karşı Access Analyzer ve politika simülasyonu kullanın |
AssumeRole sonrasında kapsamı daraltılmış zararsız bir eylem başarılı oluyor | Saldırı yolu başlangıç kimliğinden itibaren fiilen yürütülebilmektedir | Aynı eylemi reddetmesi gereken bir sınır (boundary) veya koşul ekleyip tekrarlayın | CloudTrail’de STS ve sonraki API olaylarını birbiriyle ilişkilendirin |
PassRole ve servis oluşturma/güncelleme hakları aynı rolde kesişiyor | Ayrı ifadeler üzerinden servisle ilişkili bir ayrıcalık yolu mevcuttur | iam:PassedToService veya rol kaynağını kısıtlayın ve zincirin kırıldığını teyit edin | Hem rolü devredebilen hem de ilgili servisi çağırabilen kimlikleri sorgulayın |
| Hesaplar arası geçiş, hedef taramanın dışındaki bir hesaptan başlıyor | Yetki yükseltme çizgesi idari mülkiyet sınırlarını aşmaktadır | Harici güveni iptal edin veya koşula bağlayın ve aynı kaynaktan testi tekrarlayın | External ID’ler ve principal koşulları dahil tüm organizasyon kapsamında güven çizgesini çıkarın |
Sıkça karşılaştığım ortak örüntü
Bu zincirlerdeki her tehlikeli izin, verildiği anda tamamen doğru olan bir gerekçeyle tanımlanmıştır. Bir dağıtım rolünün bir değişikliği yayınlamak için bir politikayı güncellemesi gerekiyordu, bu yüzden CreatePolicyVersion aldı. Bir tedarikçinin bir rolü devralması gerekiyordu, bu yüzden hesaplar arası güven oluşturuldu. Bir servisin bir role ihtiyacı vardı, bu yüzden biri aynı kimliğin önce bir politika bağlayabileceğini fark etmeden PassRole tanımladı.
Hiçbiri ilk bakışta yanlış görünmez. Bunlar sıradan sistem yönetimi adımlarıdır ve kural tabanlı bir tarayıcının bunları ortaya çıkaramamasının tam nedeni de budur: Ortada işaret edilecek tek bir yanlış yapılandırma yoktur, yalnızca kimsenin baştan sona sırayla okumadığı bir kararlar dizisi vardır.
Bir sertifika yetkilisini iki ekibin arasında kaldığı için denetimsiz bırakan dinamik neyse; bulut güven ilişkilerini de iki hesabın arasında kaldığı için denetimsiz bırakan dinamik odur. Kimlik ekibi kullanıcının sahibidir, platform ekibi rolün sahibidir ve hiçbiri saldırı yolunun sahibi değildir.
Savunuculara teslim edilmesi gerekenler
Politikayı değil, saldırı yolunu gösterin. Belirli kimliği, yürüyebileceği izin dizilimini ve kaldırıldığında zinciri kıran en erken tekil adımı belirtin. “IAM aşırı yetkilendirilmiş” diyen bir rapor genel bir temizlik projesi başlatır. “Bu servis rolü yeni bir politika sürümü yayınlayabilir, yönetici rolünü devralabilir ve canlı ortama geçebilir” diyen bir rapor ise doğrudan somut bir bilet açılmasını sağlar.
Kimliği kaynaktan ayırın. Her güven politikası, kaynak politikası ve KMS anahtar politikası taramanın yanlış tarafında yaşayan birer erişim kararıdır. Bunları açıkça envantere alın; çünkü kimlik tarafındaki araçlar bunu sizin yerinize asla yapmaz.
Hesaplar arası güveni haritalandırın. Organizasyon genelindeki principal haritası, hesaplar arası pivotları yakalayan tek çıktıdır ve çoğu kurum bunu bugüne kadar hiç çıkarmamıştır. Bunu bir kez kurun ve düzenli olarak çalıştırın; çünkü güven ilişkileri de tıpkı izinler gibi zamanla birikir: Yeni bir tedarikçi, yeni bir hesap, yeni bir “geçici” tanımlama.
Tarayıcı yanılmıyor. Yalnızca saldırganın sorduğu sorudan tamamen farklı bir soruyu yanıtlıyor.
Bu teknik not ne kadar güncel?
En son kaynak incelemesi, içerik güncellemesi veya yayın tarihi gösterilmektedir.
Yazar teknik incelemeyi tamamladı. Bu etiket tek başına laboratuvar yeniden üretimi iddiası taşımaz.
