I/O 관리자가 CPU의 연산을 보고 미리 예측해서 명령과 데이터를 가져온다. 그런데 여기서 핵심은 '시키지도 않은 일'이라는 것이다. 그래서 심각한 사고가 발생했는데 바로 CPU 게이트 사건이다. 흔히 'Meltdown' 혹은 'Spectre'라는 것이다.
예를 들어보자. 해외 순방 중인 대통령을 암살하려는 범죄조직이 있다고 하자. 이 조직은 대통령이 어느 호텔의 A동에 묵는다는 것까지는 알아냈다. 그러나, 몇 호실에 있는지는 알아내지 못했다. 여기서는 A동 202호라고 하자. 대통령 관련 정보는 당연히 1급도 아닌 극비사항이므로 호텔 프론트에는 "A동 관련 질문은 일절 답변하지 말라"는 엄명이 내려와 있다. 따라서 "대통령이 A동 몇 호실에 묵고 있나요?"라고 물어봐도 당연히 "대답해 드릴 수 없습니다."라는 답변만 돌아올 뿐이다. 여기서 조직원은 잔머리를 굴려 프론트 직원의 노하우를 역이용하기로 한다. 프론트 직원은 다음과 같이 일을 처리한다고 알려져 있다.
- 특정 호실에 대한 문의가 자주 들어오면 직원은 그 방을 시스템에서 자꾸 검색하는 수고를 덜기 위해 해당 방의 정보를 메모지에 적어 놓는다.
- 메모지에 적어놓은 방의 정보는 검색하지 않고 메모지를 참고해 다른 방에 비해 훨씬 빠르게 대답해준다.
- 메모지에 뭐라고 적혀있는지 직접 묻는 질문에는 대답하지 않는다.
여기서 1번이 어떠한 메모리에 대해 참조를 하면 그것을 캐싱하겠다는 의미이다.
하지만 여기서 문제는 해커들이 이를 역이용한다는 것이다.
작전 1단계. 우선 질문을 다음과 같이 바꾼다.
"B동 호텔방 중 A동의 대통령이 묵는 호실과 같은 호실이 비어있나요?"
A동 관련 질문이 들어갔기 때문에 직원은 여전히 "대답해 드릴 수 없습니다."라고만 대답할 뿐이다. 그런데 상기했듯 프론트 직원은 특정 방에 대한 문의가 많이 들어온다 싶으면 호텔 시스템을 계속 뒤져보는 번거로움을 덜기 위해 해당 방의 정보를 메모지에 적어 놓는 습관이 있다. 이제 저 질문을 계속 반복해서 직원의 귀차니즘을 자극해 보자. 그러면 직원은 계속 "대답해 드릴 수 없습니다."라고 대답은 하면서도 메모지에다가는 문제의 "B동 호텔방 중 A동의 대통령이 묵는 호실과 같은 호실", 즉 B동 202호의 정보를 적어 놓을 것이다.
직원의 귀차니즘을 충분히 자극했다 싶으면 작전 2단계로 간다. 작전의 목표는 메모지에 적힌 호실이 어디인지 알아내는 것. 다만 상기했듯 메모지의 내용을 직접 묻는 질문에는 여전히 답변을 거부한다. 하지만 간접적으로 알아낼 방법은 있다. 바로 "2. 메모지에 적어놓은 방의 정보는 검색하지 않고 메모지를 참고해 다른 방에 비해 훨씬 빠르게 대답해준다."를 이용하는 것. 이를 위해 "A동"이라는 말은 싹 빼고 B동에 있는 모든 방에 대해 직원에게 무작위로 캐묻는다.
"B동 408호 비어 있나요?"
"B동 105호 비어 있나요?"
"B동 803호 비어 있나요?"
...
이런 식. 방의 정보를 순서대로가 아닌 무작위로 캐묻는 이유는, 순서대로 물어보면 규칙을 예측한 프론트 직원이 물어보는 방 정보의 뒷방 정보를 메모지에 미리미리 적어놓아서 빨리 대답해버리기 때문에 귀차니즘을 자극한 게 무용지물이 될 수 있기 때문이다.
A동 관련 질문은 일절 답변하지 말라는 엄명이 내려와 있지만, B동에 대해서는 특별한 지침이 내려오지 않았기 때문에 직원은 모두 순순히 대답을 해 줄 것이며, 물어볼 때마다 아무것도 모르는 프론트 직원은 호텔 시스템을 검색하기 위해 "잠시만요..." 하며 뜸을 들일 것이다. 하지만 문제의 "B동 호텔방 중 A동의 대통령이 묵는 호실과 같은 호실", 즉 B동 202호는 프론트 직원이 이미 메모지에 적어 놓아서, 호텔 시스템을 검색할 필요 없이 뜸을 들이지 않고 바로 대답해줄 수 있다. 그리고 조직원은 이로부터 프론트 직원이 메모지에 써놓은 호실이 B동 202호임을 알 수 있게 되는 것이다. 여기서 B동을 A동으로만 바꾸면 거기에 대통령이 있다는 것을 알 수 있다. 일을 효율적으로 하기 위한 프론트 직원의 노하우가 여기서는 오히려 기밀정보를 유출시켜 대통령을 위험에 빠뜨리는 결정적인 계기로 작용하는 것이다.
즉 실제로 보면 메모리를 아무데나 무작위로 참조를 한다. 그리고 CPU가 예측한것과 다른 곳을 참조한다. 그렇게 수차례하면 원하던 메모리를 캐싱이 될것이고 그 메모리를 참조할 수 있다. 그러면 해커들은 그 메모리를 참조해서 무엇을 알아내려 하는 것일까? 램에서는 일정 I/O Address range를 특정 장치가 점유한다. 예를들어 키보드라고 보면 I/O Address range에 우리가 타자친 내용이 다 들어가져 있다. 이렇게 우리가 타자 친 내용들을 알 수 있는 것이다.
또 예를 들면 해커가 특정 메모리를 참조하라는 user-mode application을 작동시키면 이 특정 메모리를 read할 수 있는 권한은 system call(커널)밖에 없어서 권한오류가 나오고 동작을 안한다. 하지만 실제로는 권한과 상관없이 연산이 일어나고 보여주지 않을 뿐이다. 이 점을 노리는 것이다.
즉, 해커가 시킨 일을 하기 위해 CPU는 다음의 일을 해야 한다.
- 100번 방에서 숫자를 꺼낸다.
- 100번 방에서 꺼낸 숫자를 레지스터 al에 임시로 저장한다.
- al에 저장된 숫자와 1000을 더한다. (여기에서는 1097로 가정하자.)
- 3에서 더한 결과에 해당하는 RAM의 숫자를 꺼낸다. (즉, 1097번 방의 자료를 꺼낸다.)
- 꺼낸 숫자를 해커에게 전달한다.
상기에 서술한대로, 이 일련의 과정들은 권한 오류를 일으킨다.
문제는 CPU의 파이프라인 구조에 있다. 해커가 100번방의 숫자를 꺼내라고 했을 때, CPU는 권한 여부에 상관없이 일단 100번 방의 숫자를 꺼낸다. 그리고 RAM의 1097번 방의 숫자도 꺼낸다. 즉, 실제로 CPU는 해커가 시킨 일을 다 한다. 단지 보여주지 않을 뿐이다. 예전까지는 해커한테 보여주지만 않으면 괜찮다고 생각했기 때문에 이런 방식이 사용되었다. 'CPU가 일을 다 하고 보여주지만 않으니, CPU가 일한 흔적을 찾아 100번 방의 숫자를 알아내자'라는 것이 멜트다운 버그의 핵심 아이디어이다.
더 대박은 가상화 환경에서 난리가 났다.
- Guest0번에서 악성코드 등장
- 같은 CPU내의 VM에서 프로세스 동작 및 실제 CPU에 데이터 전달 및 RAM에 저장 (코어에 전달)
- 연산을 하는 고장에 캐싱 후 동작
- 악성 코드가 무작위로 RAM 메모리 참조
- 결국 VM 프로세스 자동 캐싱
- 즉, Guest2 VM에서 Guest0 VM의 메모리를 참조하는 기적 발생
이 예로 우리가 AWS를 이용하여 웹서버를 이용하고 있다고 보자. 거기에는 인증서도 있고 각종 코드도 있을 것이다. 위에 설명한 방법으로 AWS에 우리의 인증서가 털리는 경우가 발생한다.