728x90
반응형
CFI는 제어 흐름의 무결성을 보장하는 기법으로 정상적인 제어 흐름을 벗어나는 공격에 대해 탐지합니다. 하지만 지난 ‘제어 흐름 무결성 CFI의 종착점’ 칼럼에서 살펴본 것처럼, 완벽하게 문맥까지 고려하여 만들어진 CFI라고 하더라도 모든 메모리 손상 공격을 완벽하게 방어하지 못합니다. 이번 칼럼에서는 메모리 손상 공격이 발생했을 때, 제어 흐름을 변조하지 않으면서 공격할 수 있는 데이터 변조 공격에 대해 알아보겠습니다.
 
메모리 손상 공격(memory corruption)은 시스템 보안에서 가장 오래된 문제 중 하나입니다. 메모리 손상 공격은 흔히 프로그램의 개발 실수로 인해 초기화되지 않거나 허가되지 않는 메모리 영역에 접근 시 발생합니다. 해킹이 발생하는 일련의 과정을 보면, 응용 프로그램이나 운영체제에 존재하는 취약점으로 인해 익스플로잇(exploit)이 발생하면, 공격자는 메모리의 특정 영역을 변조할 수 있게 됩니다. 공격자는 특정 영역을 조작함으로써 자신이 원하는 악의적인 행위를 수행하게 됩니다. 이렇게 메모리 손상을 통해 공격자는 특정 데이터를 조작할 수 있게 되고 이를 통해 공격자가 원하는 악의적인 행위를 수행합니다.
 
여기서 데이터는 제어 데이터(control data)와 비제어 데이터(non-control data) 두 가지로 구분할 수 있습니다. 제어 데이터는 값으로 메모리 주소를 가지고 있어 제어 흐름에 직접적으로 영향을 미치는 데이터입니다. 제어 데이터 변조는 프로그램의 흐름을 변조하여 공격자가 원하는 코드를 실행하며, 제어 흐름 탈취 공격(control flow hijacking attack)이라 합니다.
 
반면, 비제어 데이터는 제어 데이터와 상반된 개념으로 제어 흐름에 직접적으로 영향을 미치지 않는 데이터 변수나 포인터를 뜻합니다. 비제어 데이터 변조는 프로그램의 흐름을 변조하지 않으면서 공격자가 원하는 행위를 실행하는 방법으로 Data-Oriented Attack이라 합니다.
 
Data-oriented attack은 앞에서 언급한 것과 같이 프로그램의 비제어 데이터를 조작하여 악의적인 행위를 수행합니다. 이 공격은 간단히 데이터의 변수를 변조하는 것으로도 가능하며, 주로 패스워드나 암호화키를 추출하는 정보 누출(information disclosure), 사용자의 정보를 조작하여 더 높은 권한을 획득하는 권한 상승(privilege escalation), 시스템 자원의 낭비로 인한 성능 하락을 노리는 성능 저하(performance degradation), 시스템에 적용된 여러 가지 보안 기법들을 우회하기 위한 목적으로 사용됩니다.

 

 
Data-oriented attack은 공격 방식에 따라 직접 데이터 변조(Direct Data Manipulation)와 DOP(Data-Oriented Programming)로 나뉩니다. 직접 데이터 변조 방식은 말 그대로 데이터를 직접 변조함으로써 공격자가 원하는 악의적인 행위를 하는 것을 뜻합니다. 이를 위해 공격자는 변조할 데이터의 메모리 주소를 알아야 하고, 이 데이터를 조작할 수 있어야 합니다.
ProFTPd DOP attack flow. An attacker needs to know the underlined addresses and offsets to launch the attack.
DOP는 좀 더 고도화된 비제어 데이터 공격 방식입니다. 직접 데이터 변조가 비제어 데이터를 직접적으로 단순하게 변조하는 것이라면, DOP는 튜링 완전(turing-complete)한 비제어 데이터 공격을 목표로 합니다. 즉, 단순히 데이터의 값을 변조하는 것에서 그치는 것이 아니라, 값을 읽고, 쓰고, 연산하는 것을 포함하여 모든 조작이 가능하게 하여 풍부하게 표현하는 것을 목표로 합니다.
 
DOP 공격은 ROP 공격과 유사하게 기존에 존재하는 코드를 활용하여 공격 코드를 구성합니다. 이때 사용하는 DOP 가젯은 산술, 논리, 할당, 읽기, 쓰기 기능을 하는 명령어로 구분하고, 제어 흐름을 벗어나지 않는 코드를 대상으로 탐색합니다. 이렇게 구분된 가젯을 조합하여 공격 코드를 구성하여 원하는 데이터에 접근하여 값을 읽거나 변조합니다.
 
Data-oriented attack은 제어 흐름을 벗어나지 않는 정상적인 흐름 내에서 공격하기 때문에 제어 흐름 방어 기법으로는 보호할 수 없습니다. Data-oriented attack을 방어하는 방법은 ASLR과 유사하게 데이터 공간 무작위화(data space randomization) 방식과 DFI(Data Flow Integrity)가 존재합니다. 이 두 방식은 아직까지 Data-oriented attack에 대해 완벽한 보안을 제공하지 못하고 있습니다.
 
 
데이터 공격은 메모리 손상으로부터 시작되어 ‘Non-Control Data’의 변조가 일어나면서 시작됩니다. 메모리 손상부터 데이터 변조까지의 공격 흐름에 따라 각 단계에 대한 방어 기법을 생각해보면, 가장 처음 할 수 있는 방법은 메모리 손상을 막는 것입니다. 메모리 손상은 흔히 취약점을 통해 익스플로잇(Exploit)되면서 발생하며, 방어기법으로는 Memory Safety 기법이 존재합니다.
 
