Rowhammer 공격 대응을 위한 ECC 메모리의 효과는? Error-Correcting Code의 실효성 검증

Anna Kim
31 min readFeb 3, 2020

본 포스팅은 하드웨어&보안 SCALAR lab의 권건우 교수님 세미나를 바탕으로 논문 ‘Exploiting Correcting Codes: On the Effectiveness of ECC Memory Against Rowhammer Attacks (Lucian Cojocar 외 저)’를 읽고 이해한 내용을 정리한 글입니다. 하드웨어에 대한 전문적인 지식이 없더라도 읽고 이해할 수 있도록 background를 최대한 쉽게 풀어서 구성해본 후 본문의 전문 용어 의미에 충실한 기술 번역(technical translation)을 하고자 합니다. (본 논문은 세계 보안 4대 학회 중 하나인 IEEE Symposium on Security and Privacy 2019에 선정된 논문입니다.)

오류 수정 코드(ECC) 메모리에서도 과연 로우 해머 공격이 가능할까?

사전지식 (논문을 리뷰하기 전에 알아야 할 용어들을 정리합니다.)

ECC 메모리(오류 수정 코드 메모리)는 DRAM 하드웨어 보안 취약점을 공격하는 Row Hammer에 방어(defense)하기 위해서 등장한 기억 장치의 일부로 이를 이해하기 전에 먼저 rowhammer 공격 방식과 DRAM 구조에 대해 간단히 살펴보겠습니다.

RAM을 쉽게 설명한 영상
  • Rowhammer 공격 방식: DRAM의 cell 밀집도가 높아지면서 하나의 row에 반복적인 접근을 할 때 인접한 메모리 row에 비트 플립(bit-flip)이 발생한다는 하드웨어 설계 결함을 활용한 공격 방식.

공격자가 특정 row에 대하여 hammering(악의적인 반복적인 접근이 마치 망치로 때리는 듯함)을 하게 되면 다른 메모리 유닛에 비트 플립을 발생시키게 되고 이때 공격자는 메모리 열에서 나타나는 비트 플립을 관찰함으로서 가까운 열에 있는 비트의 값을 추론할 수 있게 됩니다. 비트 플립이란 0이여야 할 데이터가 1로 혹은 그 반대로 의도하지 않게 변경되는 메모리 에러입니다. 이는 시스템 권한 상승이나 보안 솔루션인 샌드박스 우회 혹은 웹사이트에서도 운영체제나 시스템에 상관 없이 Javascript를 이용하여 공격이 가능하여 위험성이 큰 공격으로 알려져 있습니다. (재현 예시: google에서 발표한 rowhammer-test) 이 공격은 많은 DDR3나 DDR4 SDRAM 모듈에 영향을 미치는 것으로 알려져 있습니다.

  • DRAM의 구조: 메모리 혹은 기억 장치는 기본적으로 0 또는 1 bit들로 정렬된 2차원 그리드로 구성되어 있습니다. DRAM(Dynamic random-access memory)은 동적인 RAM(임의 접근 기억 장치)로 여기서 동적(dynamic)이란 기억 장치의 내용을 잃어버리지 않기 위해 일정 시간 마다 메모리 내용을 재생시켜야 해서 붙여진 이름입니다. DRAM은 6개의 transistors를 필요로 하는 SRAM과 달리 비트당 하나의 capacitor와 하나의 transistor로 구성됩니다. 이때 DRAM에서 사용하는 축전기(capacitor)는 시간이 지나면서 전자를 누전하게 되는데 기억 장치의 정보를 유지하려면 지속적인 re-read 작업과 전기 공급이 필요합니다. 이러한 전기 공급을 refresh, 즉 재충전 작업이라 하며 일반적인 상황에서 메모리 셀의 전하가 누출되는 문제를 완화시켜주지만 rowhammer 공격을 통해 더 많은 누출이 발생하게 되면 refresh interval에서도 셀의 내용이 변경될 수 있습니다.
Fig1. DRAM cell 배열 구조

Fig1 에서처럼 메모리 셀은 열(columns: bitlines)와 행(rows: wordlines)의 배열로 실리콘 상에 에칭되어 있습니다.

DRAM 관련 용어들

