메모리 보안

위키백과, 우리 모두의 백과사전.

메모리 보안(Memory safety)은 소프트웨어 개발에서 고려하는 것으로서, 버퍼 오버플로허상 포인터 같은 (RAM 접근을 다루는) 보안 취약점을 유발시킬 수 있는 소프트웨어 버그들을 회피할 목적으로 이루어진다.

포인터 연산, 캐스팅 그리고 할당 해제를 지원하는 C나 C++ 같은 언어들은 전형적으로 안전한 메모리를 갖지 않는다. 아래의 탐지 섹션을 보면 알겠지만 이러한 언어들에서 오류들을 찾는 여러 가지 접근들이 존재한다.

대부분의 고수준 프로그래밍 언어들은 포인터 연산과 캐스팅을 완전히 불허하고, 단일한 메모리 관리 제도로서 쓰레기 수집 (컴퓨터 과학)을 강화함으로써 이 문제를 피한다.

메모리 오류의 종류[편집]

사용되는 프로그래밍 언어에 따라 여러 종류의 메모리 에러가 발생할 수 있다.

  • 버퍼 오버플로 - 경계 외부에 이루어지는 쓰기는 인접한 객체들의 내용이나 내부 데이터 또는 반환 주소를 변경시킬 수 있다.
  • 동적 메모리 오류들 - 동적 메모리와 포인터의 부정확한 관리
    • 허상 포인터 - 삭제된 객체의 주소를 저장하는 포인터
    • 중복 할당 해제 - 이미 할당 해제된 객체에 대한 반복적인 free() 호출은 프리리스트 기반 할당자를 실패시킬 수 있다.
    • 유요하지 않은 할당 해제 - 유효하지 않은 주소를 free()에 넘기는 것은 heap을 변경시키거나 정의되지 않은 행동을 유발한다.
    • 널 포인터 접근은 대부분의 환경에서 예외나 프로그램 종료를 유발하지만 운영체제 커널이나 메모리 보호가 없는 시스템을 오염시킬 수 있다.
  • 초기화되지 않은 변수 - 값이 부여되지 않은 변수가 사용된다. 이것은 몇몇 언어들에서는 의도되지 않은 오염된 값을 갖는다.
    • 와일드 포인터는 포인터가 초기화되기 전에 사용될 때 발생한다. 이것은 허상 포인터와 같은 오류적인 행동을 보이지만 탐지되지 않는 비율은 적다.
  • 아웃 오브 메모리 에러는 가끔은 메모리 보호에 대한 위협으로 여겨진다.
    • 스택 오버플로 - 주로 너무 깊은 재귀 시에 스택 공간이 바닥날 때 발생한다.
    • 메모리 할당 실패 - 프로그램이 사용 가능한 양보다 더 많은 메모리를 사용하려 시도한다. 몇몇 언어들에서, 이것은 각 할당 후에 손수 체크되어야 한다.

탐지[편집]

안전하지 않은 언어로 쓰여진 프로그램들에서 메모리 오류를 탐지하는 많은 방법들이 있다.

  • 사각지대(dead zone)를 제공하고 이 사각지대에 접근하지 못하게 체크하는 특별한 힙 할당자를 사용함으로써 가능하다. 다이하드[1]알리니어 DDT는 자신의 가상 메모리에 객체들을 할당하고, 유효하지 않은 읽기와 쓰기를 금지시키며, 이것을 발생시키는 그 명령어를 디버그 함으로써 메모리를 보호한다.
  • 허상 포인터는 할당 해제된 메모리에 접근 시 중지하고 프로세스를 디버깅하는 하드웨어 메모리 보호를 사용함으로써 잡을 수 있다.[2]
  • 소스코드 도구화하기. SoftBound,[3] CheckPointer[4] 그리고 AddressSanitizer[5] 같은 툴들은 포인터의 정당한 값을 모으고 추적하며, 타당성을 위해 메타데이터에 대한 각 포인터 접근을 체크함으로써 탐지한다.
  • 메모리 체크하는 가상 머신에서 컴파일된 프로그램을 실행 시킴으로써 탐지한다. Valgrind의 메모리 체크 툴이 이 방식을 사용한다.
  • 정적 프로그램 분석도 어떤 경우에는 탐지할 수 있다.

각주[편집]

  1. DieHard
  2. “Memory Debugging in Allinea DDT”. 2015년 2월 3일에 원본 문서에서 보존된 문서. 2015년 2월 3일에 확인함. 
  3. SoftBound
  4. CheckPointer
  5. AddressSanitizer