본문 바로가기

Data

[고전 커널 취약점]Linux Kernel 2.4/2.6 sock_sendpage() ring0 local root exploit (very simple)

이번에 설명할 exploit은 한번찾고 발표를 안해서 해커들이 꽤 오랜시간동안 우려먹었다고 전해지는(전문) 취약점입니다.

작성시 참고한곳  http://www.exploit-db.com/exploits/9479/ (simple ver)

http://www.exploit-db.com/exploits/9545/ (one shot)

일단 첫번째 링크는 gogossing이 있는걸로 보아 한국분 글이구요

(아이넷캅의 ㅇㄷㅇ님이란 전문을 들었습니다.)


주석에 보신바대로 100%성공하지 않기때문에 goto문을 활용해 uid가 0이 아닌경우 계속해서 공격을 시도하는 코드입니다.

그리고 두번째글은 32비트, 64비트 PowerPc, 스레드(?)등 다양한 환경울 고려해서 만들은 원샷 코드입니다.

마지막으로 제가 작성한건 fedora core 9를 기준으로 작동을 확인한 간단한 원샷코드입니다.

위 두 링크의 익스플로잇의 개념은 모두 같으며 비슷한 구조의 페이로드를 가졌습니다. 저는 여기서 동작에 필요없는 부분을 전부 날린상태이구요.


원래의 코드 구조는 passket님이 즉석에서 작성한 것을 베이스로 전체적으로 심플버전링크와 원샷링크를 비교해가며 코드를 줄여 나갔습니다.


간략하게 만든 exploit을 설명하자면, 코드에선 sendfile의 내부루틴인 sock_sendpage에서 널 포인터 디레퍼런스를 하게되서(dmesg 로 확인가능) 0x00000000에 권한을 주고 코드를 삽입하는 전형적인 과정이후 커널의 ring0 모드를 유지한채

task_struct( process control block )에 저장된 uid와 gid등을 찾아 0으로 설정하고 ring 3으로 돌아간후 execl 해주는 코드입니다.

pcb 구조체의 uid, gid를 찾는 부분의 해설을 하자면

아래와같이 커널스택 시작부분부터 찾기위해 esp를 옮겨주고

페도라 9에선 왠지 4k단위로 할당이 되있다해서 ~4096과 주소를 and연산을 해서 하위비트를 날림으로써

커널스택의 시작주소로 마스킹을 하는 모습을 보실 수 있습니다. 그후 4씩 증가하면서 원래의 uid, gid들과 비교를 하게되죠.

여러차례 삽질경과 이전소스(혹은 simple ver)는 마스킹 과정에서 8k단위라 가정하고 8196과 and 연산을 하기때문에 정확한 시작주소에서부터 pcb를 찾지못해서 간혹 exploit이 실패함을 알수 있었습니다.

따라서 위와 같이 마스킹을 하고 찾으면 원샷에 성공함을 알 수 있습니다. 하지만 아래와 같이 그냥 tmp변수가 할당된 영역을 넣고 찾아도 적어도 제환경(fedora 9)에선 pcb찾는데 이상없이 원샷으로 동작하니 저렇게 줄인겁니다.


+)두번째링크인 범용원샷코드를 자세히 이해하실려면 아래 ppt를 참고하시면 도움이 됩니다.

http://www.cs.columbia.edu/~nahum/w4118/lectures/Processes.ppt


음 아래는 최종 코드에 주석을 달아보았습니다. 편의상 작성시 썼던 주석은 유지하겠습니다.




헌데 요샌 널디레 생겨도 커널에서 아예 할당을 막아버린답니다. -_-

ps : 윈도우는 여전히 널페이지를 할당하는 꼼수가 존재하니 아래링크를 참고하시길

http://bananapayload.org/entry/널-페이지-할당과-버그-클래스

http://jz.pe.kr/63