Fig2. Single rank with 8 chips example(Non-ECC Memory)
  • Channel: 메모리와 CPU의 캐시 간에 데이터 전달 통로. 하나의 채널은 64bit 대역폭을 가진다.
  • DIMM(dual in-line memory module): 여러 개의 DRAM 칩을 회로 기판 위에 탑재한 메모리 모듈로 일반 PC부터 노트북 프린터까지 이 메모리 모듈 타입을 사용한다. 기본적으로 64bit data path 폭을 지닌다. 여기서 64bit data path란 한 클럭 사이클 동안 전송되는 데이터 bits의 수가 64bit임을 의미한다.
  • Rank: 여러 개의 칩들이 모여서 메모리의 대역폭이 64bit 가 되면 이를 하나의 랭크라고 부른다. 메모리 칩 한개는 일반적으로 4, 8, 16bit 인데 프로세서와 메모리 사이에서 데이터를 전송할 때 64bit의 대역폭을 채우기 위해선 여러 개의 메모리 칩을 하나로 묶어야 한다. Fig2가 여러 작은 칩들이 모여서 64bit wide data area를 이룬 하나의 랭크(single rank)이다.
  • Chip: 메모리 칩은 쉽게 말해서 정보를 저장할 수 있는 통합된 회로(integrated circuit)이다. 즉 capacitor(전기를 저장하는 역할)와 transitor(전기 스위치와 증폭 작용을 하는 반도체 소자)가 행과 열의 형태로 무수히 많이 결합된 회로로 구성되어 있고 주소를 지정할 수 있는 형식으로 각 메모리 비트를 저장하는 단일 트랜지스터이다. Fig2에서 검은 부품 각각이 하나의 메모리 칩이다.
  • Row/Column: Fig1의 설명 참조.

참고. ECC 메모리의 경우 랭크당 하나의 칩이 더 꼽혀있는데 이는 에러 검출을 위해 추가하는 패리티 비트(parity bit) 때문입니다.

  • ECC 메모리: 외부 환경적 요인의 변화가 DRAM 셀의 capacitor에 충전되어 있는 정도(level)를 변화시키게 되면 값의 오류를 발생 수 있는데 ECC 메모리는 원래 data bit 옆에 추가적인 패리티 비트(parity bit 혹은 control bit)를 더 붙여줌으로서 오류를 탐지할 수 있게 된다. ECC 지원이 되는 DRAM은 하나의 칩이 더 필요하고 따라서 memory bus도 8개의 추가적인 line이 필요하다. (메모리 버스는 간단히 말하면 메인 메모리에서 CPU 간에 데이터나 주소를 전달할 수 있는 통로) ECC 메모리의 경우 전송하고자 하는 데이터 옆에 control bit도 함께 추가해야 하기 때문에 기존의 64bit의 대역폭이 아닌 72bit 버스 대역폭이 필요함.(논문 p.2)

정리

ECC 메모리는 본래 외부적 환경의 요인(우주선 안이나 드물지만 데이터 충돌이 일어나는 등)으로 인해 발생할 수 있는 오류를 감지하고 수정해줄 수 있는 메모리이다. (최대 2 비트의 오류를 감지, 1비트의 오류를 정정 가능)

2014년 로우해머 공격의 위험성이 처음 알려진 후부터 다양한 컴퓨팅 환경(PC, 클라우드, 핸드폰), 다양한 언어(C 바이너리, 브라우저 기반 javascript), 다양한 프로세서(x86, ARM, GPU), 다양한 타켓(페이지 테이블, 암호화키, 객체 포인터, repository URL, 연산코드), 다양한 메모리 타입(DDR3, DDR4)까지 공격이 가능하다는 것이 입증되면서 그 영향력과 위험성에 대한 우려는 커져있는 상황이다.

그러나…

기존의 로우해머 공격은 non-ECC 플랫폼에서만 행해졌으며 대형 클라우드 공급자(아마존 EC2)부터 고가의 소비자 플랫폼, 핸드폰이나 IoT 기기에서 DRAM의 refresh 비율을 줄이기 위한 저전력 제품들까지 ECC 메모리의 사용이 확장되어 가는 추세에서 막연히 로우해머 공격을 막아줄 것이라고 기대했던 이 메모리에 대해서도 검증이 필요한 상황이다. 과연 ECC 메모리는 로우해머 공격을 완화시켜주는 대안책이 맞을까?

FIg3. MacBook Pro retina 2015년형 모델 스펙

이제 ECC 메모리에 대해 살펴볼 사전 준비를 마쳤습니다. 본격적으로 논문 리뷰를 시작하겠습니다.

Abstract

로우 해머 공격의 영향력에 대한 우려가 커짐에 따라 하드웨어 보안 업계가 희망을 건 것은 ECC (에러 수정 코드) 메모리였습니다. ECC 알고리즘이 어떠한 비트 플립도 감지하고 수정해 줄 수 있을 것이라고 기대하면서 로우해머 공격에 대한 방어 역시 해줄 것이라고 믿고 있지만 실효성에 대한 검증은 열려있는 task 입니다. 논문 저자는 2가지 직면한첼린지에 대해 언급합니다.

Main challenges

  1. 상용화된 제품 내의 ECC 구현에 대한 정보는 외부에 공개되어 있지 않다.
  2. 기존의 로우해머 공격은 ECC 메모리 상에서 공격이 어렵다.

저자는 논문 전반에 걸쳐 이 두 가지 과제에 대한 해결책을 제시하고 ECC 메모리가 로우 해머 공격을 막아줄 수 있는지에 대한 실효성을 검증해봅니다.