Memory Safety 기법은 비제어 데이터뿐만 아니라 제어 데이터까지도 보호하는 방식으로 모든 메모리 손상을 막는 것을 목표로 합니다. 메모리 오류를 탐지해 유효한 포인터와 오브젝트의 주소를 검사하는 방식으로 메모리 공간의 안정성을 보장합니다. 하지만 이 방식은 바이너리 내의 포인터들을 메타데이터와 구분하기 위해 별개의 메모리 공간에 보관하고, 데이터의 접근이 발생할 때, 포인터 여부에 대한 검사와 포인터들이 역참조될 때마다 유효한 범위 내에 있는지 검사를 진행하는 오버헤드로 인해 아직까지는 실생활에 적용할 수 없을 정도의 엄청난 오버헤드가 발생한다는 단점이 존재합니다.
 
메모리 손상으로부터 보호하기 위한 또 다른 방식으로는 중요한 데이터들을 따로 격리시키는 방법이 있습니다. 이러한 메모리 격리 방식은 권한이 높은 리소스에 대한 무단 액세스를 방지하기 위해 널리 사용됩니다. 합법적인 코드 영역에서만 사용자 ID와 권한 같은 보안에 중요한 데이터에 접근할 수 있게 함으로써 의도치 않은 접근으로 인한 직접적인 데이터 손상을 방지합니다. 이 방식은 메모리를 격리할 수 있는 추가적인 하드웨어나 소프트웨어적인 방법이 필요하다는 것과 적은 양의 중요한 데이터를 보호하는 경우에만 효과적이라는 단점이 존재합니다.
 
다음으로 Non-Control Data가 변조되는 것을 막기 위한 방법으로는 데이터의 위치를 알 수 없게 만드는 방법이 있습니다. 이 방식은 데이터 오브젝트 내의 위치를 랜덤하게 변화하는 방식과 데이터 표현을 수정하는 방식이 있습니다. DSR(Data Space Randomization)이라고 하는 방식은 메모리의 각 데이터 개체를 임의의 키값으로 암호화하고, 사용하기 전에 해독하는 방식으로 데이터를 보호합니다. 하지만, ASLR과 유사하게 무작위화의 한계로 인해 완벽한 보안을 제공하지는 못합니다. 또한, 메모리 레이아웃을 파악해 공격이 가능하며, DOP(Data-Oriented Programming) 공격에 취약하다는 한계점이 있습니다. 또한, 모든 데이터의 위치를 무작위화 하는 것은 높은 오버헤드를 발생시킬 수 있다는 단점도 존재합니다.
 
마지막 방법으로 데이터 흐름 무결성(Data Flow Integrity) 기법이 있습니다. 이름에서도 느껴지듯이, 데이터 흐름 무결성 방식은 제어 흐름 무결성 방식과 접근 방식이 비슷합니다. 먼저 프로그램 실행 전에 데이터가 정의되고 사용되는 것에 대한 정적 데이터 흐름 그래프(DFG)를 생성합니다. 그리고 프로그램이 실행되면서 각 데이터의 읽기 작업이 수행될 때, 이 데이터가 합법적인 작업에 의해서 정의되었는지 데이터 변조에 대한 검사를 수행해 데이터를 보호합니다. 이 방식 또한, 모든 메모리 영역에 데이터 흐름 무결성을 완벽하게 적용하면 모든 데이터 변조 공격을 막을 수 있지만, 모든 데이터가 정의될 때 값을 기억하고, 사용될 때 값이 변조되었는지 검사하는 루틴이 추가되어 매우 높은 오버헤드가 존재하며, 아직까지 기술적으로 어려운 부분이 많이 있습니다.
 
대부분의 데이터 공격에 대한 방어기법들을 요약하자면, 프로그램 내에 존재하는 수많은 데이터를 모두 보호하기에 아직 기술적으로나 성능적인 측면에서 볼때 상당히 많은 비용이 발생하기 때문에 결국에는 보안적으로 중요한 데이터들을 선별하여 일부 데이터들만 보호하는 방법이 실용적인 접근 방법이라고 할 수 있겠습니다.
 
지금까지 살펴본 것처럼 메모리 손상에 대한 다양한 공격들과 그에 대한 여러 가지 방어 기법들에 대해 살펴보았습니다. 결국 가장 완벽해 보이는 최신의 방어기법이라도 또 다른 취약점과 여러 우회적인 공격에 의해 공격이 가능하다는 한계점이 있다는 것을 알 수 있었습니다. 따라서 더욱 안전한 시스템을 만들기 위해서는 여러 공격들에 대한 높은 이해와 심도 있는 분석을 바탕으로 한 방어기법 연구, 더욱 철저한 검증과 테스팅이 조화를 이룰 때 가능하며, 더욱 완벽한 보안을 위해서는 자동화가 필수적인 과제가 아닐까 생각해 봅니다.
 

https://dl.acm.org/doi/fullHtml/10.1145/3462699

 

Exploitation Techniques for Data-oriented Attacks with Existing and Potential Defense Approaches

1 INTRODUCTION Memory-corruption vulnerabilities are one of the most common attack vectors used to compromise computer systems. Attackers exploit these vulnerabilities in different ways to perform arbitrary code execution and data manipulation. Existing me

dl.acm.org

 

728x90
Posted by Mr. Slumber
,