Off by one overflow
Last updated
Last updated
Learn & practice AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE) Learn & practice GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
1B 오버플로우에 대한 접근만으로 공격자는 다음 청크의 size
필드를 수정할 수 있습니다. 이는 실제로 해제된 청크를 조작할 수 있게 하여, 다른 유효한 청크를 포함하는 청크를 생성할 수 있습니다. 이 공격은 double free 또는 겹치는 청크와 유사합니다.
오프 바이 원 취약점에는 두 가지 유형이 있습니다:
임의 바이트: 이 유형은 해당 바이트를 임의의 값으로 덮어쓸 수 있습니다.
널 바이트 (off-by-null): 이 유형은 해당 바이트를 0x00으로만 덮어쓸 수 있습니다.
이 취약점의 일반적인 예는 strlen
과 strcpy
의 동작이 일관되지 않아 다음 청크의 시작 부분에 0x00 바이트를 설정할 수 있는 다음 코드에서 볼 수 있습니다.
이는 House of Einherjar로 악용될 수 있습니다.
Tcache를 사용하는 경우, 이는 double free 상황으로 활용될 수 있습니다.
다른 검사들 중에서, 이제 청크가 해제될 때마다 이전 크기가 메타데이터의 청크에 설정된 크기와 비교되므로 이 공격은 2.28 버전부터 상당히 복잡해졌습니다.
이 공격은 Tcaches의 사용으로 인해 더 이상 작동하지 않습니다.
게다가, 더 큰 청크를 사용하여 이를 악용하려고 하면 (따라서 tcaches가 관련되지 않음) 다음과 같은 오류가 발생합니다: malloc(): invalid next size (unsorted)
한 청크가 다른 청크 안에 포함되도록 하여 두 번째 청크에 대한 쓰기 접근이 포함된 청크를 덮어쓸 수 있도록 합니다.
크기 메타데이터 정보를 수정하기 위한 off by one overflow
세 개의 청크 A
, B
및 C
(크기 0x20이라고 가정)를 할당하고, 상단 청크와의 통합을 방지하기 위해 또 다른 하나를 할당합니다.
C
를 해제합니다 (0x20 Tcache free-list에 삽입됨).
청크 A
를 사용하여 B
를 오버플로우합니다. off-by-one을 악용하여 B
의 size
필드를 0x21에서 0x41로 수정합니다.
이제 B
는 해제된 청크 C
를 포함하고 있습니다.
B
를 해제하고 0x40 청크를 할당합니다 (여기 다시 배치됩니다).
여전히 해제된 C
의 fd
포인터를 수정할 수 있습니다 (Tcache 중독).
메모리의 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의 내용을 제어할 수 있게 됩니다.
이 이미지는 공격을 완벽하게 설명합니다:
strlen
이 다음 청크의 size
필드를 고려하기 때문에 off-by-one입니다.
Tcache가 사용되고 있으므로 일반적인 off-by-one 공격이 Tcache 중독을 통해 임의 쓰기 원시를 얻는 데 작동합니다.
off by one을 악용하여 힙에서 주소를 유출할 수 있습니다. 왜냐하면 문자열의 끝에 있는 바이트 0x00이 다음 필드에 의해 덮어쓰여지기 때문입니다.
임의 쓰기는 off by one 쓰기를 악용하여 포인터가 가짜 포인터가 있는 다른 위치를 가리키도록 만들어 얻습니다. 그런 다음 이 구조체의 포인터를 따라가 임의 쓰기를 얻을 수 있습니다.
libc 주소가 유출되는 이유는 힙이 mmap을 사용하여 확장될 경우 mmap에 의해 할당된 메모리가 libc로부터 고정 오프셋을 가지기 때문입니다.
마지막으로, 임의 쓰기를 악용하여 __free_hook
의 주소에 one gadget을 씁니다.
사용자 입력 줄을 읽는 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 ]
[ 0x200 Chunk 1 (free) ] [ 0x50 Chunk 2 ] [ 0x68 Chunk 5 (free) ] [ 0x1f8 Chunk 3 (free) ] [ 0xf0 Chunk 4 ] [ 0x400 Chunk defense ]