Off by one overflow

Reading time: 5 minutes

tip

AWS Hacking'i öğrenin ve pratik yapın:HackTricks Training AWS Red Team Expert (ARTE)
GCP Hacking'i öğrenin ve pratik yapın: HackTricks Training GCP Red Team Expert (GRTE)

HackTricks'i Destekleyin

Temel Bilgiler

Sadece 1B taşma erişimine sahip olmak, bir saldırganın bir sonraki parça için size alanını değiştirmesine olanak tanır. Bu, hangi parçaların gerçekten serbest bırakıldığını manipüle etmeyi sağlar ve potansiyel olarak başka bir geçerli parçayı içeren bir parça oluşturabilir. Sömürü, double free veya üst üste binen parçalarla benzerdir.

İki tür off by one zafiyeti vardır:

  • Keyfi byte: Bu tür, o byte'ı herhangi bir değerle yazmayı sağlar.
  • Null byte (off-by-null): Bu tür, o byte'ı yalnızca 0x00 ile yazmayı sağlar.
  • Bu zafiyetin yaygın bir örneği, strlen ve strcpy davranışlarının tutarsız olduğu aşağıdaki kodda görülebilir; bu, bir sonraki parçanın başında 0x00 byte'ı ayarlamaya olanak tanır.
  • Bu, House of Einherjar ile sömürülebilir.
  • Tcache kullanılıyorsa, bu bir double free durumuna dönüştürülebilir.
Off-by-null
c
// From https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/off_by_one/
int main(void)
{
char buffer[40]="";
void *chunk1;
chunk1 = malloc(24);
puts("Get Input");
gets(buffer);
if(strlen(buffer)==24)
{
strcpy(chunk1,buffer);
}
return 0;
}

Diğer kontrollerin yanı sıra, artık bir parça serbest bırakıldığında, önceki boyut, meta verilerin parçasında yapılandırılan boyutla karşılaştırılmaktadır; bu da bu saldırıyı 2.28 sürümünden itibaren oldukça karmaşık hale getirmektedir.

Kod örneği:

Amaç

  • Bir parçanın başka bir parçanın içinde yer almasını sağlamak, böylece o ikinci parça üzerindeki yazma erişimi, içeridekini geçersiz kılmayı sağlar.

Gereksinimler

  • Boyut meta verisi bilgisini değiştirmek için off by one overflow.

Genel off-by-one saldırısı

  • Üç parça A, B ve C (örneğin boyut 0x20) ayırın ve üst parça ile birleştirmeyi önlemek için başka bir parça ayırın.
  • C parçasını serbest bırakın (0x20 Tcache serbest listeye eklenmiştir).
  • A parçasını B üzerinde taşmak için kullanın. Off-by-one'ı kötüye kullanarak B'nin size alanını 0x21'den 0x41'e değiştirin.
  • Artık B, serbest parça C'yi içermektedir.
  • B'yi serbest bırakın ve 0x40 boyutunda bir parça ayırın (buraya tekrar yerleştirilecektir).
  • Hala serbest olan C'nin fd işaretçisini değiştirebiliriz (Tcache zehirlenmesi).

Off-by-null saldırısı

  • 3 bellek parçası (a, b, c) ardışık olarak ayrılır. Ardından ortadaki parça serbest bırakılır. İlk parça bir off by one overflow açığı içerir ve saldırgan bunu 0x00 ile kötüye kullanır (önceki byte 0x10 olsaydı, ortadaki parça gerçekte olduğundan 0x10 daha küçük olduğunu gösterirdi).
  • Ardından, ortada serbest bırakılan parçaya (b) 2 tane daha küçük parça ayrılır, ancak b + b->size asla c parçasını güncellemez çünkü işaret edilen adres olması gerekenin altındadır.
  • Ardından, b1 ve c serbest bırakılır. c - c->prev_size hala b'ye (şimdi b1) işaret ettiğinden, her ikisi de tek bir parçada birleştirilir. Ancak, b2 hala b1 ve c arasında kalır.
  • Son olarak, bu bellek alanını geri almak için yeni bir malloc gerçekleştirilir; bu alan aslında b2'yi içerecek ve yeni malloc'un sahibi b2'nin içeriğini kontrol edebilecektir.

