
CVE-2014-0038용 Linux 로컬 루트 익스플로잇
X86_X32 recvmmsg 시스템 콜은 사용자 공간에서 전달된 타임아웃 포인터를 제대로 검사하지 않습니다.
recvmmsg의 타임아웃으로 커널 주소에 대한 포인터를 전달하세요, 그 주소의 원래 바이트를 알고 있다면 알려진 데이터로 덮어쓸 수 있습니다. 최하위 바이트가 0xff이면, 255초를 기다리면 0x00으로 바뀝니다.
전달된 주소의 첫 번째 long(tv_sec)은 양수여야 하며 두 번째 long(tv_nsec)은 1000000000보다 작아야 합니다.
초기화되지 않은(따라서 쓰기 가능한) 커널 메모리에 있는 ptmx_fops 구조체의 release 함수 포인터를 대상으로 합니다. 최상위 세 바이트를 0으로 만들어 사용자 공간에 매핑 가능한 주소를 가리키는 포인터로 변환합니다. release 포인터는 그 뒤에 16개의 0x00 바이트가 이어지므로(따라서 tv_nsec가 유효합니다) 사용됩니다. /dev/ptmx를 열고 닫기만 하면 됩니다.
그다지 깔끔하지는 않지만 심볼을 해석할 수 있다면 상당히 신뢰할 만할 것입니다.
Ubuntu 13.10에서 테스트함
참고: http://blog.includesecurity.com/2014/03/exploit-CVE-2014-0038-x32-recvmmsg-kernel-vulnerablity.html
/proc/kallsyms에서 주소를 가져와 익스플로잇을 실행하세요:
./build.sh && ./timeoutpwn
원격 서버용 바이너리를 빌드하려면 다음을 시도하세요:
ssh user@host 'cat /proc/kallsyms' > syms.txt
CFLAGS=-static ./build.sh syms.txt
scp timeoutpwn user@host:
...
kallsyms에서 ptmx_fops를 찾을 수 없으면, 헤더 패키지(Arch Linux의 linux-headers)와 함께 제공되는 vmlinux에서
추출해 보세요:
nm /lib/modules/$(uname -r)/build/vmlinux > syms.txt