파일 다운로드 - HNS | Hacking and Security

최초 작성일: 2015-03-12 / 최종 수정일: 2015-03-17
Rowhammer Bug
2015.03.17
최초 작성일: 2015-03-12 / 최종 수정일: 2015-03-17
차례
1. 개요 ................................................................................................................................3
2. 주요 내용 .........................................................................................................................3
(1) rowhammer란? ........................................................................................................3
(2) bit flip 발생시키기 ......................................................................................................3
3. PoC 테스트 .....................................................................................................................4
(1) NaCl escape............................................................................................................4
(2) Kernel privilege escalation ......................................................................................5
(3) 테스트 결과................................................................................................................7
4. 취약 여부 테스트 .............................................................................................................15
(1) Rowhammer-test ...................................................................................................15
(2) Rowhammer detective ..........................................................................................17
5. 향후 전망 .......................................................................................................................17
6. 관련 자료 ......................................................................................................................18
rowhammer
1. 개요
메모리 내의 비트가 변화하는 bit-flip 현상은 우주선(cosmic ray), 방사선(radioactive ray), 전압저하
(Lowering voltage) 등 여러 원인으로 인해 의도치 않은 상황에서도 발생하는 것으로 알려져 있다. 카네
기멜론 대학의 김윤구, Ross Daly 등은 논문에서 DRAM 메모리의 row에 access를 반복함으로써 인접한
row에 bit flip을 일으킬 수 있다고 발표했다. Google Project Zero 팀은 이 논문의 내용을 이용하여
NaCl sandbox escape, kernel 권한 상승에 대한 PoC(proof of concept) 코드를 발표함으로써 bit-flip
이 실제공격에 활용될 수 있음을 보였다.
소프트웨어적인 입력으로 하드웨어적 에러를 일으켜 다시 소프트웨어적인 공격을 가능하게 한다는 점에
서 rowhammer는 공격에 대한 새로운 접근을 시도하고 있다고 할 수 있다. 그러므로 rowhammer attack
은 앞으로 다양하게 나타날 하드웨어+소프트웨어 공격의 시발점으로 중요하게 생각된다.
* 이 문서에서는 Google Project Zero팀의 문서를 기반으로 해당 공격에 대해서 논의한다.
2. 주요 내용
(1) rowhammer란?
DRAM(Dynamic random-access memory)은 메모리의 각 비트가 작은 콘덴서로 이루어져 있다. 콘덴
서에 전류가 충전되어있는가 아닌가에 따라 1, 0으로 데이터를 표시한다. 기술이 발전함에 따라 DRAM이
의 cell 밀집도가 높아지면서 한 row에 대해 반복적인 접근했을 때 인접한 행들에서 bit flip이 일어날 수
있음이 알려져 있다. 좁은 공간에 cell들을 넣음으로써 charge leak의 영향이 일어나기 쉬워졌고, 하나의
row address에 반복적으로 ACTIVATED/ Refreshed 명령(아래에서 설명)을 내리면 인접 row에 bit-flip
이 일어난다는 것이다. 하나의 row를 ‘hammered’함으로써 일어나는 문제라는 것에 착안해 해당 결함에
는 rowhammer라는 이름이 붙여졌다.
(2) bit flip 발생시키기
카네기멜론 대학의 김윤구 등이 작성한 논문1에 따르면 DRAM의 같은 메모리 주소를 약 100,000번 반
복적으로 접근하면 인접한 다른 메모리 위치에 bit flip을 일으킬 수 있다고 한다.
1
Yoongu Kim, Ross Daly “Flipping Bits in Memory Without Accessing Them: An Experimental Study of
DRAM Disturbance Errors”
3/18
rowhammer
해당 논문에서는 아래와 같은 코드를 이용하여 bit flip을 일으켰다.
code1a:
mov (X), %eax // Read from
mov (Y), %ebx // Read from
clflush (X) // Flush cache
clflush (Y) // Flush cache
jmp code1a
address X
address Y
for address X
for address Y
bit flip을 일으키기 위해서 mov로 eax, ebx에 (X, Y)값을 읽고 Clflush로 x, y를 캐쉬에서 지우는 과정을
반복하면 bit flip이 일어난다는 것이다. 단 이때 X와 Y는 같은 bank의 다른 row이어야 row-buffer에서
값을 읽어오면서 발생하는 activate(decharging-recharging)2과정이 일어날 수 있다. 또한 CPU 캐쉬에
서 읽어오는 것을 막기 위해 CLFLUSH 인스트럭션을 사용해서 캐쉬에서 지워주어야 한다.
3. PoC 테스트
Google Project Zero팀은 rowhammer에 대해서 연구결과로 두가지 PoC exploit을 내놓았다. 해당 코드
들은 x86-64 리눅스 환경에서만 동작한다. 두가지 공격은 공통적으로 bit-flip을 발생시키기 위해 x86
CLFLUSH 인스트럭션을 이용하고 있으나 추가 연구에 따라 이외의 공격법이 나타날 것으로 예상된다.
본 문서에서는 두가지 PoC 코드 중 Kernel Privilege escalation에 대한 테스트 결과를 보인다.
(1) NaCl escape
Native client(NaCl)은 하드웨어의 예외에 대해서는 지원하지 않고 있어 bit-flip을 이용한 공격이 가능하
다. Google의 exploit은 아래의 sandboxed indirect jump를 위한 명령어 시퀀스를 타겟으로 한다.
andl $~31, %eax // Truncate address to 32 bits and mask to be 32-byte-aligned.
addq %r15, %rax // Add %r15, the sandbox base address.
jmp *%rax // Indirect jump.
레지스터 넘버를 수정하는 bit flip을 이용한다(추후 연구에 따라 opcode 변경도 가능할 것으로 예상). 예
를 들어 jmp *%rax의 bit를 1에서 0으로 flip시킨다면 제한되어 있지 않으므로 어떤 주소로 점프가 가능
2
메모리로의 접근은 row에서 칩의 row buffer로의 데이터 전송(이 과정에서 row cell은 discharge), row buffer
의 내용을 읽고 쓰고 cell로 복사해오는 과정(이 과정에서 recharge)이 포함된다. 이러한 activating(dischargerecharge )과정이 인접한 row의 auto refresh동안(보통 64ms마다) 충분한 숫자만큼 행해지면 bit flip이 일어날
수 있다. 그런데 X와 Y가 같은 row에 있다면 row buffer에서 읽어들이기만 할 뿐 activating이 일어나진 않는다.
4/18
rowhammer
하고 일단 프로그램이 점프하게 되면 안전하지 않은 명령을 감출 수 있는 것이므로 sandbox에서 빠져나
올 수 있게 된다.
이를 위해 NaCl의 dyncode_create() API를 이용하여 sandbox의 동적코드 영역을 250MB의 indirect
jump 명령 시퀀스로 채워넣는다. 그리고 CLFLUSH를 이용하여 동적코드 영역에 rowhammer를 일으키
고 공략가능한 bit-flip이 일어났을 때 쉘코드로 점프시키는데 이용하고 공략이 힘든 bit-flip의 경우는 무
시하는 loop를 돌린다.
(2) Kernel privilege escalation
Google Project Zero측이 제시한 공격방법은 bit flip을 이용하여 PTE(page table entry)를 수정함으로
써 kernel 권한을 상승시킨다. 이때 flip할 bit를 완벽하게 컨트롤 할 수 없기 때문에 memory spray 개념
을 사용한다. mmap()을 이용하여 하나의 파일에 대한 다수의 page table을 물리 메모리에 뿌려놓는다.
Page table은 프로세스마다 하나이며 RAM에 상주하므로 반복해서 mmap()으로 다수의 page table을
올린다면 bit-flip으로 수정된 PTE가 유효한 페이지를 가리킬 가능성이 높아질 것이다.
공격은 크게 다음과 같은 절차로 이루어진다.
• 유용한 bit-flip을 일으키는 어드레스 찾기3
• 메모리에 page table spray
• rowhammer
• 수정된 PTE가 공격가능한지 확인
• page table 수정
해당 코드에서 bit-flip을 만들어내는 것 역시 CLFLUSH를 이용했다. 현재 커널단에서 CLFLUSH를 가로
채거나 사용하지 못하게 하는 것이 불가능하다. VMX를 사용하면 WBINVD, CPUID 등 많은 인스트럭션
을 가로챌 수 있으나 CLFLUSH는 그것이 불가능하다고 알려져 있다.
3
bit-flip은 발생한 곳에서 반복되는 경향이 있다
5/18
rowhammer
1) 테스트 과정 : Kali-linux 1.10 + DDR3 DRAM(아래 그림 참고) + kernel(3.19.1)
2) PoC 수정
- exploitdb에 올라온 PoC는 컴파일이 되지 않는 문제가 있다. 아래와 같은 방법으로 컴파일 가능하다.
•파일이름 : privesc.cp -> privesc.cc
•매크로 설정(privesc.cc ) : #define __STDC_FORMAT_MACROS 추가
- 아래와 같은 오류들이 나올 수 있다.
/usr/bin/ld: cannot find -lstdc++ : apt-get install g++-multilib로 해결
3) 추가 설정
- qemu 설치
# apt-get install qemu-system
- 커널 bzImage 컴파일
# kernel.org에서 커널 소스파일 다운로드
6/18
rowhammer
/usr/src에 압축을 푼 후
# make mrproper
# make menuconfig —> kernel hacking에서 /dev/mem에 대한 필터 disable
# make
# make module
# mv bzImage /PoC 코드 디렉토리
# ./run.sh (qemu 환경에서 테스트이므로 root 권한으로 실행되어야 한다)
(3) 테스트 결과
PoC 코드는 qemu 가상머신 환경에서 “Hello world -- in innocent program”를 출력하는 단순한 프로
그램을 대상으로 테스트한다. payload에는 write와 exit만 존재하는 PoC 코드이다. 실제 exploit에서는
write, exit가 아닌 execve 등 실행함수를, 단순한 프로그램이 아닌 root권한의 SetUID 프로그램을 공략
하게될 것이다. 공격에 성공하면 최종적으로는 일어났던 bit-flip을 되돌려준다(Cleaning up).
root@kali:~/Downloads/36310# ./run.sh
3242 blocks
use_kvm=True
[
0.000000] Initializing cgroup subsys cpuset
[
0.000000] Initializing cgroup subsys cpu
[
0.000000] Initializing cgroup subsys cpuacct
[
0.000000] Linux version 3.19.1 (root@kali) (gcc version 4.7.2 (Debian
4.7.2-5) ) #1 SMP Mon Mar 16 21:21:56 PDT 2015
[
0.000000] Command line: console=ttyS0
[
0.000000] e820: BIOS-provided physical RAM map:
[
0.000000] BIOS-e820: [mem 0x0000000000000000-0x000000000009fbff] usable
[
0.000000] BIOS-e820: [mem 0x000000000009fc00-0x000000000009ffff] reserved
[
0.000000] BIOS-e820: [mem 0x00000000000f0000-0x00000000000fffff] reserved
[
0.000000] BIOS-e820: [mem 0x0000000000100000-0x00000000dfffdfff] usable
[
0.000000] BIOS-e820: [mem 0x00000000dfffe000-0x00000000dfffffff] reserved
[
0.000000] BIOS-e820: [mem 0x00000000feffc000-0x00000000feffffff] reserved
[
0.000000] BIOS-e820: [mem 0x00000000fffc0000-0x00000000ffffffff] reserved
[
0.000000] BIOS-e820: [mem 0x0000000100000000-0x0000000119ffffff] usable
[
0.000000] NX (Execute Disable) protection: active
[
0.000000] SMBIOS 2.4 present.
[
0.000000] Hypervisor detected: KVM
[
0.000000] AGP: No AGP bridge found
[
0.000000] e820: last_pfn = 0x11a000 max_arch_pfn = 0x400000000
[
0.000000] PAT not supported by CPU.
[
0.000000] e820: last_pfn = 0xdfffe max_arch_pfn = 0x400000000
[
0.000000] found SMP MP-table at [mem 0x000f1820-0x000f182f] mapped at
[ffff8800000f1820]
[
0.000000] init_memory_mapping: [mem 0x00000000-0x000fffff]
7/18
rowhammer
[
0.000000] init_memory_mapping: [mem 0x119e00000-0x119ffffff]
[
0.000000] init_memory_mapping: [mem 0x100000000-0x119dfffff]
[
0.000000] init_memory_mapping: [mem 0xc0000000-0xdfffdfff]
[
0.000000] init_memory_mapping: [mem 0x00100000-0xbfffffff]
[
0.000000] RAMDISK: [mem 0x7ff5a000-0x7fffffff]
[
0.000000] ACPI: Early table checksum verification disabled
[
0.000000] ACPI: RSDP 0x00000000000F16A0 000014 (v00 BOCHS )
[
0.000000] ACPI: RSDT 0x00000000DFFFE450 000034 (v01 BOCHS
BXPCRSDT
00000001 BXPC 00000001)
[
0.000000] ACPI: FACP 0x00000000DFFFFF80 000074 (v01 BOCHS
BXPCFACP
00000001 BXPC 00000001)
[
0.000000] ACPI: DSDT 0x00000000DFFFE490 001137 (v01 BXPC
BXDSDT
00000001 INTL 20100528)
[
0.000000] ACPI: FACS 0x00000000DFFFFF40 000040
[
0.000000] ACPI: SSDT 0x00000000DFFFF700 000838 (v01 BOCHS
BXPCSSDT
00000001 BXPC 00000001)
[
0.000000] ACPI: APIC 0x00000000DFFFF610 000078 (v01 BOCHS
BXPCAPIC
00000001 BXPC 00000001)
[
0.000000] ACPI: HPET 0x00000000DFFFF5D0 000038 (v01 BOCHS
BXPCHPET
00000001 BXPC 00000001)
[
0.000000] No NUMA configuration found
[
0.000000] Faking a node at [mem 0x0000000000000000-0x0000000119ffffff]
[
0.000000] NODE_DATA(0) allocated [mem 0x119ffa000-0x119ffdfff]
[
0.000000] kvm-clock: Using msrs 4b564d01 and 4b564d00
[
0.000000] kvm-clock: cpu 0, msr 1:19ff2001, primary cpu clock
[
0.000000] Zone ranges:
[
0.000000]
DMA
[mem 0x00001000-0x00ffffff]
[
0.000000]
DMA32
[mem 0x01000000-0xffffffff]
[
0.000000]
Normal
[mem 0x100000000-0x119ffffff]
[
0.000000] Movable zone start for each node
[
0.000000] Early memory node ranges
[
0.000000]
node
0: [mem 0x00001000-0x0009efff]
[
0.000000]
node
0: [mem 0x00100000-0xdfffdfff]
[
0.000000]
node
0: [mem 0x100000000-0x119ffffff]
[
0.000000] Initmem setup node 0 [mem 0x00001000-0x119ffffff]
[
0.000000] ACPI: PM-Timer IO Port: 0xb008
[
0.000000] ACPI: LAPIC (acpi_id[0x00] lapic_id[0x00] enabled)
[
0.000000] ACPI: LAPIC_NMI (acpi_id[0xff] dfl dfl lint[0x1])
[
0.000000] ACPI: IOAPIC (id[0x00] address[0xfec00000] gsi_base[0])
[
0.000000] IOAPIC[0]: apic_id 0, version 17, address 0xfec00000, GSI 0-23
[
0.000000] ACPI: INT_SRC_OVR (bus 0 bus_irq 0 global_irq 2 dfl dfl)
[
0.000000] ACPI: INT_SRC_OVR (bus 0 bus_irq 5 global_irq 5 high level)
[
0.000000] ACPI: INT_SRC_OVR (bus 0 bus_irq 9 global_irq 9 high level)
[
0.000000] ACPI: INT_SRC_OVR (bus 0 bus_irq 10 global_irq 10 high level)
[
0.000000] ACPI: INT_SRC_OVR (bus 0 bus_irq 11 global_irq 11 high level)
[
0.000000] Using ACPI (MADT) for SMP configuration information
[
0.000000] ACPI: HPET id: 0x8086a201 base: 0xfed00000
[
0.000000] smpboot: Allowing 1 CPUs, 0 hotplug CPUs
[
0.000000] PM: Registered nosave memory: [mem 0x00000000-0x00000fff]
[
0.000000] PM: Registered nosave memory: [mem 0x0009f000-0x0009ffff]
[
0.000000] PM: Registered nosave memory: [mem 0x000a0000-0x000effff]
[
0.000000] PM: Registered nosave memory: [mem 0x000f0000-0x000fffff]
[
0.000000] PM: Registered nosave memory: [mem 0xdfffe000-0xdfffffff]
[
0.000000] PM: Registered nosave memory: [mem 0xe0000000-0xfeffbfff]
8/18
rowhammer
[
0.000000] PM: Registered nosave memory: [mem 0xfeffc000-0xfeffffff]
[
0.000000] PM: Registered nosave memory: [mem 0xff000000-0xfffbffff]
[
0.000000] PM: Registered nosave memory: [mem 0xfffc0000-0xffffffff]
[
0.000000] e820: [mem 0xe0000000-0xfeffbfff] available for PCI devices
[
0.000000] Booting paravirtualized kernel on KVM
[
0.000000] setup_percpu: NR_CPUS:512 nr_cpumask_bits:512 nr_cpu_ids:1
nr_node_ids:1
[
0.000000] PERCPU: Embedded 30 pages/cpu @ffff880119c00000 s85376 r8192
d29312 u2097152
[
0.000000] KVM setup async PF for cpu 0
[
0.000000] kvm-stealtime: cpu 0, msr 119c0e180
[
0.000000] Built 1 zonelists in Node order, mobility grouping on.
Total
pages: 1007879
[
0.000000] Policy zone: Normal
[
0.000000] Kernel command line: console=ttyS0
[
0.000000] PID hash table entries: 4096 (order: 3, 32768 bytes)
[
0.000000] AGP: Checking aperture...
[
0.000000] AGP: No AGP bridge found
[
0.000000] Memory: 3951556K/4095600K available (5546K kernel code, 972K
rwdata, 1844K rodata, 1236K init, 824K bss, 144044K reserved, 0K cma-reserved)
[
0.000000] Hierarchical RCU implementation.
[
0.000000]
RCU dyntick-idle grace-period acceleration is enabled.
[
0.000000]
RCU restricting CPUs from NR_CPUS=512 to nr_cpu_ids=1.
[
0.000000] RCU: Adjusting geometry for rcu_fanout_leaf=16, nr_cpu_ids=1
[
0.000000] NR_IRQS:33024 nr_irqs:256 16
[
0.000000] Console: colour VGA+ 80x25
[
0.000000] console [ttyS0] enabled
[
0.000000] tsc: Detected 1600.011 MHz processor
[
0.008000] Calibrating delay loop (skipped) preset value.. 3200.02 BogoMIPS
(lpj=6400044)
[
0.008000] pid_max: default: 32768 minimum: 301
[
0.008000] ACPI: Core revision 20141107
[
0.009189] ACPI: All ACPI Tables successfully acquired
[
0.010294] Security Framework initialized
[
0.011099] AppArmor: AppArmor disabled by boot time parameter
[
0.012005] Yama: becoming mindful.
[
0.013221] Dentry cache hash table entries: 524288 (order: 10, 4194304
bytes)
[
0.016532] Inode-cache hash table entries: 262144 (order: 9, 2097152 bytes)
[
0.018335] Mount-cache hash table entries: 8192 (order: 4, 65536 bytes)
[
0.019885] Mountpoint-cache hash table entries: 8192 (order: 4, 65536 bytes)
[
0.020250] Initializing cgroup subsys memory
[
0.021239] Initializing cgroup subsys devices
[
0.022211] Initializing cgroup subsys freezer
[
0.024009] Initializing cgroup subsys net_cls
[
0.024981] Initializing cgroup subsys blkio
[
0.025926] Initializing cgroup subsys perf_event
[
0.026949] Initializing cgroup subsys net_prio
[
0.028094] mce: CPU supports 10 MCE banks
[
0.029052] Last level iTLB entries: 4KB 0, 2MB 0, 4MB 0
[
0.029052] Last level dTLB entries: 4KB 0, 2MB 0, 4MB 0, 1GB 0
[
0.043423] Freeing SMP alternatives memory: 20K (ffffffff81a2a000 ffffffff81a2f000)
[
0.049034] ftrace: allocating 22200 entries in 87 pages
9/18
rowhammer
[
0.060320] ..TIMER: vector=0x30 apic1=0 pin1=2 apic2=-1 pin2=-1
[
0.061615] smpboot: CPU0: Intel QEMU Virtual CPU version 1.7.0 (fam: 06,
model: 06, stepping: 03)
[
0.064000] Performance Events: Broken PMU hardware detected, using software
events only.
[
0.064000] Failed to access perfctr msr (MSR c1 is 0)
[
0.064000] x86: Booted up 1 node, 1 CPUs
[
0.064000] smpboot: Total of 1 processors activated (3200.02 BogoMIPS)
[
0.064162] NMI watchdog: disabled (cpu0): hardware events not enabled
[
0.065116] devtmpfs: initialized
[
0.070379] pinctrl core: initialized pinctrl subsystem
[
0.071236] NET: Registered protocol family 16
[
0.071982] cpuidle: using governor ladder
[
0.072013] cpuidle: using governor menu
[
0.072609] ACPI: bus type PCI registered
[
0.073156] acpiphp: ACPI Hot Plug PCI Controller Driver version: 0.5
[
0.074429] PCI: Using configuration type 1 for base access
[
0.076817] ACPI: Added _OSI(Module Device)
[
0.077398] ACPI: Added _OSI(Processor Device)
[
0.077999] ACPI: Added _OSI(3.0 _SCP Extensions)
[
0.078640] ACPI: Added _OSI(Processor Aggregator Device)
[
0.081384] ACPI: Interpreter enabled
[
0.081896] ACPI Exception: AE_NOT_FOUND, While evaluating Sleep State
[\_S1_] (20141107/hwxface-580)
[
0.083168] ACPI Exception: AE_NOT_FOUND, While evaluating Sleep State
[\_S2_] (20141107/hwxface-580)
[
0.084319] ACPI: (supports S0 S3 S4 S5)
[
0.084848] ACPI: Using IOAPIC for interrupt routing
[
0.085528] PCI: Using host bridge windows from ACPI; if necessary, use
"pci=nocrs" and report a bug
[
0.089880] ACPI: PCI Root Bridge [PCI0] (domain 0000 [bus 00-ff])
[
0.090746] acpi PNP0A03:00: _OSC: OS supports [ASPM ClockPM Segments MSI]
[
0.091659] acpi PNP0A03:00: _OSC failed (AE_NOT_FOUND); disabling ASPM
[
0.092099] acpi PNP0A03:00: fail to add MMCONFIG information, can't access
extended PCI configuration space under this bridge.
[
0.093972] acpiphp: Slot [3] registered
[
0.094523] acpiphp: Slot [4] registered
[
0.095074] acpiphp: Slot [5] registered
[
0.096027] acpiphp: Slot [6] registered
[
0.096578] acpiphp: Slot [7] registered
[
0.097127] acpiphp: Slot [8] registered
[
0.097673] acpiphp: Slot [9] registered
[
0.098225] acpiphp: Slot [10] registered
[
0.098787] acpiphp: Slot [11] registered
[
0.099349] acpiphp: Slot [12] registered
[
0.100026] acpiphp: Slot [13] registered
[
0.100584] acpiphp: Slot [14] registered
[
0.101146] acpiphp: Slot [15] registered
[
0.101705] acpiphp: Slot [16] registered
[
0.102263] acpiphp: Slot [17] registered
[
0.102828] acpiphp: Slot [18] registered
[
0.103385] acpiphp: Slot [19] registered
[
0.103944] acpiphp: Slot [20] registered
[
0.104025] acpiphp: Slot [21] registered
10/18
rowhammer
[
0.104585] acpiphp: Slot [22] registered
[
0.105144] acpiphp: Slot [23] registered
[
0.105702] acpiphp: Slot [24] registered
[
0.106267] acpiphp: Slot [25] registered
[
0.106827] acpiphp: Slot [26] registered
[
0.107387] acpiphp: Slot [27] registered
[
0.108025] acpiphp: Slot [28] registered
[
0.108584] acpiphp: Slot [29] registered
[
0.109144] acpiphp: Slot [30] registered
[
0.109703] acpiphp: Slot [31] registered
[
0.110257] PCI host bridge to bus 0000:00
[
0.110806] pci_bus 0000:00: root bus resource [bus 00-ff]
[
0.112004] pci_bus 0000:00: root bus resource [io 0x0000-0x0cf7]
[
0.112820] pci_bus 0000:00: root bus resource [io 0x0d00-0xffff]
[
0.113633] pci_bus 0000:00: root bus resource [mem 0x000a0000-0x000bffff]
[
0.114541] pci_bus 0000:00: root bus resource [mem 0xe0000000-0xfebfffff]
[
0.120686] pci 0000:00:01.1: legacy IDE quirk: reg 0x10: [io 0x01f0-0x01f7]
[
0.121639] pci 0000:00:01.1: legacy IDE quirk: reg 0x14: [io 0x03f6]
[
0.122518] pci 0000:00:01.1: legacy IDE quirk: reg 0x18: [io 0x0170-0x0177]
[
0.123451] pci 0000:00:01.1: legacy IDE quirk: reg 0x1c: [io 0x0376]
[
0.124610] pci 0000:00:01.3: quirk: [io
0xb000-0xb03f] claimed by PIIX4
ACPI
[
0.125575] pci 0000:00:01.3: quirk: [io 0xb100-0xb10f] claimed by PIIX4 SMB
[
0.145929] ACPI: PCI Interrupt Link [LNKA] (IRQs 5 *10 11)
[
0.146892] ACPI: PCI Interrupt Link [LNKB] (IRQs 5 *10 11)
[
0.148230] ACPI: PCI Interrupt Link [LNKC] (IRQs 5 10 *11)
[
0.149165] ACPI: PCI Interrupt Link [LNKD] (IRQs 5 10 *11)
[
0.150052] ACPI: PCI Interrupt Link [LNKS] (IRQs *9)
[
0.151150] ACPI: Enabled 16 GPEs in block 00 to 0F
[
0.152044] vgaarb: setting as boot device: PCI:0000:00:02.0
[
0.152803] vgaarb: device added: PCI:0000:00:02.0,decodes=io+mem,owns=io
+mem,locks=none
[
0.153873] vgaarb: loaded
[
0.154243] vgaarb: bridge control possible 0000:00:02.0
[
0.155082] PCI: Using ACPI for IRQ routing
[
0.155937] HPET: 3 timers in total, 0 timers will be used for per-cpu timer
[
0.156023] hpet0: at MMIO 0xfed00000, IRQs 2, 8, 0
[
0.156751] hpet0: 3 comparators, 64-bit 100.000000 MHz counter
[
0.161082] Switched to clocksource kvm-clock
[
0.166386] pnp: PnP ACPI init
[
0.167568] pnp: PnP ACPI: found 7 devices
[
0.174451] NET: Registered protocol family 2
[
0.175213] TCP established hash table entries: 32768 (order: 6, 262144
bytes)
[
0.176258] TCP bind hash table entries: 32768 (order: 7, 524288 bytes)
[
0.177212] TCP: Hash tables configured (established 32768 bind 32768)
[
0.178085] TCP: reno registered
[
0.178528] UDP hash table entries: 2048 (order: 4, 65536 bytes)
[
0.179339] UDP-Lite hash table entries: 2048 (order: 4, 65536 bytes)
[
0.180330] NET: Registered protocol family 1
[
0.180981] pci 0000:00:00.0: Limiting direct PCI/PCI transfers
[
0.181771] pci 0000:00:01.0: PIIX3: Enabling Passive Release
[
0.182549] pci 0000:00:01.0: Activating ISA DMA hang workarounds
[
0.183469] Unpacking initramfs...
11/18
rowhammer
[
0.197064] Freeing initrd memory: 664K (ffff88007ff5a000 - ffff880080000000)
[
0.198052] PCI-DMA: Using software bounce buffering for IO (SWIOTLB)
[
0.198909] software IO TLB [mem 0xdbffe000-0xdfffe000] (64MB) mapped at
[ffff8800dbffe000-ffff8800dfffdfff]
[
0.200363] microcode: CPU0 sig=0x663, pf=0x1, revision=0x1
[
0.201165] microcode: Microcode Update Driver: v2.00
<[email protected]>, Peter Oruba
[
0.202599] futex hash table entries: 256 (order: 2, 16384 bytes)
[
0.203433] audit: initializing netlink subsys (disabled)
[
0.204189] audit: type=2000 audit(1426571643.378:1): initialized
[
0.205303] HugeTLB registered 2 MB page size, pre-allocated 0 pages
[
0.206165] zpool: loaded
[
0.206664] VFS: Disk quotas dquot_6.5.2
[
0.207207] VFS: Dquot-cache hash table entries: 512 (order 0, 4096 bytes)
[
0.208794] alg: No test for stdrng (krng)
[
0.209415] Block layer SCSI generic (bsg) driver version 0.4 loaded (major
252)
[
0.210479] io scheduler noop registered
[
0.210977] io scheduler deadline registered
[
0.211556] io scheduler cfq registered (default)
[
0.212302] pci_hotplug: PCI Hot Plug PCI Core version: 0.5
[
0.213083] pciehp: PCI Express Hot Plug Controller Driver version: 0.4
[
0.214003] GHES: HEST is not enabled!
[
0.214601] Serial: 8250/16550 driver, 4 ports, IRQ sharing enabled
[
0.241713] 00:05: ttyS0 at I/O 0x3f8 (irq = 4, base_baud = 115200) is a
16550A
[
0.243124] Linux agpgart interface v0.103
[
0.243760] AMD IOMMUv2 driver by Joerg Roedel <[email protected]>
[
0.244638] AMD IOMMUv2 functionality not available on this system
[
0.245539] i8042: PNP: PS/2 Controller [PNP0303:KBD,PNP0f13:MOU] at
0x60,0x64 irq 1,12
[
0.247318] serio: i8042 KBD port at 0x60,0x64 irq 1
[
0.247983] serio: i8042 AUX port at 0x60,0x64 irq 12
[
0.248802] mousedev: PS/2 mouse device common for all mice
[
0.249844] input: AT Translated Set 2 keyboard as /devices/platform/i8042/
serio0/input/input0
[
0.251207] rtc_cmos 00:00: RTC can wake from S4
[
0.252128] rtc_cmos 00:00: rtc core: registered rtc_cmos as rtc0
[
0.253114] rtc_cmos 00:00: alarms up to one day, 114 bytes nvram, hpet irqs
[
0.254056] ledtrig-cpu: registered to indicate activity on CPUs
[
0.255029] TCP: cubic registered
[
0.255496] NET: Registered protocol family 10
[
0.256286] mip6: Mobile IPv6
[
0.256700] NET: Registered protocol family 17
[
0.257307] mpls_gso: MPLS GSO support
[
0.258062] registered taskstats version 1
[
0.258910] rtc_cmos 00:00: setting system clock to 2015-03-17 05:54:02 UTC
(1426571642)
[
0.260527] Freeing unused kernel memory: 1236K (ffffffff818f5000 ffffffff81a2a000)
[
0.261600] Write protecting the kernel read-only data: 8192k
[
0.262576] Freeing unused kernel memory: 588K (ffff88000156d000 ffff880001600000)
12/18
rowhammer
[
0.263664] Freeing unused kernel memory: 204K (ffff8800017cd000 ffff880001800000)
[
1.200507] tsc: Refined TSC clocksource calibration: 1600.008 MHz
[
42.804616] Bits 55-60 of /proc/PID/pagemap entries are about to stop being
page-shift some time soon. See the linux/Documentation/vm/pagemap.txt for
details.
flip_offset_page=32
file_size=32 MB
iterations=57088
Out of 16 page tables per mmap():
Page table 0 requires flip to 0: address is 0x74db4000
Page table 1 requires flip to 1: address is 0x614e7000
Page table 2 requires flip to 1: address is 0xafe16000
Page table 3 requires flip to 0: address is 0x63d3c000
Page table 4 requires flip to 0: address is 0x8afe0000
Page table 5 requires flip to 1: address is 0xc18e9000
Page table 6 requires flip to 1: address is 0x4de16000
Page table 7 requires flip to 0: address is 0x56120000
Page table 8 requires flip to 0: address is 0x3393e000
Page table 9 requires flip to 1: address is 0x8425e000
Page table 10 requires flip to 0: address is 0x10bc7000
Page table 11 requires flip to 1: address is 0x9da33000
Page table 12 requires flip to 1: address is 0x6c4ef000
Page table 13 requires flip to 0: address is 0xb29de000
Page table 14 requires flip to 0: address is 0x677f7000
Page table 15 requires flip to 0: address is 0x2799f000
pte_pages=16000, pte_size=62 MB, rate=21.8 MB/sec
pte_pages=32000, pte_size=125 MB, rate=25.6 MB/sec
pte_pages=48000, pte_size=187 MB, rate=28.8 MB/sec
pte_pages=64000, pte_size=250 MB, rate=32.0 MB/sec
pte_pages=80000, pte_size=312 MB, rate=32.9 MB/sec
pte_pages=96000, pte_size=375 MB, rate=35.3 MB/sec
pte_pages=112000, pte_size=437 MB, rate=36.7 MB/sec
pte_pages=128000, pte_size=500 MB, rate=38.1 MB/sec
pte_pages=144000, pte_size=562 MB, rate=39.3 MB/sec
pte_pages=160000, pte_size=625 MB, rate=40.2 MB/sec
pte_pages=176000, pte_size=687 MB, rate=40.9 MB/sec
pte_pages=192000, pte_size=750 MB, rate=41.3 MB/sec
pte_pages=208000, pte_size=812 MB, rate=41.4 MB/sec
pte_pages=224000, pte_size=875 MB, rate=40.8 MB/sec
pte_pages=240000, pte_size=937 MB, rate=40.6 MB/sec
pte_pages=256000, pte_size=1000 MB, rate=40.8 MB/sec
pte_pages=272000, pte_size=1062 MB, rate=41.0 MB/sec
pte_pages=288000, pte_size=1125 MB, rate=41.0 MB/sec
pte_pages=304000, pte_size=1187 MB, rate=41.0 MB/sec
pte_pages=320000, pte_size=1250 MB, rate=40.9 MB/sec
pte_pages=336000, pte_size=1312 MB, rate=40.2 MB/sec
pte_pages=352000, pte_size=1375 MB, rate=40.0 MB/sec
pte_pages=368000, pte_size=1437 MB, rate=40.0 MB/sec
pte_pages=384000, pte_size=1500 MB, rate=39.9 MB/sec
pte_pages=400000, pte_size=1562 MB, rate=39.7 MB/sec
pte_pages=416000, pte_size=1625 MB, rate=39.6 MB/sec
pte_pages=432000, pte_size=1687 MB, rate=39.3 MB/sec
pte_pages=448000, pte_size=1750 MB, rate=38.7 MB/sec
13/18
rowhammer
pte_pages=464000, pte_size=1812 MB, rate=38.5 MB/sec
pte_pages=480000, pte_size=1875 MB, rate=38.3 MB/sec
pte_pages=496000, pte_size=1937 MB, rate=38.1 MB/sec
pte_pages=512000, pte_size=2000 MB, rate=37.9 MB/sec
pte_pages=528000, pte_size=2062 MB, rate=37.7 MB/sec
pte_pages=544000, pte_size=2125 MB, rate=37.5 MB/sec
pte_pages=560000, pte_size=2187 MB, rate=37.3 MB/sec
pte_pages=576000, pte_size=2250 MB, rate=36.8 MB/sec
pte_pages=592000, pte_size=2312 MB, rate=36.5 MB/sec
pte_pages=608000, pte_size=2375 MB, rate=36.4 MB/sec
pte_pages=624000, pte_size=2437 MB, rate=36.4 MB/sec
pte_pages=640000, pte_size=2500 MB, rate=36.1 MB/sec
pte_pages=656000, pte_size=2562 MB, rate=36.1 MB/sec
pte_pages=672000, pte_size=2625 MB, rate=36.0 MB/sec
pte_pages=688000, pte_size=2687 MB, rate=35.9 MB/sec
pte_pages=704000, pte_size=2750 MB, rate=35.7 MB/sec
pte_pages=720000, pte_size=2812 MB, rate=35.5 MB/sec
pte_pages=736000, pte_size=2875 MB, rate=35.2 MB/sec
pte_pages=752000, pte_size=2937 MB, rate=35.0 MB/sec
pte_pages=768000, pte_size=3000 MB, rate=34.7 MB/sec
pte_pages=784000, pte_size=3062 MB, rate=34.2 MB/sec
pte_pages=800000, pte_size=3125 MB, rate=33.9 MB/sec
pte_pages=816000, pte_size=3187 MB, rate=33.7 MB/sec
pte_pages=832000, pte_size=3250 MB, rate=33.7 MB/sec
pte_pages=848000, pte_size=3312 MB, rate=33.5 MB/sec
pte_pages=864000, pte_size=3375 MB, rate=33.5 MB/sec
pte_pages=880000, pte_size=3437 MB, rate=33.5 MB/sec
pte_pages=896000, pte_size=3500 MB, rate=33.5 MB/sec
pte_pages=912000, pte_size=3562 MB, rate=33.3 MB/sec
pte_pages=913408, pte_size=3568 MB, rate=33.3 MB/sec
Running target executable...
Hello world -- in innocent program
Test mode: Flipping bit at address cee63100...
before: val=0x800000004de16027
after:
val=0x800000004df16027
Changed bit 20 to 1
Searching for modified PTE...
Found at index 0xdf14c20
In page table 6 (out of 16 per mmap())
Entry 0 contains 0x0
Entry 32 contains 0x80000000614e7027
Modifying PTE...
Searching for page that uses this PTE...
Found at index 0x11184201
Points to 0xf000ff53f000ff53
Running target executable...
Escape!
Test mode: Cleaning up: Undoing bit flip
Test mode: Flipping bit at address cee63100...
before: val=0x800000004df16067
after:
val=0x800000004de16067
Changed bit 20 to 0
** exited with status 0 (0x0)
14/18
rowhammer
4. 취약 여부 테스트
현재까지 논의된 바로는 rowhammer 취약점이 존재하는 환경은 다음과 같다.4
•DDR3 DRAM(DDR2, DDR4는 안됨)
•SODIMM (DIMM은 안됨)
•ECC 환경에서는 제한적 가능
(1) Rowhammer-test
Google Project Zero팀은 시스템이 bit flip을 일으키는가를 확인할 수 있는 코드5를 제공하고 있다.
•Test machine: Macbook air 2011mid
•RAM of test machine6 :
4
http://seclists.org/fulldisclosure/2015/Mar/72
5
https://github.com/google/rowhammer-test
6
RAM Type 확인
• Linux: $sudo dmidecode -t memory
• OS X: $system_profiler SPMemoryDataType
15/18
rowhammer
테스트 결과는 아래와 같다. 각 Iteration마다 메모리에 0xffffffffffffffff을 썼으나 2881번의 Iteration에
서 0xfffffbffffffffff가 읽혔음을 알 수 있다. 이것은 bit flip가 일어났다는 의미로 테스트 머신은 row
hammer에 취약함을 의미한다.
Google Project Zero 팀은 2010~2014년까지 생산된 DDR3 DRAM을 사용하는 29개의 x86 랩탑 머신
에 대해서 조사했고, 이 중 15개의 제품에서 bit-flip이 일어나는 것을 확인했다. DDR4 DRAM은 현재 이
취약점과는 무관한 것으로 알려져있다. error-correcting memory(ECC)를 사용하는 RAM의 경우 단일
비트 오류에 대해서는 수정을 가하므로 어느정도 안전하나 복수비트에 대해서는 검출만 가능하므로 추가
적인 연구를 통해 공격이 가능할 것으로 생각된다.
현재 Google 그룹스7에는 자신의 머신이 취약한지 여부에 대한 테스트 결과를 많은 사람들이 올리고 있
어 다양한 표본을 수집할 수 있을 것이다.
7
https://groups.google.com/forum/#!forum/rowhammer-discuss
16/18
rowhammer
(2) Rowhammer detective
FuturePlusSystem에서는 단일 row에 대한 과도한 ACTIVATE 명령을 검출해 내어 rowhammer를 일으
키는지 확인하기 위한 서비스를 제공하고 있다. 중요한 자료를 가지고 있는 머신인 경우 해당 기기를 사
용하여 안전성을 높일 수 있을 것이다.
5. 향후 전망
rowhammer는 갑자기 나타난 문제는 아니다. 몇년 전부터 인지되어왔고 관련된 연구들이 이루어져 왔었
다. 실제로 DDR4에서 해당 문제가 수정된 것을 보면 제조사들 역시 해당 문제를 인지했음을 알 수 있다.
하지만 지금까지의 논의는 문제점의 발견, 수정 등을 위한 연구였다면 Google Project Zero 측의 논의는
하드웨어적 결함을 소프트웨어적 공격으로의 접근으로 삼았다는 점이 새로운 것이다.
rowhammer처럼 하드웨어 결함에 대한 발견/수정 논의에만 그치고 있는 하드웨어적 결함들이 아직도
많이 존재하고 있을 것이라고 생각된다. 따라서 DDR3에서의 rowhammer 공격법과 같은 하드웨어+소
프트웨어 공격 분야의 다양한 연구들이 나타날 것으로 생각된다.
끝으로 rowhammer에 대한 추가 연구들에 대한 전망을 덧붙여본다.
- CLFLUSH를 사용하지 않는 공격 가능성
현재 연구는 주로 쉽게 ACTIVATE 명령을 줄 수 있는 CLFLUSH 인스트럭션이 존재하는 x86 머신에
대해서만 이루어지고 있다. 하지만 현재 MOVNTQ를 이용한 공격8 , 자바스크립트로 부터의 공격가능
성9 등 다양한 방법이 연구되고 있다. - ECC 환경
ECC(error-correcting memory)가 지원되는 디바이스의 경우 1개비트의 오류에 대해서 수정이 가해
진다. 그러나 다수의 bit-flip에 대해서는 수정할 수 없으므로 ECC가 지원된다고 해서 안전하다고 장담
할 수 없다. 1개비트 오류가 아닌 다수비트 오류를 만들어내야 한다는 점에서 확률이 떨어지는 문제가
있으나 이를 해결할 방법이 추가로 연구될 수 있을 것이다.
8
https://groups.google.com/forum/#!topic/rowhammer-discuss/82EYAaMJxq0
9
http://blog.erratasec.com/2015/03/some-notes-on-dram-rowhammer.html#.VQfHVBCsUqk
17/18
rowhammer
- 다양한 rowhammer를 위한 추가 연구
Google Project Zero 측은 테스트를 위한 PoC코드를 qemu 가상머신에서 구동시키고, 테스트 종료
후 bit-flip을 원상복구 시키는 등의 기능을 넣음으로써 혹시 모를 crash를 방지하고 있다. 이러한 위험
성을 줄이고자 하는 연구가 진행되고 있다.10
또한 mmap을 이용한 momory spray는 가장 직관적이지만 비효율적인 공격법으로 보인다. bit-flip
을 이용해 효율적으로 공격할 수 있는 논의가 진행 중이므로 다양한 공격법이 나타날 것이다.
6. 관련 자료
•Google Project Zero, “Exploiting the DRAM rowhammer bug to gain kernel privileges”
http://googleprojectzero.blogspot.com/2015/03/exploiting-dram-rowhammer-bug-togain.html
•Yoon Kim et al, CMU “Flipping Bits in Memory Without Accessing Them: An Experimental Study
of DRAM Disturbance Errors”
http://users.ece.cmu.edu/~yoonguk/papers/kim-isca14.pdf
•Google Project Zero rowhammer-test program
https://github.com/google/rowhammer-test
•FuturePluzSystem youtube video https://www.youtube.com/watch?v=7wIUQ04Vkes
•DDRDetective “Industry Wide Papers on Row Hammer”
http://www.DDRDetective.com/row-hammer
•Safe Rowhammer Privilege Escalation
http://www.halfdog.net/Security/2015/SafeRowhammerPrivilegeEscalation/
10
http://www.halfdog.net/Security/2015/SafeRowhammerPrivilegeEscalation/
18/18