Notice
Recent Posts
Recent Comments
Link
«   2024/04   »
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30
Tags
more
Archives
Today
Total
관리 메뉴

trash houz

[Linux Kernel] CSAW-CTF 2015 stringIPC 본문

Writeup

[Linux Kernel] CSAW-CTF 2015 stringIPC

applemasterz17 2019. 8. 5. 21:23

CSAW CTF 2015에서 출제된 stringIPC라는 Kernel Exploitation 문제이다. 

로드되어있는 모듈은 IPC를 통하여 통신할 수 있는 기능을 제공하며 새로운 IPC 채널을 생성, 찾기, 크기 변경 등이 가능하다.

각 채널은 생성 시 채널 ID 와 버퍼가 커널 메모리에 할당되고, 버퍼에 내용을 쓰거나 수정, 버퍼크기 변경 등이 가능하다. 

문제 출제시 소스코드를 제공했으므로 IDA로 분석하는 참극은 일어나지 않도록 하자.

https://github.com/mncoppola/StringIPC/blob/master/main.c

 

mncoppola/StringIPC

CSAW CTF 2015 Linux kernel exploitation challenge. Contribute to mncoppola/StringIPC development by creating an account on GitHub.

github.com

CSAW_ALLOC_CHANNEL

CSAW_OPEN_CHANNEL

CSAW_GROW_CHANNEL

CSAW_SHRINK_CHANNEL

CSAW_READ_CHANNEL

CSAW_WRITE_CHANNEL

CSAW_SEEK_CHANNEL

CSAW_CLOSE_CHANNEL

 

이러한 기능들이 있는데, 취약점은 GROW, SHRINK에서 터진다. 

일단 하나씩 알아보도록 하자. 

 

 

CSAW_ALLOC_CHANNEL

CSAW_ALLOC_CHANNEL

특별한 것은 없고 ipc 채널을 새로 생성해주는 동작을 한다. 

mutex를 사용해 lock, unlock 해주는 과정이 코드 전후반에 있지만, 문제에 큰 영향을 주지는 않는다. 

alloc_new_ipc_channel이라는 함수를 다시 호출해 실제 채널 생성을 하는데, 한번 살펴보자. 

 

alloc_new_ipc_channel()

채널 정보에 관한 구조체를 위한 공간을 kzalloc()으로 동적 할당하고, 

실제 data 를 담을 공간을 인자로 넘겨받은 buf_size 만큼 동적 할당한다. 

마지막으로 idr_alloc() 을 통해서 id 번호를 생성한다. 

 

 

CSAW_OPEN_CHANNEL

CSAW_OPEN_CHANNEL

이미 생성된 채널을 오픈하는 파트인데, 이 문제에서 별로 중요하진 않다. 

간단하니 넘어가도록 하겟당. 

 

 

CSAW_GROW_CHANNEL, CSAW_SHRINK_CHANNEL

CSAW_GROW_CHANNEL, CSAW_SHRINK_CHANNEL

이 부분에서 취약점이 터지게 된다. 

정확하게 말하면 이 파트에서 호출하는 realloc_ipc_channel에서 문제가 터진다. 

GROW는 말 그대로 늘려주는 애고, SHRINK는 줄여주는 애다. 

 

realloc_ipc_channel()

동작을 보면 일단 id로 채널 정보를 불러온 뒤에, grow 값이 있으면 size 만큼 늘리고 값이 없다면 줄여 버린다.

이런 과정들을 krealloc() 이 처리해주는데, 사용자가 입력한 값만큼 더해서 재 할당을 하고 기존 공간은 free  한 뒤에 

새로 할당된곳의 주소를 리턴해준다. 

만약 할당에 실패를 하면 기존 공간을 free 하지 않고 NULL을 리턴하게 된다. 

이 때문에 코드에서는 NULL로 에러 처리를 한 것 같은데, krealloc() 은 특정 조건으로 실패할 경우 NULL을 리턴하지 않는다.

 

krealloc() 함수

그렇다... 리턴 값이 무조건 NULL 이 아니라 ZERO_SIZE_PTR(16)을 리턴할 수도 있다. 

이렇게 되면 data의 주소를 16으로 바꿔 메모리를 읽어 온 뒤 comm을 찾아 cred를 바꾸는 짓이 가능해진다. 

위 내용에 관한 자세한 설명은 아래 링크를 참조해보도록 하자.

https://applemasterz17.tistory.com/222

 

 

'Writeup' 카테고리의 다른 글

[Linux Kernel] 0CTF 2018 FINAL BABY  (0) 2019.08.23
[Linux Kernel] CISCN 2017 babydriver  (0) 2019.08.20
[Linux Kernel] STARCTF 2019 hackme  (0) 2019.08.02