Notice
Recent Posts
Recent Comments
Link
«   2024/09   »
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30
Archives
Today
Total
관리 메뉴

멜트다운 취약점 원리 간단요약 본문

Study/Etc

멜트다운 취약점 원리 간단요약

awakerrday 2018. 2. 7. 20:22

멜트다운 (http://www.cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-5754)


당신이 키보드로 무엇을 입력했는지 훔쳐내려는 해커가 있다고 생각해보자. 키보드로 무엇을 입력했는지 알아내면 은행 거래 비밀번호 등 중요한 정보를 탈취해낼 수 있다. 해커의 목적이 키보드 입력값의 탈취라는 전제 하에 다음의 사항을 생각해 보자.

컴퓨터는 모든 것을 숫자로 처리한다. 가령 ASCII코드를 전제할 때 컴퓨터는 'a'라는 문자를 97로 이해하고 'b'라는 문자를 98로 이해한다. 우리가 키보드로 'a'를 칠 때, 컴퓨터는 메모리의 100번째 방에 숫자 '97'을 적어넣는다고 치자. 원칙적으로는 OS의 핵심부분인 커널 이외에는 메모리의 100번 방에 무슨 내용이 들어가 있는지 아무도 알 수 없다.[16] 해커는 이 100번째 방의 내용을 노리고자 '메모리의 100번째 방을 읽어서 나한테 보내라'라고 CPU에게 명령을 내리지만, CPU는 명령을 거부한다. 이게 정상이다. 만약 CPU가 아무한테나 100번째 방의 내용을 보내준다면 가능하다면 비밀번호 등 우리가 키보드로 친 내용들이 유출될 것이다. 그러나 멜트다운 버그를 이용하면 이 100번째 방의 내용을 알 수 있다.

100번째 방의 내용을 읽어내기 위해 해커는 두 개의 명령을 CPU에게 연속해서 전달한다. 첫 번째는 '메모리의 100번 방에 있는 내용을 레지스터 al로 복사해라' 이며 두 번째는 '1000+al을 계산한 다음 RAM에서 그 방에 있는 숫자를 가져다 줘'이다. 즉 100번 방의 내용 → al → 1000+al을 통해 해커는 100번 방의 내용을 알아내려고 하는 것이다. 만약 1000+al이 1097이라면, 'a'가 97인 점을 이용하여 해커는 키보드에서 'a'가 입력되었다는 것을 알아낼 수 있다.1000+al이 1098이라면 해커는 'b'가 입력되었다는 것을 알 수 있다.

즉, 해커가 시킨 일을 하기 위해 CPU는 다음의 일을 해야 한다.
1. 100번 방에서 숫자를 꺼낸다.
2. 100번 방에서 꺼낸 숫자를 레지스터 al에 임시로 저장한다.
3. al에 저장된 숫자와 1000을 더한다. (여기에서는 1097로 가정하자)
4. 3에서 더한 결과에 해당하는 RAM의 숫자를 꺼낸다. (즉, 1097번 방의 자료를 꺼낸다.)
5. 꺼낸 숫자를 해커에게 전달한다.

그런데 애당초 100번 방에 있는 숫자를 해커가 꺼내라고 한 1번부터 잘못되어있다. 숫자를 꺼낸 것 자체가 잘못인데, 2, 3, 4, 5번을 할 수가 없다. CPU는 메모리의 100번 방에 있는 내용을 al로 복사하지도, 1000+al을 계산해서 RAM의 방 번호를 찾아 내용을 가져다 주지도 않는다.

문제는 CPU의 파이프라인 구조에 있다. 해커가 100번방의 숫자를 꺼내라고 했을 때, CPU는 실제로는 100번 방의 숫자를 꺼낸다. 그리고 RAM의 1097번 방의 숫자도 꺼낸다. 즉, 실제로 CPU는 해커가 시킨 일을 다 한다. 단지 보여주지 않을 뿐이다. 예전까지는 해커한테 보여주지만 않으면 괜찮다고 생각했다. CPU가 일을 다 하고 보여주지만 않으니, CPU가 일한 흔적을 찾아 100번 방의 숫자를 알아내자라는 것이 멜트다운 버그의 핵심 아이디어이다. 

해커는 앞서 간단히 언급한 캐시를 이용한다(캐시는 램보다 속도가 훨씬 빠른 메모리이다). CPU가 RAM의 1097번 방에 있는 정보를 꺼낼 때, 1097번 방의 정보는 자동으로 캐시에 기록된다. RAM에 있는 정보를 캐시로 베껴 써 두면 나중에 다시 볼 때 이를 빠르게 볼 수 있기 때문이다.[17] CPU는 해커에게 RAM에서 일껏 1097번 방의 자료를 꺼내오고는 해커에게 보여주지는 않는다. 하지만 어쨌든 1097번 방의 자료를 꺼내왔기에 1097번 방의 정보는 캐시에 들어가 있다. CPU가 RAM을 읽으면 무조건 이 정보는 캐시에 기록되기 때문이다.

이제 해커는 RAM의 1000번 방 부터 하나씩 방을 검색하기 시작한다. 1000번 이후의 모든 방들은 캐시에 없기 때문에, 램에서 읽어와야 하므로 읽는 데 시간이 꽤 오래 걸린다. 하지만 1097번 방은 캐시에 있기 때문에, 읽는 데 시간이 적게 걸린다. 해커는 RAM의 1000번 방 이후의 방을 읽을 때마다 읽는 데 걸린 시간을 측정한다. 1097번 방을 읽을 때 시간이 적게 걸리는 것을 잡아내면, 해커는 CPU가 나한테 보여주지는 않았지만, 실제로는 1097번 방을 읽었다는 것을 알게 된다. 이를 근거로 al에 원래는 97이 들어가야 했다는 것을 알 수 있고 우리가 키보드로 'a'를 쳤다는 것을 알 수 있다.


----------------------------------------------------------------


공격 프로그램은 커널의 특정 메모리 주소를 읽기 위해 다음의 변수 및 배열을 설정한다.

1. ka: 값을 읽어올 커널의 메모리 주소.
2. ua1: L1 캐시 크기 만큼의 배열
3. ua2: 256 크기 만큼의 배열. [20]

코드의 실행순서는 다음과 같다.
A. ka에 원하는 주소를 세팅한다.
B. ua1의 모든 값을 읽는다.
C. ka의 값을 읽어서 레지스터 al에 저장한다.
D. ua2[al]의 값을 읽는다.
E. 아무 것도 하지 않는 명령어를 적당히 깔아둔다.
F. ua2에서 캐시로 값이 들어온 주소를 알아낸다.

자세한 설명은 다음과 같다.

첫째. B에서 ua1의 값을 모두 읽었기에, L1 캐시는 ua1의 정보로 가득 차 있다. 따라서 이 시점에서 ua2의 정보는 캐시에 없다는 것이 보장된다.
둘째. C는 항상 실행이 취소된다. 사용자 프로세스가 커널 정보를 읽는 것이기 때문에 보호비트가 발동된다. 
셋째. C가 실행이 취소되기 전, C, D는 파이프라인의 execute state를 지난다. 즉, CPU는 ua2[al]의 값을 읽는다. 단지 commit 하지 않을 뿐이다. [21]
넷째. 컴퓨터에서 array에 접근할 때에는 보통 간접적인 방식으로 접근한다. C언어에서 tmp_arr[10]이라고 적는 경우를 생각해 보자. 실제로는 tmp_arr이 가리키는 주소에서 10을 더하는 방식으로 주소를 계산한다. ua2[al]을 읽을 때에도 마찬가지로 계산한다.
다섯째. D는 execute state를 지났으므로, CPU는 실제로 ua2[al]을 읽는다. 따라서 이 값이 ua2 배열 중 유일하게 캐시에 올라와 있다. al이 97 즉, 'a'라면 ua2[97]만 캐시에 올라와 있고 나머지는 캐시에 없다.
여섯째. F단계에서 해커는 ua2[0]~ua2[255]까지를 랜덤하게 읽어본다. 읽을 때마다 읽기 시간을 측정한다. 다른 모든 값은 캐시에 없으니 읽는 데 시간이 걸리지만, ua2[97]은 캐시에 올라와 있으니 읽기 시간이 빠르다. 이를 근거로 ka값이 가리키는 주소에 97이 들어있다는 것을 있다. [22][23]
일곱째. E에서 아무 것도 하지 않는 명령어를 적당히 깔아두는 이유는 F가 실행취소되거나 재시도 되는 것을 막기 위함이다.




출처 및 더 자세한 내용: 

https://namu.wiki/w/CPU%EA%B2%8C%EC%9D%B4%ED%8A%B8


https://googleprojectzero.blogspot.kr/2018/01/

https://cyber.wtf/2017/07/28/negative-result-reading-kernel-memory-from-user-mode/


'Study > Etc' 카테고리의 다른 글

vim 에디터 설정  (0) 2018.03.26
디렉토리 브루트포스 (Directory Bruteforce)  (0) 2018.02.09
메모리 구조, 변수  (0) 2017.12.02
Dangling Pointer와 Use-After-Free  (0) 2017.11.30
랜섬웨어 시뮬레이터 RanSim  (0) 2017.11.03
Comments