OS 개발에서의 보안 기법

OS 개발에서의 보안 기법

개요

우린 지금까지 드림핵, CTF 에서 응용 프로그램에 대한 보안을 깊게 다뤄왔습니다.

이번 블로그에서는 응용 프로그램보다 더 아랫단계인 운영체제의 보안 기법중 하나인 Paging guard 기법을 알아보겠습니다.

페이징

페이징은 물리메모리를 특정 크기로 쪼개서 가상 메모리를 지정하는 방식을 말합니다.

이 사진에서 현재 프로세스가 A 라고 가정하면 1번지 메모리를 접근할 때 실제로는 물리주소의 2번을 접근하게 됩니다.

하지만 프로세스가 아닌 운영체제 레벨에서는 접근 주소와 실제 물리주소는 같다고 가정합시다.

스택 오버플로우

운영체제에서도 스택이라는 개념이 있는데 프로세스와 비슷하게 grow-down 입니다.

여기서 운영체제가 실행되는 주소가 2MB 고, 스택의 시작 주소는 3MB 라 가정합시다.

그런데 만약 스택에서 2MB 짜리의 데이터를 할당한다면?

데이터를 쓸 수 있는 주소가 커널 코드를 넘어서기 때문에 커널 코드를 오염시켜 해킹의 가능성이 매우 커지게 됩니다.

가드 페이지

이런 스택 오버플로우를 막기 위한 기법이 가드 페이지 입니다.

페이징은 특정 블록에 대해서 권한을 설정할 수 있습니다.

이를 이용할 겁니다.

위 사진에서 가상주소와 물리주소는 같습니다.

저러한 구조에서는 스택에서 8MB 를 할당하여 커널 코드를 임의로 조작하려 할 때 스택은 필연적으로 저 접근금지 영역을 건드리게 됩니다.

이를 CPU 에서 감지하면 예외를 터트리게 되고 OS 는 강제종료 됩니다.

카나리 기법과는 달리, 데이터 변경 여부에 상관없이 오류가 터지기 때문에 더욱 강력한 기법입니다.

우회?

카나리와 달리 가드 페이징은 우회 방법이 매우 제한적입니다.

한가지를 꼽자면, CPU 에서 페이징을 쓸때 페이징에 대한 정보를 기록하는 자료구조가 메모리에 있는데 이를 조작할 수 있다면 됩니다.

만약 여기서 페이징에 대한 정보가 스택 영역에 있다면 가드 페이징 상관없이 저 메모리 영역에 대한 권한 자체를 임의로 변경할 수 있습니다.

하지만 페이징 파일을 비롯한 OS 의 중요 파일들을 전부 저 커널 영역에 배치한다면 접근 금지 영역으로 인해 스택 오버플로우로는 일반적인 상황에서 해킹이 거의 불가능하게 됩니다.

하이퍼바이저 인젝션 외에는 하드웨어의 결함을 이용하는 방법밖에 없습니다.

응용 프로그램에서는...

이론상 버퍼 오버플로우를 방지하기 위해 카나리 대신 가드 페이징을 쓰면 완벽할 것으로 보입니다.

하지만 페이징은 최소 4KB 의 블럭 크기를 사용하여 메모리 낭비가 매우 심해지기 때문에 현실적으로는 어렵습니다.

리턴 어드레스를 저장하는 스택 따로, 변수 스택따로 배치한다면 가능성이 있습니다.