Trawling

광자 방출 분석으로 RP2350의 Secure 디버그를 활성화하는 레이저 결함 주입

Ledger Donjon 연구진이 RP2350의 DEBUGEN 레지스터 위치를 광자 방출 현미경으로 찾아낸 뒤, 레이저 펄스로 Secure 디버그를 복구했습니다. 물리적 칩 디캡슐화와 약 25만 달러 규모의 장비가 필요하지만, rescue reset과 결합하면 OTP에 저장된 비밀값까지 읽을 수 있음을 입증했습니다.

본문

Ledger Donjon 연구진은 Raspberry Pi의 RP2350 마이크로컨트롤러에서 영구적으로 비활성화된 디버그 기능을 레이저 결함 주입(Laser Fault Injection, LFI)으로 다시 활성화하고, Secure 세계에 저장된 비밀값을 읽어내는 실험을 수행했습니다. 이 공격은 일반적인 소프트웨어 취약점이나 부트 이미지 변조가 아니라, 칩 후면을 노출한 뒤 특정 트랜지스터 영역에 정밀한 레이저 펄스를 조사하는 하드웨어 보안 공격입니다. 물리적 접근과 파괴적인 시료 준비가 필요하며 전체 실험 장비 비용은 약 25만 달러입니다.

RP2350의 보안 경로와 공격 대상

RP2350은 각 프로세서 소켓에서 Arm Cortex-M33 또는 RISC-V Hazard3 코어를 선택할 수 있는 듀얼 코어 마이크로컨트롤러입니다. Secure Boot는 OTP(One-Time Programmable) 메모리에 저장된 공개키 지문으로 서명된 펌웨어를 인증하고, Armv8-M TrustZone은 Secure와 Non-secure 실행 상태를 분리합니다. 외부 디버거는 Arm Serial Wire Debug(SWD)를 통해 Serial Wire Debug Port(SW-DP)와 메모리 접근 포트(Mem-AP)에 연결합니다.

영구 디버그 비활성화 설정인 CRIT1.DEBUG_DISABLE이 설정되면 두 코어의 Mem-AP가 시스템 버스에 접근하지 못하고, factory-test JTAG 인터페이스와 RISC-V 디버그 모듈 접근 포트도 비활성화됩니다. 다만 SW-DP와 RP-AP(reset and recovery access port)는 계속 응답합니다. 특히 Secure 소프트웨어가 메모리 매핑 레지스터인 DEBUGEN을 설정하면 각 코어의 Mem-AP와 해당 포트를 통한 Secure 접근을 다시 활성화할 수 있습니다. 연구진은 영구 비활성화 플래그 자체가 아니라, 그 효과를 덮어쓸 수 있는 이 DEBUGEN 레지스터를 공격 대상으로 삼았습니다.

DEBUGEN의 주요 기능 비트는 PROC0, PROC0_SECURE, PROC1, PROC1_SECURE, MISC입니다. 특정 코어에서 Secure 디버그를 사용하려면 Mem-AP를 켜는 비트와 해당 포트를 통한 Secure 트랜잭션을 허용하는 비트를 모두 설정해야 합니다. OTP의 보안 필드에는 8개 행에 걸친 3-of-8 투표 인코딩과 다중 중복 잠금 비트가 적용되어 있지만, 데이터시트에는 DEBUGEN 비트에 대한 중복 인코딩, 패리티 또는 다수결 보호가 기록되어 있지 않습니다.

광자 방출 현미경으로 레지스터 위치를 좁혔습니다

연구진은 RP2350 A4 리비전 장치에 공개키 지문을 BOOTKEY0에 기록하고, Secure Boot와 영구 디버그 비활성화, 최대 민감도의 glitch detector를 활성화했습니다. 이후 칩을 후면 디캡슐화해 실리콘 기판을 통해 적외선이 트랜지스터에 도달하도록 만들고, GND 연결을 복구한 뒤 Ledger Donjon의 Scaffold 플랫폼에 장착했습니다.

