작성자 : 김영민

분석 환경 Windows 10 19H1(18362.30) 64bit

취약점 요약 : ws2ifsl.sys 드라이버에서 발생한 UAF 취약점을 통한 로컬 권한 상승 취약점

취약점 개요

ws2ifsl.sys 는 프로세스와 소켓에 대한 기능이 구현되어있다. 내부적으로 만드는 오브젝트들에 대해서, 프로세스의 경우 편의를 위해서 procData 라고 부르고 소켓의 경우 sockData 라고 하자.

NtCreate 함수를 통해서 ws2ifsl 드라이버에 접근해서 프로세스의 핸들 또는 소켓의 핸들을 얻을 수 있다. 이때 프로세스 핸들을 얻기 위해서는 스레드의 핸들을 인자로 설정해야 하고, 소켓의 핸들을 얻기 위해서는 프로세스의 핸들을 인자로 설정해야 한다.

윈도우에 있는 모든 스레드들은 비동기를 처리하기 위해서 APC(Asynchronous procedure call) 큐를 가진다. 이는 스레드 핸들을 인자로 받아 생성되는 procData 또한 동일하다. 이때 procData 는 APC 와 관련된 작업을 indrect call 로 실행하며, 관련 함수 포인터를 가지고 있다.

NtWriteFile 과 같은 쓰기 함수의 인자로는 소켓 핸들을 넣어줄 수 있는데, 이 경우 작업이 SignalRequest 의 호출을 통해서 APC 큐에 들어가게 된다.

하지만 큐에 쌓여있는 APC 들이 실행되지 못하고 모종의 이유로 취소를 해야되는 상황이 발생할 수 있다. 이는 커널레벨과 유저레벨에서 모두 발생할 수 있는데, 유저레벨에서는 CloseHandle 함수를 호출하여 RequestRundownRoutine 를 호출하여, 이 일을 할 수 있다.

취약점은 이 때 발생하게 된다. APC 큐에 이미 해제된(freed) procData 가 참조된 작업이 있는 경우에도 루틴은 그대로 실행이 되어 RequestRundownRoutine 이 실행된다. 이 경우 procData 는 free 되어 더미값이 들어가있기 때문에, 추후 실행되는 커널의 보안검사에서 잘못된 링크로 인한 에러가 감지되어 블루스크린이 뜨게 돤다. 그러나 mideum 권한으로 실행된 경우 커널의 주소를 알아낼 수 있기 때문에, 버그체크 루틴을 우회하고 함수 포인터를 덮어서, 특정 함수를 실행할 수 있다.

익스플로잇 분석

windbg 를 통해서 커널 디버깅을 진행하였다. ws2ifsl 모듈에 bp를 걸기 위해서

sc stop ws2ifsl (vmware), sxe ld ws2ifsl(windbg), sc start ws2ifsl 을 통해서 모듈이 로드 될 때 멈추도록 하였다.

1. Socket 핸들과 Process 핸들 생성

https://github.com/bluefrostsecurity/CVE-2019-1215 에 코드가 공개되어있다.

아래 코드는 익스플로잇에서 핵심 부분인 TriggerBug 함수이다.

void TriggerBug(HANDLE threadHandle, DWORD64 writeAddress, DWORD64 kthreadAddress, int id)
{
	HANDLE procHandle = CreateProcessHandle(threadHandle); //프로세스 핸들
	printf("[!] procHandle %x\\n", (DWORD)procHandle);

	HANDLE sockHandle = CreateSocketHandle(procHandle); //소켓핸들
	printf("[!] sockHandle %x\\n", (DWORD)sockHandle);
...

먼저 프로세스 핸들과 소켓 핸들을 얻는다. 프로세스 핸들과 소켓 핸들을 얻는 방법은 비슷한데