아.. 이 중요한 취약점을 여기에다는 포스팅을 안 해뒀구나.. 지금 써둬야겠다. 무려, 작년에 있었던 Bash와 더불어 엄청난 영향을 주었던 취약점이다. OpenSSL에 존재하는 취약점으로 HeartBleed 취약점이라고 불리는 취약점이다. 우선 해당 취약점을 이해하기 위한 기본 지식을 살펴보려고 한다.


What is A heartbeat protocol?(https://tools.ietf.org/html/rfc6520)
우선, DTLS와 TLS가 무엇인지 알아보자. DTLS는 UDP와 같이 unreliable traffic이며, DTLS는 연결되어 있는 peer가 여전히 살아있는지 확인하기 위해서 SSL connection을 재수립한다. TLS는 TCP와 같은 reliable traffic으로, peer가 살아있는지 확인하기 위해서 data를 지속적으로 전송해주는 방법 밖에 없다. 이러한 제한을 해결하기 위한 것이 Heartbeat Hello Exxtention이다. heartbeat protocol은 TLS와 DTLS에 계층에서 트래픽을 암호화하기 위해 사용되며 TCP와 UDP 모두 쓰일 수 있다.


What kind of vulnerability was found?
OpenSSL에서 TLS와 DTLS 계층에 대한 구현 부분에서, 즉 Heartbeat Hello Extention 소스코드에서, 취약점이 발견된 것이다. 취약점의 영향으로 공격자는 서버 메모리에 올라와 있는 값을 일부 확인할 수 있다.


What does cause this vulnerability?
취약점이 어떻게 야기되는지 알아보자. 우선, Python으로 작성한 heatbleed 테스트 스크립트를 돌려보자. (http://www.exploit-db.com/exploits/32745/)
코드를 보면, 단순히 Heartbeat 요청을 보내고 응답을 받는 단순한 스크립트이다. 해당 스크립트는 응답의 길이로 해당 서버가 취약한지 취약하지 않은지를 결정한다. 스크립트가 사용하는 취약한 heartbeat 메세지를 한번 봐보자.



hb(0) Record Layer content Type 0x18
hb(1)hb(2) Record Layer Version TLS 1.1
hb(3)hb(4) Record Layer Length 3
hb(5)hb(6)hb(7) Heartbeat Message 01 40 00


Record Layer Length 길이는 최소한 이상이 되어야 한다. Record Layer Length 이전에 최소 3비트는 있기 때문이다. Heartbeat Message 0x014000을 자세히 봐보자.


위에 보이는 malformed packet에 대해서 모두들 쉽게 이해하기를 바란다. "Malformed Packet : SSL" 부분이 빨간색으로 하이라이트되어 있는데, 이는 malformed packet이라는 것을 의미하는 표시이다. 자세히 보면, payload length가 16384로 설정되어 있음에도 불구하고, 실제 payload 값은 없다. 따라서 이 malformed packet이 서버에 보내졌을 때 서버는 단순히 "Payload Length"만을 계산하고 16384만큼의 값을 Client에게 던저준다. 서버의 메모리에 올라와있는 응답값 길이는 16384보다 훨씬 작을 것이다. 그럼에도 불구하고 서버는 16384만큼 보내줄 예정인데, 그렇다면 어떤 값이 Client에게 갈까? 메모리의 일부가 가는 것이다. 그 메모리에 어떤 값이 포함되어 있을까? 아무도 모른다. 서버 내의 민감한 정보(가령, private key 값) 등이 포함되어 있을 수 있다.


Detail of the exploit
openssl의 어떤 부분이 취약하게 작성되었는지 알아보자. openssl 소스코드에서 ssl/d1_both.c 파일 안에 선언되어 있는 dtls1_process_heartbeat 함수에서 취약점이 존재한다. 



1487 줄에 보면, memcpy(bp, pl, payload)라고 되어있는 이 부분이 malformed packet에서 메모리 일부를 유출하게 작성되어있다. memcpy는 pl에서 시작하는 메모리 contents를 bp로 복사하도록 한다. 이 포인터 변수 pl은 heartbeat 메세지의 세번째 바이트를 가리킨다. (*p++와 n2s(p, payload)함수가 pl이 세팅되기 전에 실행된다는 것을 참고하자.) malformed heartbeat message에서 payload는 0x4000 즉, 16384 바이트이다. 따라서 pl이 가리키는 곳부터 16384바이트가 bp로 복사된다. 그런데 우리가 위에서 본 malformed packet에서는 16384만큼의 packet이 없다. 따라서 packet 다음에 따라오는 메모리의 일부를 복사한다. 공격자는 아마도 자기가 원하는 어떤 값들이 있기를 희망하며 공격을 수행할 것이다.(즉, 공격이 성공해도 공격자 입장에서 항상 원하는 정보를 얻는 것은 아니라는 뜻이다.) 참고로 n2s는 메크로로 아래와 같이 정의되어 있다.


Which version of openssl is vulnerable?

아래의 openssl 버전이 취약하다.


# 취약한 버전
1.0.1f, 1.0.1e, 1.0.1d, 1.0.1c, 1.0.1b, 1.0.1a, 1.0.1


위의 버전들은 1.0.1g 혹은 그 이상 버전으로 업그레이드 되어야 한다. 1.0.1g에서 소스코드는 아래와 같이 데이터 길이를 체크하는 방식으로 수정되어 있다.


지금까지 CVE-2014-0160에 대해서 알아봤다. 아래의 링크를 참고하고 다른 종류의 openssl 취약점이 존재하는지도 한번 살펴봐도 좋다.
http://www.openssl.org/news/vulnerabilities.html

Posted by 빛나유
,