DEBUGEN의 개별 비트를 무작위로 찾는 것은 매우 어렵습니다. 명령어 스킵 공격처럼 코어의 넓은 영역 중 어디를 건드려도 같은 결과가 나오는 방식이 아니라, 특정 레지스터 비트의 저장 영역을 수 마이크로미터 단위로 겨냥해야 하기 때문입니다. 연구진은 이 문제를 해결하기 위해 트랜지스터 동작에서 발생하는 미세한 근적외선 광자를 측정하는 광자 방출 현미경(Photon-Emission Microscopy, PEM)을 사용했습니다.

Secure 소프트웨어가 DEBUGEN의 특정 비트를 반복해서 켰다 끄는 루프를 실행하도록 하고, 서로 다른 비트 마스크를 사용한 두 루프의 촬영 결과를 비교했습니다. 여러 프레임을 평균 내 센서 잡음을 줄인 뒤 두 평균 스택을 빼면 정적 배경, 센서 오프셋, 열 방출, 공통 스위칭 동작이 제거되고 선택한 비트에 따라 달라지는 방출만 남습니다. 연구진은 이 차분 분석을 통해 DEBUGEN 비트 0~3과 연관된 세 영역을 찾아냈고, 이후 레이저 스캔 범위를 수 마이크로미터 규모로 줄였습니다. 이 영역이 실제 저장 셀인지 주변 논리 회로인지는 레이아웃 정보가 없어 구분하지 못했지만, 무작위 탐색보다 훨씬 작은 범위에서 결함 주입을 수행할 수 있었습니다.

두 위치에 레이저를 조사해 Secure 디버그를 복구했습니다

연구진은 980nm 파장, 최대 광출력 2.97W인 펄스 레이저를 약 40% 출력인 1.2W 수준으로 사용했고, 50배 대물렌즈를 통해 100ns 펄스를 조사했습니다. PEM으로 찾은 영역을 스캔하면서 매 펄스 뒤 SWD로 디버그 포트를 확인했습니다.

몇 마이크로미터 떨어진 두 위치가 각각 PROC1과 PROC1_SECURE에 대응했습니다. 한 위치에 펄스를 조사하면 코어 1의 Mem-AP를 통한 버스 접근이 가능해져 PROC1이 설정된 것으로 판단할 수 있었고, 다른 위치에서는 Mem-AP의 Control/Status Word에서 SDeviceEn=1이 관찰되어 PROC1_SECURE가 설정된 것으로 판단했습니다. 한 비트를 설정하는 펄스가 다른 비트를 지울 수도 있었기 때문에, 연구진은 PROC1 위치를 반복 조사해 버스 접근을 확보한 뒤 PROC1_SECURE 위치를 조사하고, 버스 접근이 사라지면 다시 첫 위치로 돌아가는 반복 절차를 사용했습니다.

두 위치와 펄스 조건을 보정한 뒤 이 순서는 수 초 안에 Secure 디버그를 활성화했습니다. 20배 대물렌즈로는 재현되지 않았는데, 넓은 레이저 스폿이 비트를 설정하는 영역과 지우는 영역을 동시에 때렸기 때문으로 분석했습니다. 두 비트가 설정된 뒤에는 추가 레이저 조사나 소프트웨어 쓰기 없이 상태가 유지됐습니다. Secure 전용 DEBUGEN 레지스터를 Mem-AP로 읽었을 때 값은 0xc였으며, Secure 전용 레지스터를 성공적으로 읽었다는 점이 해당 트랜잭션이 Secure 속성으로 수행됐음을 확인해 줬습니다.

rescue reset으로 런타임 잠금을 우회했습니다

Secure 디버그를 얻는 것만으로는 challenge의 비밀값을 바로 읽을 수 없었습니다. challenge 펌웨어는 OTP page 48에 저장된 128비트 비밀값을 부팅 과정에서 런타임 잠금으로 다시 보호합니다. page 48의 영구 잠금은 Non-secure 접근을 막지만 Secure 읽기·쓰기는 허용하는 상태였으나, 펌웨어가 부팅되면 otp_hw->sw_lock[48]에 가장 제한적인 값인 0b1111을 기록해 Secure와 Non-secure 모두 접근할 수 없게 만듭니다. 이 소프트 잠금은 다음 OTP reset까지 유지됩니다.

