Off by one overflow

Reading time: 5 minutes

tip

AWS 해킹 배우기 및 연습하기:HackTricks Training AWS Red Team Expert (ARTE)
GCP 해킹 배우기 및 연습하기: HackTricks Training GCP Red Team Expert (GRTE)

HackTricks 지원하기

Basic Information

1B 오버플로우에 접근하면 공격자는 다음 청크의 size 필드를 수정할 수 있습니다. 이는 실제로 해제된 청크를 조작할 수 있게 하여, 다른 유효한 청크를 포함하는 청크를 생성할 수 있습니다. 이 공격은 double free 또는 겹치는 청크와 유사합니다.

오프 바이 원 취약점에는 두 가지 유형이 있습니다:

  • 임의 바이트: 이 유형은 해당 바이트를 임의의 값으로 덮어쓸 수 있습니다.
  • 널 바이트 (off-by-null): 이 유형은 해당 바이트를 0x00으로만 덮어쓸 수 있습니다.
  • 이 취약점의 일반적인 예는 다음 코드에서 볼 수 있으며, strlenstrcpy의 동작이 일관되지 않아 다음 청크의 시작 부분에 0x00 바이트를 설정할 수 있습니다.
  • 이는 House of Einherjar로 악용될 수 있습니다.
  • Tcache를 사용하는 경우, 이는 double free 상황으로 활용될 수 있습니다.
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;
}

다른 검사들 중에서, 이제 청크가 해제될 때마다 이전 크기가 메타데이터의 청크에 설정된 크기와 비교되므로 이 공격은 2.28 버전부터 상당히 복잡해졌습니다.

코드 예제:

목표

  • 하나의 청크가 다른 청크 안에 포함되도록 하여 두 번째 청크에 대한 쓰기 접근이 포함된 청크를 덮어쓸 수 있도록 합니다.

요구 사항

  • 크기 메타데이터 정보를 수정하기 위한 off by one overflow

일반적인 off-by-one 공격

  • 세 개의 청크 A, BC (크기 0x20이라고 가정)를 할당하고, 상단 청크와의 통합을 방지하기 위해 또 다른 하나를 할당합니다.
  • C를 해제합니다 (0x20 Tcache free-list에 삽입됨).
  • 청크 A를 사용하여 B를 오버플로우합니다. off-by-one을 남용하여 Bsize 필드를 0x21에서 0x41로 수정합니다.
  • 이제 B가 해제된 청크 C를 포함하고 있습니다.
  • B를 해제하고 0x40 청크를 할당합니다 (여기 다시 배치됩니다).
  • 여전히 해제된 Cfd 포인터를 수정할 수 있습니다 (Tcache 중독).

Off-by-null 공격

  • 메모리의 3개 청크 (a, b, c)가 차례로 예약됩니다. 그런 다음 중간 청크가 해제됩니다. 첫 번째 청크는 off by one overflow 취약점을 포함하고 있으며 공격자는 0x00을 사용하여 이를 남용합니다 (이전 바이트가 0x10이면 중간 청크가 실제보다 0x10 작다고 표시하게 됩니다).
  • 그런 다음, 중간에 해제된 청크 (b)에 두 개의 더 작은 청크가 할당되지만, b + b->size는 포인터 주소가 있어야 할 것보다 작기 때문에 청크 c를 업데이트하지 않습니다.
  • 그런 다음, b1과 c가 해제됩니다. c - c->prev_size가 여전히 b (현재 b1)를 가리키므로 두 개가 하나의 청크로 통합됩니다. 그러나 b2는 여전히 b1과 c 사이에 있습니다.
  • 마지막으로, 이 메모리 영역을 재사용하는 새로운 malloc이 수행되며, 실제로 b2를 포함하게 되어 새로운 malloc의 소유자가 b2의 내용을 제어할 수 있게 됩니다.

이 이미지는 공격을 완벽하게 설명합니다:

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

기타 예제 및 참조

  • https://heap-exploitation.dhavalkapil.com/attacks/shrinking_free_chunks
  • Bon-nie-appetit. HTB Cyber Apocalypse CTF 2022
  • strlen이 다음 청크의 size 필드를 고려하기 때문에 off-by-one입니다.
  • Tcache가 사용되고 있으므로 일반적인 off-by-one 공격이 Tcache 중독을 통해 임의 쓰기 원시를 얻는 데 작동합니다.
  • Asis CTF 2016 b00ks
  • off by one을 남용하여 힙에서 주소를 유출할 수 있습니다. 왜냐하면 문자열의 끝에 있는 바이트 0x00이 다음 필드에 의해 덮어쓰여지기 때문입니다.
  • 임의 쓰기는 off by one 쓰기를 남용하여 포인터가 가짜 구조체와 가짜 포인터가 구축될 다른 위치를 가리키도록 하여 얻습니다. 그런 다음 이 구조체의 포인터를 따라가 임의 쓰기를 얻을 수 있습니다.
  • libc 주소가 유출되는 이유는 힙이 mmap을 사용하여 확장될 때 mmap에 의해 할당된 메모리가 libc로부터 고정 오프셋을 가지기 때문입니다.
  • 마지막으로, 임의 쓰기를 남용하여 __free_hook의 주소에 one gadget을 씁니다.
  • plaidctf 2015 plaiddb
  • 사용자 입력 줄을 읽는 getline 함수에 NULL off by one 취약점이 있습니다. 이 함수는 콘텐츠의 "키"를 읽는 데 사용되며 콘텐츠는 읽지 않습니다.
  • 작성물에서 5개의 초기 청크가 생성됩니다:
  • chunk1 (0x200)
  • chunk2 (0x50)
  • chunk5 (0x68)
  • chunk3 (0x1f8)
  • chunk4 (0xf0)
  • 상단 청크와의 통합을 피하기 위한 청크 방어 (0x400)
  • 그런 다음 청크 1, 5 및 3이 해제되므로:

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

- 그런 다음 청크3 (0x1f8)을 남용하여 null off-by-one을 남용하여 `prev_size`를 `0x4e0`으로 씁니다.
- 초기 할당된 청크1, 2, 5 및 3의 크기와 그 청크의 헤더 4개가 `0x4e0`과 같다는 점에 유의하십시오: `hex(0x1f8 + 0x10 + 0x68 + 0x10 + 0x50 + 0x10 + 0x200) = 0x4e0`
- 그런 다음 청크 4가 해제되어 시작까지 모든 청크를 소비하는 청크가 생성됩니다:
- ```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 ]