Google Project Zero 팀, iOS를 원격으로 해킹하다
Google Project Zero 팀은 Google의 0-day를 찾는 팀으로 2014년에 창설되어 지금까지 많은 취약점들을 찾은 팀입니다. 2020년 12월 1일 Google Proejct Zero 팀의 Ian Beer가 Google Project 공식 블로그에 iOS를 원격으로 해킹하는 내용인 "An iOS zero-click radio proximity exploit odyssey"라는 제목의 글을 작성하였습니다. iOS의 AWDL에 있는 취약점을 찾아서 공격을 했다고 하는데, AWDL은 무엇이고 어떤 취약점이 있었는지에 대해서 간단하게 알아보도록 하겠습니다.
AWDL이란?
AWDL은 Apple Wireless Direct Link의 약자로 Apple 제품들 간의 peer-to-peer 통신을 할 때 주로 이용되는 network protocol입니다. 예를 들어, iPhone에서 다른 iPhone으로 Airdrop을 이용해서 데이터를 전송한다던가, macbook에서 Sidecar를 이용해서 iPad를 두 번째 디스플레이로 사용할 때 AWDL protocol이 사용됩니다. AWDL의 처리는 iOS kernel에서 진행되며 기본적으로 블루투스를 통해 주변에 있는 기기에 AWDL protocol을 통해 연결할 수 있기 때문에 AWDL을 처리하는 부분에 취약점이 존재한다면 주변의 기기들을 원격으로 탈옥까지 (Remote Jailbreak) 할 수 있는 심각한 취약점이 될 수 있습니다.
AWDL은 custom radio protocol이 아니라, WiFi (IEEE 802.11g, 802.11a)라는 radio layer 위에서 구현되어 동작하는 protocol 입니다. 따라서 AWDL 패킷은 다음 그림과 같이 802.11 header와 action header, AWDL fixed header, AWDL payload로 구성됩니다.
(출처: https://googleprojectzero.blogspot.com/2020/12/an-ios-zero-click-radio-proximity.html)
AWDL payload는 payload의 type을 나타내는 1바이트 데이터 (type), payload의 길이를 나타내는 2바이트 데이터 (length)와 값 (value)으로 이루어져 있으며 이들을 줄여서 TLV라고도 부릅니다.
AWDL 구현 상의 취약점
AWDL payload는 iOS kernel에서 그 type에 따라서 다른 방식으로 parsing을 진행하는데, 먼저 type에 따른 length를 확인하고 유효한 length인 경우에만 parsing을 진행합니다. 기본적으로 type별로 최대 length가 정해져 있고, 특별히 정해져 있지 않은 경우에는 1024가 기본 최대 길이로 설정됩니다.
이 때, 취약점은 type이 0x14인 AWDL payload를 parsing하는 IO80211AWDLPeer::parseAwdlSyncTreeTLV 함수에서 발생합니다. 다음은 해당 함수의 일부를 발췌한 내용입니다.
int
IO80211AWDLPeer::parseAwdlSyncTreeTLV(awdl_tlv* tlv)
{
u64 new_sync_tree_size;
u32 old_sync_tree_size = this->n_sync_tree_macs + 1;
if (old_sync_tree_size >= 10 ) {
old_sync_tree_size = 10;
}
if (old_sync_tree_size == tlv->len/6 ) {
new_sync_tree_size = old_sync_tree_size;
} else {
new_sync_tree_size = tlv->len/6;
this->n_sync_tree_macs = new_sync_tree_size;
}
memcpy(this->sync_tree_macs, &tlv->val[0], 6 * new_sync_tree_size);
...
(출처: https://googleprojectzero.blogspot.com/2020/12/an-ios-zero-click-radio-proximity.html)
this_n_sync_tree_macs는 this->sync_tree_macs에 현재 존재하는 item의 개수를 나타내며 최대 10개까지만 허용합니다. 이에 맞춰서 this->sync_tree_macs 또한 6바이트 짜리 item을 최대 10개까지만 저장할 수 있도록 60바이트 array를 나타냅니다.
즉, tlv->len/6이 10보다 크면 this->sync_tree_macs를 overflow내서 그 뒤에 존재하는 데이터를 AWDL의 value 값으로 덮을 수 있다는 것을 의미합니다. 이를 방지하기 위해서는 type에 따른 length를 확인하는 부분에서 0x14 type에 대한 length를 65보다 작은 지 확인했어야 합니다. 하지만 1024보다 작은 지만 확인했기 때문에 tlv->len/6 을 10보다 큰 값으로 만들 수 있어 heap overflow 취약점이 발생하였습니다.
데모 영상
다음은 Ian Beer가 공개한 iOS 원격 서비스 거부 공격 (Remote Denial of Service Attack)과 원격 코드 실행 (Remote Code Execution)을 통해 계산기를 실행시키는 데모 동영상입니다.
(출처: https://googleprojectzero.blogspot.com/2020/12/an-ios-zero-click-radio-proximity.html)
(출처: https://googleprojectzero.blogspot.com/2020/12/an-ios-zero-click-radio-proximity.html)
결론
Google Project Zero 팀의 Ian Beer는 iOS kernel에서 AWDL을 처리하는 과정 중에서 발생하는 heap overflow 취약점을 이용해 remote jailbreak에 성공하였으며 블로그에 그 내용을 상세히 정리하였습니다. 본 칼럼에서는 AWDL의 취약점에 대해서만 간략하게 다루고 있지만, 해당 블로그에서는 iOS에 적용된 각종 mitigation을 우회해서 exploit하는 방법까지 소개되어 있으니 관심 있으신 분들은 해당 블로그를 방문해보시는 것도 좋을 것 같습니다.