첫 번째 과제. Intel과 AMD 프로세서의 ECC 메모리 구현 문제 (외부에 공개되지 않음)* Novel approach 제시 *
- custom-made hardware probe + Rowhammer bit flips + cold boot attack을 통한 ECC 알고리즘 리버스 엔지니어링
두 번째 과제. 기존의 로우해머 공격 방식의 한계점 (ECC 메모리에선 공격이 어려움)* 새로운 로우해머 공격 방법 'ECCploit'제시 *- ECC 메모리 컨트롤러 내에서 구성할 수 있고 data-controlled 비트 플립과 새로운 side channel attack 제안

결론부터 말하면 논문에서 ECC 메모리가 로우해머 공격 범위를 축소시켜 주는 것은 맞지만 ECCploit 공격을 이용하면 다양한 시스템과 환경에서 공격이 가능해진다고 저자는 말하고 있습니다.

Fig4. 논문에서 제시한 Challenges 요약

이번 포스팅에선 ECC 알고리즘에 대한 간략한 설명과 Fig4의 C1에 해당하는 Intel과 AMD에서 외부에 공개하고 있지 않는 ECC function에 대한 리버스 엔지니어링에 대해서 다루고 두번째 포스팅에서 C2, C3에 대해 다루겠습니다.

— —여기서부터는 논문 번역에 해당합니다. (translated by Anna Kim) — —

Challenge C1: Reverse Engineering ECC

(p. 4~8 논문 해석/이해) (구체적인 ECC 구현에 대해선 외부에 알려진 바가 없으므로) CPU 제조사에서 사용한 ECC functions에 대한 대략적인 아이디어를 얻기 위해서 우선 기업에서 공개한 특허와 공식 문서를 참고하면서 부족한 부분은 coding theory를 통해 보충하는 방식을 활용하였다.

ECC 시스템이 메모리에 값을 쓸때마다 ECC bits도 쓰게 되는데 예를 들어 ChipKill 구현의 경우 4 ECC nibbles(니블은 1 바이트의 절반으로 4bit를 의미, 따라서 총 16 bits)를 모든 128bits의 데이터마다 쓰게 된다. (참고로 ChipKill은 DRAM 장치에서 멀티 비트 오류를 견딜 수 있는 메모리 시스템 기능을 말함) 구체적인 ECC 니블 계산에 대한 설명은 추후에 하기로 하고(자세한 설명 link) 간단히 살펴보면 첫 번째 ECC nibble은 하나의 데이터셋 nibble에 대해 오류를 탐지해주고 두 번째 역시 다른 셋을 탐지하는 방식이다. 메모리에서 어떤 값에 액세스 할 때 다음 단계에서 ECC 니블을 다시 계산하고 메모리의 ECC 니블로 XOR 비트 연산(두 값의 자릿수를 비교할 때 값이 같으면 0 다르면 1)을 하여 나온 결과가 syndrome이다. 만일 이 syndrome이 0이 아닐 경우 에러가 발생했음을 의미한다. 어느 신드롬이 에러를 가리키는지 살펴봄으로서 칩킬은 오류가 있는 니블의 위치를 알고 이를 고쳐줄 수 있다.

우리가 보게 될 것처럼 수학적 용어인 신드롬의 계산은 (에러 패턴과 함께 transposed (전치)되어 있고 확장된 페리티 검사 행렬에 대하여) 꽤나 복잡한 곱셈을 필요로 하지만, 실제로는 이 multiplication matrix는 이미 테이블의 형태로 계산되어 있고 우리가 할 것은 단순히 AND 와 XOR 연산이다.

추가) ECC functions

(p.3) non-ECC DIMM과의 호환성과 간단함을 위해 메모리 컨트롤러가 control bits와 데이터를 다른 메모리 칩에 저장하는 것이 이상적이다. 이는 시스템상에서 인코딩 하는 과정이 필요한데 즉 메세지는 항상 codeword로 고정되어 있다. (code word란 data bits와 ECC bits의 조합으로 부호어라고 말함)

(여기서부터는 선형대수학의 선행 지식 필요)

메세지 d = (d1, d2, …, dk)를 encode하기 위해선 인코더가 generator matrix G와 multiplication을 한다. (di는 알파벳으로 나타낸 심볼)

ECC function 식 (1)
v: encoded message
G = [Ik|P] 이때 Ik는 단위행렬(identity matrix)이고 P는 parity check matrix
(k rows r columns)

ECC(d)를 d * [0k,k|P]의 결과물에 마지막 r bits라고 할 때 우리는 이를 data d를 위한 ECC bits라고 부른다. 선형대수학의 크로네커 연산(Kronecker function: δi,j = 1 if i = j and δi,j = 0 if i ≠ j)을 사용하면 ECC bits를 다음과 같이 다시 표현할 수 있습니다.

ECC function 식 (2)

Pi,j는 i행 j열인 parity check matrix을 말함. 패리티 검사 행렬의 각 행은 r bit으로 이뤄진 parity value로 표현할 수 있다. (패리티 검사 행렬은 프로세서 제조사에서 공개하고 있지 않다.)