RP-AP의 CTRL.RESCUE_RESTART는 외부 디버그가 비활성화된 상황에서도 접근 가능한 rescue reset 기능입니다. 연구진은 먼저 이 레지스터를 1로 설정한 뒤 0으로 되돌렸습니다. 그러면 전체 시스템이 재설정되고 boot ROM이 rescue flag를 확인한 뒤 사용자 펌웨어를 실행하지 않고 대기 경로에 머뭅니다. 따라서 펌웨어가 page 48의 런타임 잠금을 다시 설정하지 못하고, OTP의 영구 권한에서 파생된 Secure read-write 상태가 남습니다.

실제 공격 순서는 rescue reset 실행, 레이저로 PROC1과 PROC1_SECURE를 설정해 DEBUGEN을 0xc로 변경, Secure Mem-AP를 통해 코어 1을 DHCSR(Debug Halting Control and Status Register)로 정지, OTP의 0xc08~0xc0f 행을 guarded read interface로 읽는 단계로 구성됩니다. 연구진은 이 절차로 challenge의 전체 비밀값을 복구했습니다.

DEBUGEN_LOCK과 소프트웨어 완화책의 한계

DEBUGEN_LOCK은 소프트웨어가 해당 DEBUGEN 비트를 쓰는 것을 막는 용도이며, 데이터시트는 이를 우발적인 쓰기를 방지하는 기능으로 설명합니다. 그러나 실험에서는 DEBUGEN 비트가 0이고 대응하는 lock bit가 1인 상태에서도 레이저 펄스가 DEBUGEN을 설정할 수 있었습니다. 레이저는 DEBUGEN 변경 없이 lock bit만 설정하기도 했으며, 성공한 순서에서는 PROC1과 PROC1_SECURE가 모두 설정될 때 다섯 개 기능 lock bit가 모두 1이었습니다. 한 번 1이 된 lock bit가 0으로 돌아오는 현상은 관찰하지 못했습니다.

ACCESSCTRL로 특정 대상에 대한 디버거의 직접 접근을 제한하고 ACCESSCTRL.LOCK으로 권한 재개방을 막는 방식은 부팅 후 노출을 줄일 수 있습니다. Secure 펌웨어가 DEBUGEN을 주기적으로 검사하고 예상하지 못한 값이면 fail-safe reset을 수행하는 방법도 가능합니다. 그러나 디버거가 다음 검사 전에 코어를 정지할 수 있고, rescue reset은 펌웨어가 ACCESSCTRL를 설정하거나 검사 코드를 실행하기 전에 멈추게 합니다. 또한 디버거가 Secure 코어를 제어하면 직접 Mem-AP 읽기가 차단돼도 코어 레지스터와 코어가 수행하는 메모리 접근을 통해 값이 추출될 수 있습니다.

이번 결과는 OTP의 중복 보호나 개별 잠금 기능이 문서대로 동작하는지와 별개로, 영구 설정, 가변 제어 레지스터, reset 동작, 부팅 전후 실행 상태가 연결된 전체 enforcement path를 함께 검토해야 한다는 점을 보여줍니다. 연구진은 2026년 7월 28일 Raspberry Pi에 이 결함을 공개했으며, Raspberry Pi 팀이 공개 과정에 참여했다고 밝혔습니다.

Hacker News 반응

  • @stackghost — 물리적 접근, 파괴적인 준비, 약 25만 달러의 실험 장비가 필요합니다. 그다지 실용적이지는 않지만, 멋진 공격입니다.
  • @paulnpace — 약 25만 달러의 실험 장비는 현재 기준으로 그렇습니다.
  • @TeMPOraL — 5년 뒤에는 이 과정의 핵심 요소가 드론 같은 빠르게 성장하는 소비자 기술 제품의 요구와 맞아떨어지느냐에 따라, 40만 달러가 될 수도 있고 망치 하나와 50달러가 될 수도 있습니다.
  • @dist-epoch — GP가 RAM 가격에 대한 농담을 한 것이라고 생각합니다. RAMpocalypse가 드론 가격에 어떤 영향을 미칠지 궁금해집니다.

원문: Hacker News / 번역·요약: Trawling

참고 자료

오류 제보