spacer.png, 0 kB
Bilgi için: bilgi at bilgiguvenligi gov tr   

 

spacer.png, 0 kB
spacer.png, 0 kB
Kullanıcı Erişim Bilgilerinin (Access Token) Tahrif Edilmesi Yazdır E-posta
Osman PAMUK, TÜBİTAK BİLGEM   
20.11.2011

Kullanıcı erişim bilgileri (Access Token) Windows işletim sistemindeki işlemlerin (process) ve iş parçacıklarının (thread) güvenlik bilgilerinin saklandığı veri yapılarıdır. Bir erişim bilgisi içinde, ilgili olduğu işlem veya iş parçacığının hangi kullanıcı hesabı  ve kullanıcı grubu ile bağlantılı olduğu ve hangi ayrıcalıklara sahip olduğu bilgisi bulunur.

İşletim sistemi, bir işlem veya iş parçacığının herhangi bir nesneye erişip erişemeyeceğini ve hangi nesnede hangi tür işlemleri yapıp yapamayacağını, erişim bilgisi içindeki o işlem veya iş parçacığının hangi kullanıcı hesabıyla çalıştığı ve bu kullanıcının hangi gruplara üye olduğu bilgisine bakarak karar vermektedir. Mesela herhangi bir dosya veya registry anahtarına ulaşıp okuma veya yazma yapmaya çalıştığınızda sahip olduğunuz erişim bilgisindeki kayıtlar ile nesne üzerindeki bilgiler eşleştirilmekte ve bunun sonucunda istediğiniz yetkiyi alıp alamayacağınıza karar verilmektedir. Bunun yanında erişim bilgisi içindeki ayrıcalıklar listesi ile işletim sistemi, erişim bilgisinde belirtilen kullanıcının işlem veya iş parçacığının hangi özel sistem işlemlerini yapıp yapamacağını da belirler. Bu ayrıcalıkların içinde "Take Ownership" yani herhangi bir nesnenin sahibi olabilme yetkisi ve "Debug programs" yani herhangi bir işlemde hata ayıklama yapabilme yetkisi gibi çok önemli sistem işlemleri bulunmaktadır. [1]

Bu yazıda da Windows 7'deki bu kullanıcı erişim bilgilerini tahrif etmek ve sonuçta hak yükseltme veya hesap taklit etme(impersonation) saldırılarına yol açabilecek iki yöntemden bahsedilecektir. Amacımız şu anda pratik uygulamalarında zorluklar olmasına rağmen bu tür potansiyel saldırı alanlarının en yeni işletim sistemlerinde de olduğunu göstermektir.

Herşeyden önce şunu belirtmek gerekir ki, bahsedeceğimiz yöntemler işletim sistemi çekirdeğinde değişiklikler içermektedir. Tabiî ki kötü niyetli bir yazılımın da çekirdeğe  ulaşabilmesi için önce bir açıklık tespit etmesi ve bunu kullanabilmesi (exploit edebilmesi) gerekmektedir. Daha önce vista ile gelen çekirdek koruma tekniklerinden ve bu korumayı aşmak için kullanılabilecek bir yöntemden bahsedilmişti [2]. Fakat Windows 7'nin en güncel konumunda "memory randomization" özelliği sayesinde bu veya benzeri bir açıklığı halihazırda kullanmak mümkün değildir. Bu yüzden bu yazıda, inceleyeceğimiz yöntemlerden bahsederken, çekirdeğe ulaşmak için güvenli bir yöntem olan kernel debugger attachment (çekirdeğe hata ayıklıyıcı bağlama) yöntemini kullanacağız.

Saldırı yöntemlerini incelemeye başlamadan önce erişim bilgilerinin sistemde nasıl tutulduğu ve kulllanıldığına kısa bir göz atalım.

Windows 7 64 bit bir işletim sistemindeki erişim bilgilerinin (access token) yapısı aşağıdaki gibidir:

0: kd>  dt -v nt!_token

struct _TOKEN, 33 elements, 0x310 bytes

   +0x000 TokenSource      : struct _TOKEN_SOURCE, 2 elements, 0x10 bytes

   +0x010 TokenId          : struct _LUID, 2 elements, 0x8 bytes

   +0x018 AuthenticationId : struct _LUID, 2 elements, 0x8 bytes

   +0x020 ParentTokenId    : struct _LUID, 2 elements, 0x8 bytes

   +0x028 ExpirationTime   : union _LARGE_INTEGER, 4 elements, 0x8 bytes

   +0x030 TokenLock        : Ptr64 to struct _ERESOURCE, 15 elements, 0x68 bytes

   +0x038 ModifiedId       : struct _LUID, 2 elements, 0x8 bytes

   +0x040 Privileges       : struct _SEP_TOKEN_PRIVILEGES, 3 elements, 0x18 bytes