* Coding Theory (코딩이론, 부호화 이론)· channel encoding : 정보를 전송할 때 오류를 줄이고자 한 부호화 기법
- 에러 검출(패리티 검사), 에러 정정
- 블록 부호화(해밍부호, BCH 코드 등) -> 생성 행렬에 의함
· 페리티 검사 행렬(parity check matrix): 선형 블록 부호에서 주어진 부호어가 유효 부호어인지 검출할 수 있는 행렬
· code word(부호어): 전송, 압축을 위한 부호화 알고리즘에 의해 생성된 워드(심볼들의 시퀀스)
· 부호화(코딩): 심볼과 부호어 간의 대응 관계
· linear code(선형 부호): 부호어 집합이 선형 벡터공간을 형성하는 부호
Fig5. ECC memory

(다시 본문) 핵심은 알려진 에러 패턴에 대해서 신드롬을 갖고 있다면 역연산을 통해 패리티 검사 행렬을 얻을 수 있고 따라서 ECC function에 대해 알 수 있다는 것이다.

이를 위하여 저자는 인위적으로 메모리에 싱글 비트 에러를 발생시켜 현상을 관찰하고, 신드롬을 추정한 다음, cold boot 공격을 통해 ECC 비트를 복구하는 방식을 활용하였다. (cold boot attack은 platform reset attack이라고도 하는데 공격자가 물리적 접근을 하는 RAM에서 타깃 머신을 리셋함으로서 메모리 덤프를 하는 것) 공격 타깃은 다음과 같다.

FIg6. reverse engineer the ECC functions of common CPU

A. Theoretical foundation

해밍부호와 BCH 코드 모두 다항식 부호(polynomial code)이다.다항식 부호는 갈로아 유한체(Galois Field(GF))에서 덧셈 대신 exclusive-or을, 곱셈 대신 and 연산을 사용할 수 있기 때문에 (비트 연산으로) 하드웨어 상에서 구현이 쉽니다.

제안1. ECC function을 복구할 수 있는 방법으로 모든 ECC-word마다 정확히 하나의 데이터 비트를 확고히(asserted) 함으로서 ECC value를 찾을 수 있다.

패리티 검사 행렬의 각 행은 r bit 숫자로 표현될 수 있으며 parity value라고 부른다. 식(2)에서 s 위치에 삽입된 데이터 워드 (d)의 ECC 값은 각각의 데이터 워드(d’) (->패리티 비트가 삽입된 데이터 워드)의 패리티 값에 ∀i ∈ {s|ds = 1}에 대하여 하나의 d’i가 추가된 exclusive-or 연산으로 표현할 수 있다. (이부분은 이해가 안됨)

수신한 v’= (v1, v2, · · · , vk+r) 코드워드에 대해 에러를 검출하고 수정하려면 linear code는 syndrome decoding이라는 효과적인 테크닉을 활용한다. 신드롬은 다음과 같이 계산한다.

제안2. 특정 위치에 싱글 비트가 추가된 데이터 워드의 ECC 값은 그 특정 위치의 비트가 잘못 되었을 경우 얻어진 신드롬과 같다. 에러 e = (e1, e2, · · · , ek+r)가 e ≠01,k+r, v’= v +e이고 S(v) = 0이므로 신드롬을 다음과 같이 다시 나타낼 수 있다.

ECC function 식 (3)

이때 SYND(v’) = (e1, e2, … ek) * -P를 ‘데이터 비트에만 에러를 추가했을 때 얻어지는 신드롬'이라고 표시하자. 크로네커 연산을 사용하여 오류로 얻어진 신드롬을 다시 다음과 같이 나타낼 수 있다.

ECC function (4)

모든 연산은 binary 갈루아체(Galois field)에서 이뤄지며 코드는 순환되고 ‘-’는 아무 의미가 없다. 따라서 식(4)와 (2)에서 ei = di를 선택함으로서 우리는 아래와 같은 식을 얻는다. 간결함을 위해 우리는 ei를 가장 많이 플립된 한 비트로 선정한다.

ECC function (5)

공격자가 피해자와 같은 시스템에 접근했다고 가정할 때 우리는 어떻게 제안 1과 2를 통해 공격자가 인위적으로 오류를 더하고(inject fault) cold boot attack을 통해 리버스 엔지니어링을 하면 패리티 행렬의 구성(contents)과 어떤 DRAM 버스 라인과 출력(output) 데이터가 매핑 되는지 제시하겠다. 주의할 점은 공격자는 이런 과정을 단 한번만 시행하며 동일한 CPU 모델을 사용하는 피해자 시스템에서 복구된 정보를 재활용해야 한다는 점이다.피해자 시스템의 CPU 모델에 대한 정보는 cpuid라는 소스를 통해 확인이 가능하다.

B. Fault Injection