Bu resim saldırıyı mükemmel bir şekilde açıklamaktadır:

https://heap-exploitation.dhavalkapil.com/attacks/shrinking_free_chunks

Diğer Örnekler ve Referanslar

  • https://heap-exploitation.dhavalkapil.com/attacks/shrinking_free_chunks
  • Bon-nie-appetit. HTB Cyber Apocalypse CTF 2022
  • strlen'in bir sonraki parçanın size alanını dikkate alması nedeniyle off-by-one.
  • Tcache kullanılıyor, bu nedenle genel bir off-by-one saldırısı, Tcache zehirlenmesi ile keyfi yazma ilkesini elde etmek için çalışır.
  • Asis CTF 2016 b00ks
  • Off by one'ı, bir adresi heap'ten sızdırmak için kötüye kullanmak mümkündür çünkü bir dizeyi geçersiz kılarken sonundaki 0x00 byte'ı bir sonraki alan tarafından geçersiz kılınır.
  • Keyfi yazma, işaretçiyi başka bir yere işaret edecek şekilde off by one yazmayı kötüye kullanarak elde edilir; burada sahte işaretçilerle sahte bir yapı oluşturulacaktır. Ardından, bu yapının işaretçisini takip ederek keyfi yazma elde etmek mümkündür.
  • libc adresi sızdırılır çünkü heap mmap kullanılarak genişletildiğinde, mmap tarafından tahsis edilen bellek libc'den sabit bir ofsetle gelir.
  • Son olarak, keyfi yazma, __free_hook adresine bir gadget ile yazmak için kötüye kullanılır.
  • plaidctf 2015 plaiddb
  • Kullanıcı girişi satırlarını okuyan getline fonksiyonunda bir NULL off by one açığı vardır. Bu fonksiyon, içeriğin "anahtarını" okumak için kullanılır, içeriği değil.
  • Yazımda 5 başlangıç parçası oluşturulur:
  • chunk1 (0x200)
  • chunk2 (0x50)
  • chunk5 (0x68)
  • chunk3 (0x1f8)
  • chunk4 (0xf0)
  • üst parça ile birleştirmeyi önlemek için parça savunması (0x400)
  • Ardından parça 1, 5 ve 3 serbest bırakılır, böylece:

[ 0x200 Chunk 1 (free) ] [ 0x50 Chunk 2 ] [ 0x68 Chunk 5 (free) ] [ 0x1f8 Chunk 3 (free) ] [ 0xf0 Chunk 4 ] [ 0x400 Chunk defense ]

- Ardından, chunk3 (0x1f8) kötüye kullanılarak null off-by-one, `prev_size`'i `0x4e0` olarak yazmak için kötüye kullanılır.
- Başlangıçta tahsis edilen chunk1, 2, 5 ve 3'ün boyutlarının yanı sıra bu parçaların 4 başlıklarının toplamının `0x4e0`'a eşit olduğunu not edin: `hex(0x1f8 + 0x10 + 0x68 + 0x10 + 0x50 + 0x10 + 0x200) = 0x4e0`
- Ardından, parça 4 serbest bırakılır ve başlangıca kadar tüm parçaları tüketen bir parça oluşturur:
- ```python
[ 0x4e0 Chunk 1-2-5-3 (free) ] [ 0xf0 Chunk 4 (corrupted) ] [ 0x400 Chunk defense ]

[ 0x200 Chunk 1 (free) ] [ 0x50 Chunk 2 ] [ 0x68 Chunk 5 (free) ] [ 0x1f8 Chunk 3 (free) ] [ 0xf0 Chunk 4 ] [ 0x400 Chunk defense ]