... 

İşletim sisteminin çekirdeğinde çalıştırılan  iş parçacıklarının ve işlemlerin bilgileri "EPROCESS" ve "ETHREAD" yapılarıyla tanımlanan çekirdek nesnelerinde tutulmaktadır. Bu nesneler aynı zamanda işlem veya iş parçacığının sahip olduğu erişim bilgilerinin adres bilgisini de tutmaktadır.

"EPROCESS" yapısı ve "Token" pointer: 

0: kd> dt -v nt!_eprocess

struct _EPROCESS, 135 elements, 0x4d0 bytes

   +0x000 Pcb              : struct _KPROCESS, 37 elements, 0x160 bytes

   +0x200 ObjectTable      : Ptr64 to struct _HANDLE_TABLE, 15 elements, 0x68 bytes

   +0x208 Token            : struct _EX_FAST_REF, 3 elements, 0x8 bytes

   +0x210 WorkingSetPage   : Uint8B

Yukarıda gösterildiği gibi bir işlem nesnesinin 0x208'inci baytında işlemin erişim bilgisi nesnesinin adresini içeren _EX_FAST_REF yapısı bulunmaktadır. Bu yapıya biraz daha ayrıntılı bir şekilde göz atarsak:

1: kd>dt -b -v nt!_EX_FAST_REF

struct _EX_FAST_REF, 3 elements, 0x8 bytes

   +0x000 Object           : Ptr64 to

   +0x000 RefCnt           : BitfieldPos 0, 4 Bits

   +0x000 Value            : Uint8B

_EX_FAST_REF yapısı haddizatında sadece 8 baytlık bir işaretleyicidir (pointer). Fakat bu işaretleyicininf son 4 biti bu nesneye yapılan referansların sayısını tutmak için ayrılmıştır. Bu nedenle _EX_FAST_REF yapısından gerçek adresi bulmak için son 4 bit sıfırlanmalıdır.

Ayrıcalık Yükseltme

Bir kullanıcının sahip olduğu ayırcalıkların neler olduğunu erişim bilgisi nesnesinin baştan 0x40'ıncı baytında ki SEP_TOKEN_PRIVILEGES yapısında bulunmaktadır.

0: kd> dt -s -b _SEP_TOKEN_PRIVILEGES

nt!_SEP_TOKEN_PRIVILEGES

   +0x000 Present          : Uint8B

   +0x008 Enabled          : Uint8B

   +0x010 EnabledByDefault : Uint8B

Yukarıda da görüldüğü gibi SEP_TOKEN_PRIVILEGES yapısı 8 baytlık üç alandan oluşmaktadır. İlk alan "Present" kullanıcı işlem veya iş parçacığının sahip olabileceği  bütün ayrıcalıkların bilgisini, ikinci alan "Enabled" halihazırda  etkinlendirilmiş ayrıcalıkların bilgisini, üçüncü alan "EnabledByDefault" ise kullanıcı işlem veya iş parçacığının ilk oluşturulduğu anda sahip olacağı ayrıcalıkların bilgisini tutmaktadır. Kullanıcı işlem veya iş parçacığı ilk oluşturulduğunda bütün kullanabileceği ayrıcalıklar aktif hale getirilmemektedir. Bu ayrıcalıklar zamanla ihtiyaç duyulduğunda eğer "Present" alanında, ilgili ayrıcalığa sahip olabilir bilgisi mevcutsa aktif hale getirilmektedir. Bu alanlarda her  ayrıcalık bir bitle temsil edilmektedir. Sonuç olarak herhangi bir ayrıcalığa sahip olmasını istediğiniz bir işlemin ve iş parçacığının o ayrıcalıkla ilgili erişim bilgisindeki bitlerini 1 olarak değiştirmeniz gerekli hakları vermek için yeterlidir.

Mesela  normal kullanıcı haklarıyla çalıştırdığımız "cmd.exe" programının sahip olduğu hakları değiştirmek istiyoruz. Bunun için ilk önce "cmd.exe" programımızın erişim bilgisi nesnesindeki SEP_TOKEN_PRIVILEGES yapısına ulaşmamız gerekecektir.

Programımızın işlem nesnesinin adresini bulmak için debuggerımızdaki "!process" komutunu kullanabiliriz:

1: kd> !process 0 0 cmd.exe

PROCESS fffffa80010c1060