이번 섹션에서는 어떻게 우리만의 통제된 방식(controlled way)으로 첨가한 특정한 에러의 신드롬만으로 딱 하나의 비트만 flip 시키고 이를 이용해 모든 신드롬과 나아가 ECC function까지 알아낼 수 있는지 설명한다. 우선은 ECC 엔진이 에러를 수정하면 공격자가 그 특정 에러에 대한 신드롬을 파악할 수 있다고 가정한다. 이후에 이 가정은 느슨해질 것이다. 공격의 메인 키 포인트는 다음과 같다.

만일 우리가 반복적으로 하나의 비트를 ECC 워드의 가능한 모든 비트 포지션에 대해 flip한다면 그 특정 비트 포지션에 해당하는 신드롬을 모두 얻을 수 있을 것이고 따라서 ECC function을 복구하는 것은 간단한 문제가 된다. (식(5))

예를 들어 bit i와 j가 추가된 ECC word의 ECC 값은 1 또는 0 비트가 i 위치에서 flipped 되고 j 위치에서 flipped 된 신드롬들 간의 XOR 연산의 결과이다. 신드롬을 복구하기 위해선 우리는 원하는 비트 포지션에서 bit flip을 일으키는데 다음과 같은 3가지 오류 첨가 메커니즘(fault injection mechanisms) 중 하나를 이용하여 실현한다.

fault injection mechanisms are…

  1. 커스텀 shunt probe (shunt:선로를 바꾸다)
  2. 메모리 컨트롤러가 제공하는 특수 기능
  3. 로우 해머 공격으로 bit flip
Fig7. DDR3 구멍 핀 배치도 / 주사기 바늘로 오류 첨가

(참고)

-DQx: Data In or Out (DQ pins는 다른 말로 Input/Output pin이라고 함) 쓰기 연산에서 voltage(high=1, low=0)은 DQ에 첨가되고 이러한 voltage는 적합한 시그널로 변환되어 선택된 메모리 셀에 저장됨-Vss: (-)접지, ground, source에 연결되는 전원
Schematic diagram of CMOS Inverter

B-1. Error injection with a shunt probe

(첫 번째 오류 첨가 메커니즘은 저자가 개발한 shunt probe라는 장치를 통해 인위적으로 에러를 주입하는 방식이다.) 빠른 속도의 시그널 간 발생하는 노이즈와 혼선을 줄이기 위해 DDR DIMM의 데이터 핀(DQx)는 물리적으로 ground(Vss) 시그널 옆에 배치된다. 기평면(ground plane)이 데이터 시그널에 비해 비교적 매우 낮은 impedance(교류 회로에서 전압과 전류의 비)를 갖고 시그널 드라이버는 (가짜로) 열린 drain이기 때문에 Vss와 DQx 시그널간의 합선(short-circuiting)는 DQx의 높은 전압 레벨을 0으로 끌어내릴 것이다. 높은 전압의 인코딩에 따라 이러한 합선은 1을 0으로 혹은 0을 1로 bit flip을 주어진 DQx line에서 일으키게 된다.

Fig7의 1은 중요 시그널의 위치를 나타냄과 동시에 DQx 시그널이 항상 Vss 시그널 옆에 위치함을 보여준다. 따라서 하나의 고칠 수 있는 비트 에러를 집어넣기 위해선 시스템 메모리가 메모리의 모든 부분을 읽고 쓰면서 움직이는(exercises the memory) 동안에 우리는 DQx 시그널을 Vss와 합선해야 한다. 우리는 직접 커스텀 빌드 한 shunt probe라는 장치를 통해서 합선(short-circuit) 효과를 낼 수 있었다. (Fig7의 (a)) 우리는 DIMM 소켓의 구멍에 probe을 넣어줬다. (Fig7의 (b)) 또한 핀셋을 활용하여 두 바늘을 통해 합선하면서 생기는 에러를 넣어주는 타이밍을 조절하였고 따라서 DQx와 근처에 있는 Vss 시그널을 타킷하엿다. 이러한 방식은 간단하고 저렴할 뿐만 아니라 메모리 컨트롤러가 싱글 메모리 transaction의 ECC를 계산할 때 (ECC word 크기는 64bit) 효과적이고 특수목적을 위해 제작된 비싼 장비를 대체할 수 있다.

(일부 시스템에서 2개의 비트 에러를 반영할 경우 해결책 제안) 일부 AMD-1같은 시스템에서는 데이터가 두 개의 메모리 트랜젝션에서 얻어진 후에 넣어지게 된다. shunt probe 방식의 낮은 일시적 정확도 때문에 데이터 비트 2*k에서 나타나는 DQk (0≤k<64) 메모리 라인에 삽입시킨 에러는 128 비트 ECC 워드 안의 2*k+1 데이터 비트도 함께 나타내게(reflect) 된다. 이러한 경우 신드롬은 2개의 bit error와 일치하기 때문에 제안1에 위배된다. 오직 한개의 비트 에러를 보장하기 위해선 interleaved된 메커니즘이 이해되는 순간 움직이는(exercising) 데이터가 구성될 수 있으므로(can be constructed) reflection을 마스킹 하는 작업을 통해 reflected 포지션(두 비트를 반영하는 위치)이 오직 낮은 전압으로 인코드 된 하나의 비트만을 담을 수 있게 된다.

