힙 오버플로

힙 오버플로()는 힙 데이터 영역에서 발생하는 버퍼 오버플로의 한 종류이다. 힙 오버플로는 스택 기반 오버플로와는 다른 방식으로 익스플로잇 가능하다. 힙에서의 메모리는 런타임 시에 애플리케이션에 의해 동적으로 할당되며 일반적으로 프로그램 데이터를 포함한다. 익스플로잇은 애플리케이션이 링크드 리스트 포인터 같은 내부 구조체를 겹쳐쓰는 것 같이 이 데이터를 특정한 방식으로 오염시킴으로써 수행된다. 고전적인 힙 오버플로 기법은 동적 메모리 할당 연결(malloc 메타 데이터 같은)을 겹쳐쓰고 프로그램 함수 포인터를 겹쳐쓰기 위해 결과로 나온 포인터를 교환하는 기법이다.

옛날 버전의 리눅스에서의 전형적인 예시는 힙에서 두 버퍼가 각각 나란히 할당되고, 첫 번째 버퍼의 경계 외부에 쓰는 것이 두 번째 버퍼의 메타 데이터를 겹쳐쓰게되는 것이다. 두 번째 버퍼의 사용 비트를 0으로 설정하고 널 바이트들이 복사되게 하기 위해 작은 음수 값을 길이로 설정한 후에, 첫 번째 버퍼에서 프로그램이 free() 함수를 호출할 때 프로그램은 이 두 버퍼를 단일 버퍼로 통합하려는 시도를 할 것이다. 이 상황이 벌어지면 free될 버퍼는 이전에 할당된 버퍼의 첫 8 바이트에 포워드와 백이라는 두 포인터를 갖게 된다.

결과 
우연한 오버플로는 영향을 받은 메모리 영역을 사용하는 프로세스들에서 데이터 오염이나 예상치 못한 행위를 야기한다. 메모리 보호가 없는 운영 체제에서 이것은 시스템의 어느 프로세스라도 가능하다

의도적인 익스플로잇은 데이터가 특정한 영역에서 임의적인 방식으로 바뀌거나 임의적인 코드를 실행되게 하는 것을 야기한다.

예를 들면 마이크로소프트 JPEG GDI+ 버퍼 오버플로 취약점은 감염된 머신에서 코드의 원격 실행을 허용한다.

iOS 탈옥은 임의 코드 실행을 위해 종종 힙 오버플로를 사용하는데 이것은 보통 커널을 탈옥한 것으로 교체하기 위해 커널 익스플로잇을 위한 것이다.

탐지와 방어 
힙 오버플로를 방어하는 방식으로 세 종류가 있다. 여러 현대 운영 체제들은 세가지 모두의 구현 중 일부를 제공한다.
 일반적으로 NX 비트 같은 하드웨어 특징들을 통해 코드와 데이터를 분리함으로써 페이로드의 실행을 막는다
 힙이 고정된 오프셋에서 발견되지 못하게 난수화를 도입한다
 힙 매니저에 대한 분별력 있는 검사를 도입한다.
GNU libc는 2.3.6 버전부터 unlink를 호출할 때 포인터의 일관성을 검사하는 것 같이 힙 오버플로를 탐지하는 방어가 포함되었다. 그러나 이러한 방어들은 거의 즉시 공격 가능하다고 밝혀졌다. 추가적으로 리눅스는 (비록 PaX가 몇 년 전에 더 나은 구현을 도입하였지만) 2005년 이후부터는 ASLR을 포함하였다. 또한 리눅스는 2004년부터는 NX 비트의 지원을 포함하였다.

마이크로소프트는 2003년부터 힙에 기반한 버퍼 오버플로에 대한 방어를 포함하였다. 이러한 완화는 안전한 링크해제와 힙 엔트리 헤더 쿠키가 있다. 윈도우의 최근 버전들은 일반적으로 대상이 되는 데이터 구조체들의 제거, 힙 엔트리 메타데이터 난수화, 함수 포인터 인코딩, 힙 오염의 종료 그리고 알고리즘 변이를 포함한다. 일반 데이터 실행 방어(DEP)와 ASLR 도 또한 이 공격을 완화시키는데 도움을 준다.

같이 보기 
 힙 스프레이
 버퍼 오버플로
 스택 오버플로
 스택 버퍼 오버플로
 취약점 공격
 셸코드

각주

외부 링크 
 Smashing The Heap For Fun And Profit
 Heap Overflow article at Heise Security
 Defeating Microsoft Windows XP SP2 Heap protection and DEP bypass

취약점 공격