SessionId: 1  Cid: 0b90    Peb: 7fffffdf000  ParentCid: 082c

DirBase: 2adb8000  ObjectTable: fffff8a002a87f90  HandleCount:  19.

    Image: cmd.exe

Programımızı çalıştıran işlemin "0xfffffa80010c1060" adresinde olduğunu öğrendik. Bu adreste "EPROCESS" yapısındaki nesnemiz bulunmakta ve işlem ile ilgili bilgiler bu nesnede tutulmaktadır.  Bu işlem nesnesindeki erişim bilgisi nesnesinin adresini tutan _EX_FAST_REF yapısına gözatalım:

1: kd>dt -b -v nt!_EX_FAST_REF fffffa80010c1060+0x208

struct _EX_FAST_REF, 3 elements, 0x8 bytes

   +0x000 Object           : 0xfffff8a0`0300f6c5

   +0x000 RefCnt           : Bitfield 0y0101

   +0x000 Value            : 0xfffff8a0`0300f6c5

_EX_FAST_REF yapısındaki değer "0xfffff8a0`0300f6c5" olduğuna göre erişim bilgisi nesnesinin adres değeri "0xfffff8a0`0300f6c0" olmalı. Bu adresteki erişim bilgisi nesnesinin ayrıcalık değerlerini inceleyelim:

1: kd>dt -v -b nt!_SEP_TOKEN_PRIVILEGES0xfffff8a0`0300f6c0+0x040

struct _SEP_TOKEN_PRIVILEGES, 3 elements, 0x18 bytes

   +0x000 Present          : 0x6`02880000

   +0x008 Enabled          : 0x800000

   +0x010 EnabledByDefault : 0x800000

Bu ayrıcalıkların karşılıklarını "ProcessExplorer" [3] programıyla daha net bir şekilde görebiliriz:

01.jpg 
Şekil - 1 Erişim bilgisi tahrif edilmemiş "cmd.exe" işleminin ayrıcalıkları

Peki bütün ayrıcalıklara sahip olmak istiyorsak? Yapmamız gereken şey sadece _SEP_TOKEN_PRIVILEGES yapısındaki "Present", "Enabled" ve "EnabledByDefault" alanlarını değiştirmek:

eq 0xfffff8a0`0300f6c0+0x040 0xffffffffffffffff

eq 0xfffff8a0`0300f6c0+0x048 0xffffffffffffffff

eq 0xfffff8a0`0300f6c0+0x050 0xffffffffffffffff

Son durum:

0: kd>dt -v -b nt!_SEP_TOKEN_PRIVILEGES0xfffff8a0`0300f6c0+0x040