B-2. Error injection with memory controller

일부 서버 수준 프로세서는 메모리 컨트롤러의 기능으로 인위적으로 메모리에 에러를 주입시킬 수 있는 기능을 함께 제공하기도 한다. 이러한 메커니즘은 소프트웨어 스택의 에러 리포팅의 기능성을 테스트하는데 유용하다. 에러 주입 기능은 PCI 레지스터를 통해 드러나있지만 OEM은 이러한 리소스를 펌웨어로부터 잠글 수 있도록 선택할 수 있다. 게다가 어디에 에러를 넣고 어떤 에러를 주입시킬지 선정하는 방법은 플랫폼에 따라 다르다. 예를 들어 어떤 시스템(AMD-1)에선 그 다음의 uncached memory access에 에러를 넣는 반면 다른 시스템(Intel-1)은 주소가 구체적으로 지정된 위치에 에러를 넣는 방식이다.

B-3. Error injection with Rowhammer

또 다른 에러를 집어넣을 수 있는 방법으로는 메모리 컨트롤러의 에러 주입 기능을 지원하지 않는 경우 로우해머 방식을 통해서 bit flip을 일으킬 수 있다. 주의할 점은 이러한 로우해머 공격 방식은 신드롬을 검출하기 위한 방법은 전혀 아닐 뿐더러 ECC를 우회할 수도 없다. 공격을 받게 되는 agressor-victim 행이 검출되어도 (ECC 에러 카운터를 보거나 나중에 설명할 부채널을 이용함으로서) 공격자는 여전히 bit flip 이 일어날 위치를 알 수 없다. 하지만 우리는 나중에 보게 되겠지만 공격을 받기 쉬운(vulnerable) 비트를 그것이 flip 될 값으로 다시 덮어 씀으로서(overwrite) 로우해머 공격으로부터 비트 플립이 일어나는 것을 멈출 수 있다. 따라서 비트가 가려질 경우(masked) 어떠한 에러도 검출되지 않게 된다. 우리는 여기서 이러한 속성을 적극 활용하여(leverage) 비트 플립이 일어날 위치를 이진 탐색을 수행하는데 활용할 수 있게 된다. 이 방식의 한가지 문제점은 ECC-word 크기의 가능한 모든 비트 플립이 일어날 수 있는 위치를 전부 찾아내는 것이다. 반면에 한번 공격자가 취약한 DIMM(s)의 set을 알게 되면 그들은 이러한 DIMM을 활용하여 어떠한 타깃도 리버스 엔지니어 할 수 있다.

C. Dealing with lack of syndromes

어떠한 시스템에서는 모든 에러 핸들링 스택은 소프트웨어에 노출되어 있고 드라이버가 충분히 ECC 에러가 발생할 때 신드롬을 보고하는 방식이다. 반면 다른 일부 시스템은 언제나 정확하게 신드롬을 보고하지 않는 경우도 있으며(Intel-1) 또 다른 시스템에선 신드롬이 전체적으로 부족한 경우도 있다. (Intel-2, Intel-3) 우리는 Intel-1에 대해선 신드롬을 읽을 수 있는 우리만의 드라이버를 개발하였고 Intel-2와 Intel-3에 대해선 이용가능한 에러 카운터(이 역시 드라이버를 개발하였다)를 활용하여 제안1을 활용하여 ECC function을 리버스 엔지니어 할 수 있었다.

D. Cold boot attack

Cold boot attack(해킹 기법 중 갑자기 컴퓨터 전원이 내려갔을 때 재빨리 컴퓨터를 분해하여 RAM 부분을 액화질소 스프레이 등으로 얼린 후에 다른 컴퓨터로 RAM을 읽어서 램상에 올려진 내용을 분석하는 해킹 기법)은 기존에는 프라이버시를 위반(breach)하고 메모리 컨트롤러에서 수행된 데이터 scrambling을 리버스 엔지니어 하여 활용한 방식인데 크게 3가지 방식으로 구성된다. (1) 흥미로운 데이터가 메모리에 적혀있음 (2) 데이터를 보여한 DDR 모듈의 온도가 높은 반면 메모리의 온도가 낮아짐 (3) 재부팅 이후에 DIMM을 제거하고 즉시 다른 기계에 옮긴 후 부팅함으로서 메모리는 다시 읽혀질 수 있다.

