개요
Kernel address space layout randomization (KASLR)은 커널 포인터를 부트 시간에 랜덤한 위치에 두도록 하여서 공격자가 정확한 커널 포인터의 위치를 알 수 없도록 하는 기법이다. 이 기법은 커널 메모리 공격을 방어하기 위해서 등장하였으며, 현재 OS 보안 기법중 중요한 한 부분으로 작동하고 있다. KASLR이 작동하는 커널은 공격자가 Offset의 정확한 내용을 추론해내기 전까지 Buffer overflow, use-after-free와 같은 메모리 공격에서 어떠한 부분을 공격할지 모호하게 함으로서, 작동한다. 그러나 만약 이러한 Offset이 Side channel attack과 같은 방식으로 leak될 경우 공격자는 커널 포인터에 Offset을 뺌으로서 커널의 주소를 추론할 수 있기 때문에, 커널의 포인터를 허용되지 않은 User에게 Leak되는 것은 위험한 공격 포인트가 될 수 있다.
KASLR이 정말 강력한 방법이기 때문에 Return-oriented programming처럼 여러 커널 Attack을 할때, KASLR을 공격하는 것이 첫번째 Attack point가 되는 경우가 많다. 이처람 KASLR은 실용적이며, 구현하기 간단하고, 강력한 운영체제 보안의 방법이기 때문에, 대부분의 운영체제는 KASLR를 채택하고 있다.
리눅스에서 KASLR은 기본으로 켜져있으며 끄고 싶은 경우에는 커널 Argument로 nokaslr를 넣어주면 된다.
구현
KASLR의 Entry를 계산할때는, 커널 텍스트 섹션이 움직일 수 있는 최대 크기와, 커널 텍스트 섹션의 정렬(Align)으로 결정된다. 예를 들어서, 리눅스 커널과 같은 경우 커널은 1GB안에서 움직여야 하며, Align은 16mb라서 총 64개의 Entry가 있다. 이를 통해서 커널의 base address는 다음과 같이 정해진다.
base_address + s * align_size(16mb): 0 <= s < 64
Attack
- Cache-based timing channel
커널 포인터는 캐슁될 수 밖에 없는데, 캐쉬에 힛이 나는지 아니면 힛이 안나는지에 대한 timing정보를 바탕으로, 메모리가 mapped되어 있는지 아니면 unmapped되어 있는지를 파악할 수 있다. 이를 통해서 커널의 메모리 구조를 탈취할 수 있다. 그러나 이러한 cache-based timing attack은 명확한 공격 징후 - 즉 많은 시스템콜 호출과 page fault - 를 이용하기 때문에, 쉽게 공격의 징후를 탐지 할 수 있기도 한다.