물의 흐름을 파악하고자 색깔을 입힌 후 추적한다는 개념에서 DTA는 색깔 대신 오염(taint)이라는 명칭으로 프로그램의 어느 위치에서 영향을 미치는지 관찰하는 것이다.
10장에서는 동적 오염 분석의 기초 원리를 설명할 것이다. DTA 기법은 복잡한 내용을 다루고 있기 때문에 DTA 관련 도구를 제작할 수 있으려면 먼저 내부 원리를 상세히 파악하는 것이 중요하다.
10.1 DTA란 무엇인가?
Data Taint Analysis(DTA)의 약자로 프로그램 내부의 특정 상태를 설정했을 때, 그 부분으로 인해 어떤 부분이 영향받는지를 확인할 수 있는 프로그램 분석 방식이다.
주로 DTA는 동적 바이너리 계측 플랫폼의 최상단에서 구현되고는 한다.
실제로 거의 모든 명령어와 레지스터에 대해 처리해야 하므로 성능이 10배 이상 안좋아지고는 한다.
소스코드가 제공되는 경우에는 소스코드 단에 DTA를 삽입하여 정적 계측 방식으로도 가능하다.
10.2 DTA의 세가지 요소: 오염원, 오염 지역, 오염 전파
1. 오염원
오염원이란 추적하고자 하는 특정 데이터의 프로그램 내 위치다.
시스템 콜이나 함수 엔트리 포인트 또는 개별 명령어들을 모두 오염원으로 설정할 수 있다.
각 DTA에서 제공하는 API를 호출하여 관찰하려는 데이터에 표기하므로써 오염시킬수 있다.
2. 오염 지역
오염 지역이란 오염된 데이터로부터 영향을 받았는지 여부를 확인하고자 하는 프로글매 내의 위치를 일컫는다.
예를들어, 제어 흐름 탈취 공격을 탐지하고자 할때, 간접 호출, 간접 점프, return 명령어에 콜백 함수를 사용해 계측을 수행해야 한다.
이 경우 대상 계측 명령어들이 바로 오염 지역이 된다.
DTA 라이브러리는 대상 레지스터 또는 메모리 영역이 오염됐는지 점검해 주는 함수를 제공한다.
3. 오염 전파 추적하기
프로그램 내부에서 오염된 데이터가 어떻게 흘러가는지를 추적하려면 해당 데이터를 처리하는 모든 명령어의 입력값으로 사용돼 그 출력값을 변화시키면서 전파되는지 판정할 수 있어야한다.
예를들어 Mov 명령어의 피연산자가 오염됐다고 할 때 계측 코드에서 그 명령어의 결과값으로 도출되는 값 역시 오염됐다고 표기해야 한다.
오염이 전파되는 과정을 추적하는 것은 매우 복잡하다. 왜냐하면 연산자의 출력이 되는 피연산자가 어떤 것인지를 결정하는 것이 간단한 문제는 아니기 때문이다.
오염 전파는 입력값 피연산자와 출력값 피연산자 사이의 오염 관계를 정의하는 오염 정책에 영향을 받는다.
10.3 DTA를 사용해 Heartbleed 버그 탐지하기.
1. Hearbleed 취약점에 대한 간략한 요약
Heartbleed는 OpenSSL 프로토콜인 Heartbeat의 구현 과정에서 발생한 고전적인 버퍼 초과 읽기 오류를 뜻한다.
Heartbeat 프로토콜은 SSL이 설정된 서버를 대상으로 장치가 현 연결 상태를 확인할 수 있도록 하는 역할을 한다.
이 때 장치는 서버에 Heartbeat Request를 보내게 되는데 송신 시 임의의 문자열을 포함할 수 있다.
만약 연결된 상태라면, 서버는 HeartBeat response 메시지 내에 해당 내용을 되돌려 주는 방식으로 메아리 응답을 한다.
Heartbeat request에는 문자열로 된 내용뿐만 아니라 해당 문자열의 길이 값을 지정한 필드도 포함되어 있으며, 이 Length값을 올바르지 않게 설정해 처리하는 경우 Heartbleed 취약점이 발생할 수 있다.
실제 공격자는 해당 length값을 실제 문자열의 길이보다 훨씬 긴 값을 지정할 수 있으며, 이 경우 서버는 응답을 위해 내용을 복사하는 과정에서 메모리 내의 다른 정보까지 전달하게 된다.
해당 소스코드는 Heartbeat의 서버 사이드 소스코드이다.
buffer = OPENSSL_malloc(l + 2 + payload + padding); // 버퍼 할당
bp = buffer;
*bp++ = TLS1_HB_RESP0NSE;// 타입 값 지정
s2n(payload, bp); //s2n 매크로를 통해 payload 전달
memcpy(bp, pl, payload); //payload 사이즈만큼 메모리에서 복사
bp += payload;
RAND_pseudo_bytes(bp, padding); // 패딩 추가
r = ssl3_write_bytes(sy TLS1_RT_HEARTBEAT, buffer, 3 + payload + padding); //전달
C++
복사
10.3.2 오염 분석 방법을 통해 Heartbleed 탐지하기
위의 소스코드를 이해하고, 예시를 들어보면 request에서 전달한 데이터가 서버의 메모리에 저장되었고, 그 메모리 근처에 비밀키가 존재할 경우, 해당 비밀키를 오염시키면 해당 내용이 어디로 복사될 때 이를 추적할 수 있다.
또한 send 및 snedto 시스템 콜이 오염 지역인 것으로 가정하자. 그렇다면 오염된 데이터가 네트워크를 통해 전송될 때 그 순간을 포착할 수 있다.
문자열의 길이는 6바이트지만, 공격자가 전달한 길이는 21바이트며, 해당 길이만큼 추가적으로 복사해 공격자에게 전달하여 공격자는 비밀키를 획득할 수 있다.
10.4 DTA 설계 요소: 오염 단위, 오염 색깔, 오염 정책
해당 절에서는 DTA시스템을 설계함에 있어 가장 중요한 세 가지 측면을 살펴볼 것이다.
10.4.1 오염 단위
DTA 시스템이 관찰 할 오염 단위란, 오염된 대상 정보에 대한 단위이다.
비트 단위의 시스템일 경우, 메모리 단위 내에 개별 비트 정보들이 오염됐는지 여부로 판단한다.
바이트 단위의 시스템일 경우, 바이트 중 1비트라도 오염됐을 경우 전체가 오염된 것으로 간주한다.
바이트 단위 오염 정확도 체크는 비트에 비해서 정확하지 못하지만, 성능면에서 비트에 비해서 상당히 뛰어나다.
10.4.2 오염 색깔
DTA 시스템에서 오염이 어디서 촉발됐는지를 알고 싶을 때 오염 색깔을 사용한다.
바이트 시스템의 경우 각 비트별로 색깔을 다르게 하여 8가지 오염 색깔을 활용 할 수 있다.
10.4.3 오염 전파 정책
오염 정책이란 DTA 시스템에서 오염이 어떻게 전파되는지 그 과정을 설명하고 다수의 오염 흐름이 중첩되는 경우 오염 색깔을 어떻게 병합해 표기할지를 정하는 것이다.
1.
변수 C에 A의 값이 그대로 할당되기 때문에 :=이다
2.
XOR 연산을 하면 둘다 0인 경우를 제외하곤 합쳐지기 때문에 합집합으로 표시한다
3.
ADD 연산 또한 합쳐지기 때문에 합집합으로 표시한다.
4.
동일한 변수에 XOR을 수행하는 경우 무조건 0이 나오기 때문에 0으로 표시한다.
5.
변수 A를 6만큼 Left Shift를 수행할 경우 공격자는 A만 변조가 가능하기 때문에 <<로 표시한다.
6.
공격자는 변수 A, B 둘다 변조할 수 있기 때문에 B값으로 쉬프트를 수행하여 :=로 표시한다
a.
아직 이해가 안간다.
10.4.4 과잉 오염 및 과소 오염
1.
과소 오염
a.
실제로 오염이 발생한 상황임에도 오염이 발생하지 않은 것처럼 표현하는 경우
b.
이러한 경우 공격자가 공격을 수행했음에도 탐지가 불가능함.
2.
과잉 오염
a.
실제로 오염이 발생하지 않은 상황임에도 오염이 발생한 것처럼 표현되는 경우
b.
타 보안 솔루션의 오탐과 비슷함.
10.4.5 제어 의존성
오염 추적은 데이터 흐름을 추적하는 것과도 같다.
하지만 이런 데이터 흐름은 암시적으로 제어 흐름의 구조에 영향을 받을 수밖에 없으며, 이를 보통 암시적 흐름이라고 한다.
var = 0;
while(cond--)var++;
C++
복사
해당 로직의 경우 공격자가 반복문의 조건을 조작하고자 cond 값을 변경하면 이는 곧 결과값인 var에 영향을 미친다.
이를 곧 제어 의존성이라고 한다.
공격자가 cond 값 변조를 통해 var 값을 변조하였지만, 두 변수간의 묵시적인 데이터 흐름은 발생하지 않고 있다.
하지만 DTA 시스템은 묵시적 데이터 흐름만 추적할 수 있기 때문에, 이러한 종류의 의존 관계에 대해서 파악할 수 없을것이고, var 값을 오염되지 않은 것으로 판단하여 과소오염으로 진단하게 된다.
10.4.6 섀도 메모리
섀도 메모리란 DTA 시스템을 위해 마련되는 특수 목적의 가상 메모리 공간이며, 나머지 메모리 공간의 오염 정보 상태를 기록해 이를 추적한다
섀도 메모리가 구성되는 구조는 어떤 오염 단위를 사용하거나 오염 색깔을 몇 종류로 지원하는지에 따라 다르게 전개된다.
그림 10-2는 바이트 단위의 오염을 처리할 때 사용하는 섀도 메모리의 구조를 나타낸다.
각각 1 쉐도우 비트/바이트 , 1 쉐도우 바이트 / 바이트 , 4쉐도우 바이트 / 바이트 를 나타낸다.
오염 색깔을 메모리당 1비트씩 설정한 경우 0,1의 바이트로만 색깔 구분이 가능하며,
오염 색깔을 메모리당 1바이트씩 설정한 경우 , 총 8색깔로 구분이 가능,
오염 색깔을 메모리당 8바이트씩 설정한 경우, 총 32색깔로 구분이 가능하다.
그러나, 오염 색깔이 늘어나면 늘어날수록 섀도 메모리 당 색깔 메모리 할당량과 리소스 사용량이 급증하게 된다. 해당 부분을 고려하여 설정하여야 한다.