ECC 비트를 읽기 위해선 공격자는 cold boot 공격방식을 활용할 수 있는데 (1)과 (2)의 방식은 기존의 cold boot 방식과 유사하다. 하지만 ECC 비트가 메모리 컨트롤러에 의해 드러나 있지 않으므로 우리는 곧바로 (3)과정을 활용할 순 없다. 우리는 커스텀된 FPGA 기반 메모리 컨트롤러를 사용하여 ECC control bit 를 읽고자 한다. 비록 보편적인 DIMMs를 위한 솔루션이 존재하긴 하지만 우리는 기성품 motherboad를 사용하여 미리 복구하고 ECC function을 식별해놓은 CPU 조합을 활용하는 방식을 택하였다. 다음과 같은 사실을 알고 있는 상황에서 (1. 데이터가 쓰여짐 2. cold boot 직후 우리가 읽은 데이터 3. 기대한 ECC 값 4. 관찰된 신드롬) 우리는 특정 데이터 패턴을 통해 피해자 시스템에 저장된 ECC 값을 재구성할 수 있다.

한가지 챌린지는 ECC 메모리는 일반적으로 타킷 시스템 상에서 잘못된(spurious) ECC 에러를 피하기 위해 메모리에 접근할 때 보통 부팅 시간에 초기화된다. 이러한 초기화는 주로 firmware(BIOS) (펌웨어란 특정 하드웨어 장치에 포함된 소프트웨어로 소프트웨어를 읽어 실행하거나 수정되는 것도 가능한 장치임)를 통해 수행되고 우리의 cold boot 공격을 어렵게 만든다. 우리의 목적을 달성하기 위해선 메모리 초기화를 리버스 엔지니어링을 통해 우회하였고 DRAM 초기화 시 실행되는 일부 바이너리 BIOS 코드를 수정하였다. 이러한 패치를 오픈소스로 공개하였으며 제너릭 ECC 메모리 덤퍼를 만들 수 있도록 세부사항도 함께 적어놓았다.

E. Reverse engineering approach

Fig8. pros and cons of author’s available reverse engineering mechanisms

Fig8은 우리의 가능한 리버스 엔지니어 메커니즘의 장단점을 정리한 표이다. 우리는 Fig6에서 제시한 머신들에서 ECC functions을 이러한 메커니즘을 통해 시행해본 후 결과를 비교해보았다. (아래부터는 실험 결과이므로 key point만 요약)

E-1. Machine AMD-1

  • 데이터 시트가 ECC 에러의 위치를 알아낼 수 있도록 신드롬 디코딩 기술 포함
  • 신드롬 테이블을 통해 전체적인 ECC function 복구함
  • shunt probe를 활용해서 ECC function이 데이터 비트를 DRAM pins로 매핑한다는 사실을 확인함
  • 결론은 AMD-1은 정확하기 에러를 리포팅하고 더 나아가 DRAM pins에 매핑된 데이터 비트를 찾아냄 (나중에 cold boot attack에 유용)
  • 신형 버전의 AMD-1 CPU모델에서 에러 injection을 지원하는데 드라이버로 에러를 넣고 확인해본 결과 이는 사실로 밝혀짐

E-2. Machine Intel-1

  • ECC function은 문서화되어 있지 않음
  • 드라이버 상에서 에러 주입 쓰기 (writing error injection)을 지원하지 않기 때문에 로우 해머 공격으로 비트 플립을 일으키는 방식을 채택
  • Intel-1의 데이터 시트(부품, 하부시스템, 소프트웨어 등의 속성, 특성을 모아놓은 문서)에서 ECC error 카운터랑 ECC error의 신드롬 명시하고 있음
  • 사전에 공격 받을 수 있는 bits와 DIMMs에 관한 데이터베이스를 만들어놓고 저자가 개발한 사이드 채널 공격을 통해 ECC 유닛이 비트 플립을 수정해주는지 정보를 빼냄
  • vulnerable bit 위치의 신드롬 찾아냄 (복구를 위해 DIMMs 중 3개만 필요했음)
  • shunt probe를 통해 검증해보고 메모리 컨트롤러가 DIMMs으 여러 data pin들에 전송할 때 셔플한다는 사실도 알아냄

E-3. Machines Intel-2 and Intel-3

  • 가장 문서가 생소했지만 데이터시트에서 ECC가 64bit의 정보를 한번에 생성한다는 사실을 언급하고 있음
  • shunt probe로 확인해본 결과 이 시스템들의 소프트웨어 스택은 ECC 에러를 리포팅하지 않는다는 사실을 알아냄
  • 우리는 이미 알아낸 AMD-1의 ECC function을 토대로 cold boot attack의 마지막 공격방식을 활용
  • 결론적으로 복구해본 ECC functions는 몇가지 부정확한 케이스도 있었음

F. Results

실험의 결론을 얘기하면 AMD-1과 Intel은 트렌드를 대표하기도 하고 Intel-2와 Intel-3에선 몇가지 에러 사항이 있었으므로 논문의 뒷부분부터는 전의 두 시스템의 ECC functions에 집중하고자 한다.