struct _SEP_TOKEN_PRIVILEGES, 3 elements, 0x18 bytes

   +0x000 Present          : 0xffffffff`ffffffff

   +0x008 Enabled          : 0xffffffff`ffffffff

   +0x010 EnabledByDefault :0xffffffff`ffffffff

 

02.jpg 
Şekil - 2 Erişim bilgisi tahrif edilmiş "cmd.exe" işleminin ayrıcalıkları

Süper ayrıcalıklı uygulamanız emirlerinize hazır.

Farklı bir Kullanıcının Erişim Bilgisini Çalma

Erişim bilgisi nesneleri yanlızca bir işlem nesnesine bağlı olmak zorunda değildir. Bundan dolayı herhangi bir işlem nesnesinin _EX_FAST_REF değerini değiştirerek başka bir erişim bilgisi nesnesine yönlendirebiliriz. Bunun sonucunda normal bir kullanıcının kullanabileceği bir açıklığı kullanabilirseniz, yapmak istediğiniz işleri yapabilme hakkı olan bir kullanıcı hesabı şeçip, bu kullanıcı hesabıyla çalıştırılmış bir işlemin erişim bilgisi nesnesini paylaşabilirsiniz. Mesela her Windows işletim sisteminde olan "System" işleminin hesabını kullanarak yerel yönetici hesabından daha fazla hakka sahip de olabilirsiniz. Herhangi bir açıklığı kullanma ihtimalinin olmadığı bir durumda bu tür kernel  nesneleri üzerinde herhangi bir değişiklik yapabilmek için yönetici haklarına sahip olmanız gerekecektir. Bu tür bir durumda bile farklı bir kullanıcı hesabıyla çalışıyormuş gibi sistemi yanıltmak sistem tarafından tutulan kayıtları atlatmanızı sağlayacaktır.

Fakat diğer taraftan bu tekniğin kendine has bazı sorunları da bulunmaktadır.  Her nesne üzerinde onu kullanan ve referans veren işlemlerin sayısını tutan sayaçlar bulunmaktadır. Bir nesneyi kullanan veya referans veren bir işlem  kalmadığı takdirde nesne yöneticisi ilgili nesneyi hafızadan silmektedir. Bundan dolayı eğer bir erişim bilgisi nesnesini başka bir işleme bağlarsak ilgili erişim bilgisi nesnesinin sayaçlarının arttırılması gerekmektedir. Aksi takdirde erişim bilgisi nesnesinin gerçek sahibi olan işlem veya sonradan nesneyi kullanmaya başlayan işlemden herhangi biri kapatıldığında diğer işlemde devre dışı kalacaktır.

Bu tür sorunlarla uğraşmamak için, herhangi bir işlemle aynı erişim bilgisi nesnesini kullanmaktansa, taklit edilmek istenen erişim bilgisi nesnesinin "ZwDuplicateToken" fonksiyonuyla yeni bir kopyasını oluşturabiliriz. Bir sonraki aşamada da bu yeni oluşturulan nesnenin adresini istediğimiz bir işlemin _EX_FAST_REF değerine yazabiliriz [4].

Mesela yine normal kullanıcı haklarıyla çalıştırdığımız cmd.exe işlemimizi ele alalım. İlk çalıştırıldığında işlemimiz aşağıda gördüğünüz "User" ve "SID" haklarıyla çalışmaktadır.

03.jpg
Şekil - 3 Erişim bilgisi tahrif edilmemiş "cmd.exe" işleminin kullanıcı bilgileri

Amacımız PID'si 4 olan "System" işleminin erişim bilgisi nesnesinin bir kopyasını oluşturmak ve bu kopyayı yukarıdaki işlemimize bağlamak. Bunun için ilk önce kernel (çekirdek) hafızasında değişiklik yetkisi olan bir kernel  sürücüsü oluşturmalıyız. Halihazırda elimizde bir açıklık ve exploit olmadığını varsayarsak oluşturacağınız kernel sürücüsünü yüklemek için yerel yönetici haklarına sahip olmanız ve işletim sistemine bir çekirdek hata ayıklaycı bağlamanız gerekecektir. Sonuçta kernel sürücünüzü yükleyip çalıştırdığımızda aşağıdaki sonucu elde edeceğiz.

04.jpg
Şekil - 4 Erişim bilgisi tahrif edilmiş "cmd.exe" işleminin kullanıcı bilgileri 

Yukarıda da görüldüğü gibi yeni "User" ımız artık yerel sistem kullanıcısı. Bundan sonra "cmd.exe" işlemimizle yaptığımız her işlem bu kullanıcı haklarıyla çalıştırılacak  ve kayıtlarda da sadece "System" kullanıcısının ismi gözükecektir.

Kaynaklar:

[1]    Windows Internals 5th Edition

[2]    http://www.bilgiguvenligi.gov.tr/teknik-yazilar-kategorisi/64-bit-vista-kernel-hacking.html

[3]    http:// www.sysinternals.com

[4]    http://www.csababarta.com/downloads/Token stealing.pdf


Favori olarak ekle (0) | Görüntüleme sayısı: 9858

Yorumlar (3)
1. 29-11-2011 11:42
 
Maalesef bu yazının asıl yazım tarihi "3 Eylül 2010 Cuma", o yüzden haklısınız, şu anda uygulunan daha basit çözümler mevcut. Fakat illaki 0day bir çözüme ihtiyacınız yok, halihazırda 64bit kernel rootkitleri mevcut ve bu yöntemleri kullanmamaları için bir sebep yok.
 
Osman PAMUK
2. 28-11-2011 19:31
 
Teşekkürler. Sysinternals'da geçtiğimiz senelerde konuşulmuş bir konuydu lakin 0day bir kernel vulnerability bulamadıktan sonra etkisi olmayan bir durum. Ki kernel'e eriştikten sonra EPROCESS üzerinde çok daha etkili ve kısa yöntemler mevcut.
 
İbrahim Akgül
3. 23-11-2011 17:36
 
Elinize sağlık Osman bey. Önemli bir konuya daha değinmişsiniz.
 
Osman Murat ALKAÇ

Sadece kayıtlı kullanıcılar yorum yazabilir.
Lütfen sisteme giriş yapın veya kayıt olun.

 
spacer.png, 0 kB
spacer.png, 0 kB
Copyright 2017 TÜBİTAK-BİLGEM. Sitenin teknik altyapısında Joomla kullanılmıştır. Yazar ve site referans gösterilmeden alıntı yapılamaz. Görüşleriniz
spacer.png, 0 kB