멜트다운 (Meltdown)

I. Out of order execution, 멜트다운

가. 멜트다운(Meltdown, CVE-2017-5754)의 개념

  • 비순차적 명령어 처리과정에서 특정 응용 프로그램이 내부 메모리에 접근 가능한 CPU 보안 취약점 

나. 멜트다운의 보안 취약점/원인 기술

보안 취약점커널 메모리 접근에 따른 중요 정보 유출
원인 기술파이프라인, 추측 실행, 비순차적 명령어실행

 

II. 멜트다운 공격 코드와 원리

① 커널 메모리 주소[rcx]에 있는 값을 rax 레지스터에 저장
② rax에서 0xc 만큼 시프트 (rax * 4096, rax에 ‘0’ 12개붙임)
③ rbx + (rax * 4096) → rbx에 저장 (L1 캐시에도 저장)
④ 접근속도가 특히 빠른(캐시 저장된) 주소 값 기반 추출
※ 빠른접근 주소 값/4096 = 찾는 커널 메모리 값(data)
  • 일반 프로세스의 Page Table에서도 Kernel 프로세스 사용 가상메모리 주소 메모리 참조 가능

 

III. 멜트다운 대응 방안/영향도

대응 방안영향도
– KPTI(Kernel Page-Table Isolation)
커널이 메모리 맵핑 과정간 Page Table 분리, 타 프로세스 사용불가
– Page Table 분리에 따른 Data 접근 시 Disk I/O 성능 저하 발생
  • 특히 Linux 기반 DB서버에서 가장 많은 성능 저하 발생하므로 CPU 증설 등 보완 필요

[멜트다운의 쉬운이해]

컴퓨터는 모든 것을 숫자로 처리한다. 가령 ASCII코드를 전제할 때 컴퓨터는 ‘a’라는 문자를 97로 이해하고 ‘b’라는 문자를 98로 이해한다. 우리가 키보드로 ‘a’를 칠 때, 컴퓨터는 메모리의 100번째 방에 숫자 ’97’을 적어 넣는다고 치자. 원칙적으로는 OS의 핵심부분인 커널 이외에는 메모리의 100번 방에 무슨 내용이 들어가 있는지 아무도 알 수 없다.[16] 해커는 이 100번째 방의 내용을 노리고자 ‘메모리의 100번째 방을 읽어서 나에게 보내라’고 CPU에게 명령을 내리지만, CPU는 명령을 거부한다. 이게 정상이다. 만약 CPU가 아무에게나 100번째 방의 내용을 보내준다면 가능하다면 비밀번호 등 우리가 키보드로 친 내용들이 유출될 것이다. 그러나 멜트다운 버그를 이용하면 이 100번째 방의 내용을 알 수 있다.
 
100번째 방의 내용을 읽어 내기 위해 해커는 두 개의 명령을 CPU에게 연속해서 전달한다. 첫 번째는 ‘메모리의 100번 방에 있는 내용을 레지스터 rax로 복사해라’ 이며 두 번째는 ‘1000+rax을 계산한 다음 RAM에서 그 방에 있는 숫자를 가져다 줘’이다. 즉 100번 방의 내용 → rbx → 1000+rax을 통해 해커는 100번 방의 내용을 알아내려고 하는 것이다. 만약 1000+rax이 1097이라면, ‘a’가 97인 점을 이용하여 해커는 키보드에서 ‘a’가 입력되었다는 것을 알아낼 수 있다. 1000+rax이 1098이라면 해커는 ‘b’가 입력되었다는 것을 알 수 있다.
 
즉, 해커가 시킨 일을 하기 위해 CPU는 다음의 일을 해야 한다.
① 100번 방에서 숫자를 꺼낸다.
② 100번 방에서 꺼낸 숫자를 레지스터 rax에 임시로 저장한다.
③ rax에 저장된 숫자와 1000을 더한다. (여기에서는 1097로 가정하자)
④ ‘③’에서 더한 결과에 해당하는 RAM의 숫자를 꺼낸다. (즉, 1097번 방 자료 꺼낸다.)
꺼낸 숫자를 해커에게 전달한다.
 
그런데 애당초 100번 방에 있는 숫자를 해커가 꺼내라고 한 1번부터 잘못되어 있다. 숫자를 꺼낸 것 자체가 잘못인데, ②, ③, ④, ⑤번을 할 수가 없다. CPU는 메모리의 100번 방에 있는 내용을 rax로 복사 하지도, 1000+rax을 계산해서 RAM의 방 번호를 찾아 내용을 가져다 주지도 않는다.
 
문제는 CPU의 파이프라인 구조에 있다. 해커가 100번방의 숫자를 꺼내라고 했을 때, CPU는 실제로는 100번 방의 숫자를 꺼낸다. 그리고 RAM의 1097번 방의 숫자도 꺼낸다. 즉, 실제로 CPU는 해커가 시킨 일을 다 한다. 단지 보여주지 않을 뿐이다. 예전까지는 해커한테 보여주지만 않으면 괜찮다고 생각했다. CPU가 일을 다 하고 보여주지만 않으니, CPU가 일한 흔적을 찾아 ‘100번 방의 숫자를 알아내자’라는 것이 멜트다운 버그의 핵심 아이디어이다.
 
해커는 앞서 간단히 언급한 캐시를 이용한다(캐시는 램보다 속도가 훨씬 빠른 메모리이다). CPU가 RAM의 1097번 방에 있는 정보를 꺼낼 때, 1097번 방의 정보는 자동으로 캐시에 기록된다. RAM에 있는 정보를 캐시로 베껴 써 두면 나중에 다시 볼 때 이를 빠르게 볼 수 있기 때문이다. CPU는 해커에게 RAM에서 일껏 1097번 방의 자료를 꺼내 오고는 해커에게 보여주지는 않는다. 하지만 어쨌든 1097번 방의 자료를 꺼내 왔기에 1097번 방의 정보는 캐시에 들어가 있다. CPU가 RAM을 읽으면 무조건 이 정보는 캐시에 기록되기 때문이다.
 
이제 해커는 RAM의 1000번 방부터 하나씩 방을 검색하기 시작한다. 1000번 이후의 모든 방들은 캐시에 없기 때문에, 램에서 읽어와야 하므로 읽는 데 시간이 꽤 오래 걸린다. 하지만 1097번 방은 캐시에 있기 때문에, 읽는 데 시간이 적게 걸린다. 해커는 RAM의 1000번 방 이후의 방을 읽을 때마다 읽는 데 걸린 시간을 측정한다. 1097번 방을 읽을 때 시간이 적게 걸리는 것을 잡아내면, 해커는 CPU가 나에게 보여주지는 않았지만, 실제로는 1097번 방을 읽었다는 것을 알게 된다. 이를 근거로 rax에 원래는 97이 들어가야 했다는 것을 알 수 있고 우리가 키보드로 ‘a’를 쳤다는 것을 알 수 있다.
 
출처:나무위키- https://namu.wiki/w/CPU%EA%B2%8C%EC%9D%B4%ED%8A%B8
출처: http://sata.kr/entry/%EB%B3%B4%EC%95%88-Issue-Meltdown%EB%A9%9C%ED%8A%B8%EB%8B%A4%EC%9A%B4-%EC%B7%A8%EC%95%BD%EC%A0%90%EC%9D%84-%ED%8C%8C%ED%97%A4%EC%B3%90%EB%B3%B4%EC%9E%90-1

 

콘텐츠 사용 시 출처 표기 부탁 드리고, 궁금한 점이나 의견은 댓글 남겨주세요^^