F-1. Ideal guarantees

  • 이상적인 설정으로는 수정가능한 에러는 검출되고 수정될 수 있어야 하며 수정될 수 없는 에러는 프로세스나 시스템 충돌로 발생한 것이여야 함
  • 이러한 설정을 위해선 공격자는 시스템 충돌을 일으키지 않을 정도로의 양만 올바른 위치에 비트 플립을 일으켜야 함
Fig 9. minimum number of bit flips
  • Fig 9는 데이터 비트(dmin(data)) 혹은 데이터 비트 더하기 컨트롤 비트(dmin(cw))에서 최소 필요한 비트 플립을 의미
  • 이정도의 비트 플립을 일으키는 것은 로우해머 공격에 취약한 대부분의 DIMMs에서 어렵지만 Intel-1에선 가능

F-2. State of practice

Fig 9
  • Fig 9에서 Intel-1에서 시스템 충돌로 발생하지 않은 수정할 수 없는 에러가 발생했지만 OS에 리포트 되지 않은 사실을 발견
  • 이유는 추정해보건데 OS에서 메모리 컨트롤러의 부적절한 소프트에어 지원 때문일듯(에러 리포팅 드라이머가 이를 인지하지 못하므로 에러 리포팅 메커니즘의 자원을 초기화하지 않음)
  • 결론적으로 공격자는 시스템을 공격하는데 더 유리하다 (기본 설정에서 더 적은 숫자의 비트 플립이 이상적으로 보장되어 제공되는 ECC function보다 낮기 때문)

F-3. Exploitable patterns

Fig 10
  • AMD-1과 Intel-1의 ECC funtion에서 착취 가능한 패턴을 캐기 위해 Z3 (constraint solver)를 사용
  • Fig10은 이상적/기본 설정 보여줌 (AMD-1은 컨트롤 비트[P1] 중 하나의 비트 플립이 일어나 면16바이트마다 최소 3 비트 플립 필요)
  • 데이터 비트 하나만 타깃하려면 ECC word 내 최소 두개의 구별된 심볼에서 비트 플립 시켜야함
  • Intel-1은 (원래는 8 바이트마다 최소 두 구별된 심볼에서 네개의 비트 플립을 찾아내야 하지만) ECC 워드에서 다른 심볼 안에서 오직 두개의 비트 플립만으로 시스템 착취 가능

F-4. Exploitable ECC DIMMs

  • 서로 다른 DRAM 칩 제조사에서 네개의 ECC DIMMs 주문함
Fig 11
  • Fig 11 aggressor-victim-rows 109k 짝(pairs)에 대해 비트 플립 일으킨 결과
Fig 12
  • Fig12는 Fig10 에서 논의된 패턴을 탈출하기에 충분한 비트 플립이 있는 행의 백분율

F-5. Other DIMMs

  • Fig 12는 Tatar et al.에 의해 공개 된 비트 플립의 공개 데이터베이스
  • ECC DIMM 칩 종류가있는 14 개의 데스크탑 DIMM 포함
  • 모든 DIMM은 하나는 ECC가 수정할 수없는 비트 플립을 나타내고 10은 ECC 알고리즘이 잠재적으로 수정할 수없는 손상
  • ECC 감지가 올바르게 사용 된 경우 ([P1], [P2] 및 [P3]), 모든 비트 플립의 0.65 % -7.42 %가 여전히 조용하게 변질 일으킴
  • 기본 구성 ([P4])에서 비트 플립의 평균 10.89 %까지는 수정할 수 없음

— — — — — — — — — — — — — — — — — — — — — — — — — — — — — — —

이제 p 1~8까지의 리뷰를 마쳤습니다. Section 2에서 나머지 ECC-aware 로우해머 공격과 실질적인 ECCploit에 대해 다루겠습니다.

추가)

Memory controller chip

요약: CPU가 physical address를 활용하여 메모리에 저장된 정보에 access 하는 과정은 CPU가 직접 하지 않고 MMC(memory controller chip)라는 보조 회로에서 처리된다. MCC에는 메인 메모리에 데이터를 읽고 쓸 수 있는 logic이 들어있고 이전엔 메인보드의 northbridge에서 회로 설계를 했다면 현재는 CPU에 통합되어 있다.

(간략한 순서) 1. CPU와 메모리 컨트롤러는 주소와 외부 데이터 버스로 연결되어 있음 -> 2. 정보가 필요하면 CPU는 메모리 컨트롤러에 요청(DRAM에 데이터 저장된 위치 정보 포함) -> 3. DRAM에 multiplexer로 연결된 메모리 컨트롤는 정보를 가져와 CPU에 보냄

이외에도 power refreshment 조절(저장된 정보를 잃지 않고 지속적으로 유지하려면 전기 계속 공급해줘야), 어떤 메모리 컨트롤러는 cold boot attack으로부터 민감한 정보 보호를 위해 memory scrambling를 하는 등 메모리 관리에서 중요한 역할

Intel ECC memory value

ECCploit update

Reference

--

--