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 지원하기
- 구독 계획 확인하기!
- **💬 디스코드 그룹 또는 텔레그램 그룹에 참여하거나 트위터 🐦 @hacktricks_live를 팔로우하세요.
- HackTricks 및 HackTricks Cloud 깃허브 리포지토리에 PR을 제출하여 해킹 트릭을 공유하세요.
Basic Information
1B 오버플로우에 접근하면 공격자는 다음 청크의 size
필드를 수정할 수 있습니다. 이는 실제로 해제된 청크를 조작할 수 있게 하여, 다른 유효한 청크를 포함하는 청크를 생성할 수 있습니다. 이 공격은 double free 또는 겹치는 청크와 유사합니다.
오프 바이 원 취약점에는 두 가지 유형이 있습니다:
- 임의 바이트: 이 유형은 해당 바이트를 임의의 값으로 덮어쓸 수 있습니다.
- 널 바이트 (off-by-null): 이 유형은 해당 바이트를 0x00으로만 덮어쓸 수 있습니다.
- 이 취약점의 일반적인 예는 다음 코드에서 볼 수 있으며,
strlen
과strcpy
의 동작이 일관되지 않아 다음 청크의 시작 부분에 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 버전부터 상당히 복잡해졌습니다.
코드 예제:
- https://github.com/DhavalKapil/heap-exploitation/blob/d778318b6a14edad18b20421f5a06fa1a6e6920e/assets/files/shrinking_free_chunks.c
- 이 공격은 Tcaches의 사용으로 인해 더 이상 작동하지 않습니다.
- 게다가, 더 큰 청크를 사용하여 이를 남용하려고 하면 (따라서 tcaches가 관련되지 않음) 다음과 같은 오류가 발생합니다:
malloc(): invalid next size (unsorted)
목표
- 하나의 청크가 다른 청크 안에 포함되도록 하여 두 번째 청크에 대한 쓰기 접근이 포함된 청크를 덮어쓸 수 있도록 합니다.
요구 사항
- 크기 메타데이터 정보를 수정하기 위한 off by one overflow
일반적인 off-by-one 공격
- 세 개의 청크
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 중독).
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
- 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 ]