
gem5에서 Retbleed(CVE-2022-29900/29901) 마이크로아키텍처 공격 재현. RSB 언더플로, Flush+Reload 부채널 누출, 검증된 lfence 완화책.
Retbleed (CVE-2022-29900 / CVE-2022-29901) 의 실습 재현 — 오랫동안 안전하다고 여겨졌던 ret 명령어가 CPU의 Return Stack Buffer (RSB) 언더플로우 시 하이재킹될 수 있음을 증명하여 "Retpoline" 방어를 무력화한 2022년 마이크로아키텍처 공격.
이 프로젝트는 gem5의 x86 Out-of-Order CPU 모델에서 전체 공격 생명주기를 시뮬레이션한다: RSB 언더플로우를 트리거하고, Flush+Reload 캐시 부채널을 통해 비밀 데이터를 한 바이트씩 유출한 뒤, 누출을 차단하는 소프트웨어 완화책(lfence)을 검증한다.
과정 프로젝트 — 고급 컴퓨터 아키텍처, 2025년 가을학기, CUNY City College 저자: Abdul Kalam Mansoor & Rebiha Selmani
Spectre 계열 공격은 CPU가 잘못된 추측을 "되돌리더라도" 추측 실행이 캐시 수준의 부작용을 남긴다는 것을 보여주었다. 업계의 해결책인 Retpoline은 위험한 간접 점프를 ret 명령어로 대체했는데, 이는 반환이 작은 하드웨어 스택(RSB)에서 안전하게 예측된다는 가정에 기반했다. Retbleed는 그 가정이 틀렸음을 보여주었다: 깊은 재귀로 RSB를 고갈시키면, CPU는 Retpoline이 피하려고 설계된 바로 그 안전하지 않은 예측기로 조용히 폴백한다.
| 단계 | 발생하는 일 |
|---|---|
| 1. 트리거 | rsb_deep_call()이 32단계 깊이로 재귀하여 16개 항목의 RSB를 오버플로우한다. 재귀가 풀릴 때 RSB는 비어 있다. |
| 2. 폴백 | RSB가 비면 CPU는 ret 대상 예측을 위해 Branch Target Buffer (BTB)로 폴백하는데, 공격자가 이를 오염시킬 수 있다. |
| 3. 가젯 | 하이재킹된 추측 경로가 gadget()을 실행하고, 이는 비밀 비밀번호의 한 바이트를 읽어 probe_array의 인덱스로 사용하여 해당 배열의 한 페이지를 캐시로 끌어온다. |
| 4. Flush+Reload 스파이 | 공격 전에 probe_array의 모든 페이지가 캐시에서 플러시된다(_mm_clflush). 추측 윈도우가 닫힌 후, 프로그램은 모든 가능한 바이트 값에 대한 접근 시간을 측정한다(__rdtscp) — 빠르게 돌아오는 것(캐시 히트)이 비밀 바이트를 드러낸다. |
ROOT_PASSWORD의 모든 바이트에 대해 이를 반복하면 gadget()을 아키텍처적으로 호출하지 않고도 전체 비밀을 재구성한다.
| 모드 | 접근 지연 | 결과 |
|---|---|---|
취약 (SECURE_MODE 미정의) | ~49 사이클 (캐시 히트) | 비밀이 바이트 단위로 유출되며, 빨간색 HIT! 표시로 확인됨 |
패치됨 (SECURE_MODE 정의, _mm_lfence() 주입) | >150 사이클 (캐시 미스 / 노이즈) | 공격 실패 — 출력에 SAFE / Found: ??? 표시 |
lfence는 후속 명령어가 실행되기 전에 CPU가 반환 주소를 해결하도록 강제하여, 가젯이 비밀 의존 메모리에 접근하기 전에 추측 윈도우를 붕괴시킨다.
src/
retbleed.c # 전체 PoC: 트리거, 가젯, Flush+Reload 스파이, lfence 완화책 (SECURE_MODE로 토글)
docs/
Retbleed_Report.pdf # 전체 서면 보고서: 방법론, 관련 연구, gem5 설정, 결과
Retbleed_Attack_Demonstration.pptx # 프로젝트 발표에 사용된 슬라이드 덱
PoC는 gem5 (DerivO3CPU, Out-of-Order 모델 — In-Order 모델은 추측 실행을 구현하지 않으므로 필요함)에서 빌드되고 측정되었다:
gcc -O0 -static -o retbleed src/retbleed.c
./build/X86/gem5.opt configs/deprecated/example/se.py \
--cpu-type=DerivO3CPU --caches --l2cache \
--l1d_size=64kB --l1i_size=64kB --cmd=retbleed
취약 동작과 패치된 동작을 전환하려면 retbleed.c 상단의 이 줄을 주석 처리/해제한다:
#define SECURE_MODE
이 코드는 실제 x86 인트린직(
_mm_clflush,__rdtscp,_mm_lfence)을 사용하며, 더 빠른 데모를 위해 x86 하드웨어에서 네이티브로 컴파일 및 실행할 수도 있다(gcc -O0 -o retbleed src/retbleed.c) — 결과는 호스트 CPU 자체의 완화책(eIBRS, 마이크로코드 패치 등)에 따라 달라지며, 이는 2022년 이후 이 부류의 버그가 얼마나 철저히 패치되었는지를 보여주는 유용한 예시이기도 하다.
lfence)은 영향받는 하드웨어에서 14–39% 성능 오버헤드로 측정되었다.