클라우드플레어가 프로덕션 환경의 클라우드플레어 워커에서 원격 Spectre 공격을 재현하고, 다른 워커에 저장된 JWT 토큰을 최대 12비트/초, 99% 이상의 정확도로 읽어내는 데 성공했습니다. 실험은 클라우드플레어 측이 관리하는 공격용 워커와 피해자 역할을 하는 워커를 대상으로 진행되었으며, 연구에서 사용된 공격 기법은 이미 완화되었다고 합니다. A revisit of remote Spectre attacks on Cloudflare Workers | Cloudflare Bloghttps://blog.cloudflare.com/revisiting-spectre-attacks-on-workers/Remote-Timer-as-a-Service: Efficient Microarchitectural Leakage in the Cloud with Remote Timers(PDF 파일)https://arxiv.org/pdf/2608.17043클라우드플레어 워커는 사용자가 준비한 JavaScript 등의 코드를 클라우드플레어의 에지 서버에서 실행할 수 있는 서비스입니다. 일반적인 서버에서는 사용자마다 OS 프로세스를 분리하는 방법이 있지만, 워커에서는 부팅 시간과 처리 부하를 줄이기 위해 JavaScript 엔진 “V8”의 V8 isolate를 이용하여 다수의 사용자를 동일한 OS 프로세스 내에서 분리합니다. 각 워커에는 개별적인 JavaScript용 메모리 영역이 할당되는 모순, 여러 사용자가 동일 프로세스를 공유하기 때문에 CPU 내부 동작을 이용한 공격에 대한 대비가 중요해집니다.
Spectre는 CPU의 “예측적 실행”을 악용하는 공격입니다. CPU는 처리를 가속화하기 위해 조건 분기 지점이 확정되기 전에 분기 지점을 예측하여 앞쪽 처리를 시작할 수 있습니다. 예측이 틀리면 처리 결과는 폐기되지만, CPU 캐시 등에는 미세한 흔적이 남을 수 있습니다. 공격자는 메모리에 대한 접근 시간의 차이를 측정하고, 원래는 읽을 수 없는 데이터를 추론하는 것입니다. 그러나 Spectre에서 캐시의 미세한 속도 차이를 확인하려면 고정밀 시계가 필요합니다. 클라우드플레어는 방어책으로 CPU 처리 중에는 워커 내부 시간이 실질적으로 진행되지 않도록 하고, 멀티스레드나 공유 메모리도 이용할 수 없도록 했으며, 2021년에는 의심스러운 CPU 동작을 감지한 워커를 별 프로세스로 이동하는 “Dynamic Process Isolation(DyPrIs)”를 프로덕션 환경에 도입했습니다. 2021년에는 “워커 내부에는 고정밀 시계가 없어도 네트워크의 다른 쪽에 시계를 놓けばいい”라는 생각으로, WebSocket을 통해 외부의 고정밀 시계를 이용하는 “원격 타이머”를 사용한 공격 연구가 진행되었지만, 읽기 속도는 타이머 역할을 같은 머신 상에 두는 등 이상적인 조건에서도 1시간당 120비트 정도로 제한되었습니다.
캐시 히트와 캐시 미스의 시간 차이는 수 나노초 정도로 짧은 반면, 원격 타이머에는 네트워크 통신으로 인한 큰 지연의 변동이 포함되어 있어, 그대로에서는 양자를 구별하는 것이 어렵습니다. 이에 연구팀은 L1 캐시에서 데이터를 내보내는 것을 결정하는 “Pseudo Least Recently Used(PLRU)”라는 메커니즘을 활용하여, 1회의 작은 속도 차이를 반복적으로 증폭시켜 네트워크를 통해 식별 가능한 크기로 변환했습니다. 소수의 측정으로 밀리초 미만의 차이를 처리할 수 있을 정도로 정밀도를 높였다고 합니다. 아래 그림은 증폭된 캐시 히트와 캐시 미스의 측정 결과입니다. 상단은 네트워크를 통해 측정된 타이머 결과이고, 하단은 내부 고정밀 타이머로 측정한 기준값입니다. 하단에서는 캐시의 초기 상태에 따라 PLRU 증폭 후 처리 시간이 명확하게 분리됩니다. 상단에서는 네트워크의 변동으로 인해 분포가 중첩되어 있지만, 중앙값에는 차이가 있으며, 여러 번의 측정으로 통계적으로 캐시 히트와 캐시 미스를 구별할 수 있습니다.
또 다른 과제는 공격자와 피해자 Worker를 동일한 실행 환경에 배치하고, 공격에 필요한 상태를 장시간 유지하는 것이었습니다. 연구팀은 장시간 동작하는 처리를 처리할 수 있는 Cloudflare의 “Durable Objects”와 WebSocket을 결합했습니다. 처리 도중 정기적으로 제어를 되돌림으로써, 1개의 isolate를 5시간에서 20시간 이상 유지할 수 있었다고 Cloudflare는 설명했습니다. 캐시에서 특정 데이터를 내보내는 작업에 대해서도 개선이 이루어졌습니다. 기존처럼 목적하는 캐시 위치를 정확하게 탐색하는 대신, 캐시 용량보다 훨씬 큰 데이터 영역을 확보하여 매번 새로운 위치를 선택합니다. 선택한 위치가 이미 캐시에서 내보내지고 있을 가능성을 높임으로써, 원격 타이머를 사용한 번거로운 캐시 위치 탐색을 피했습니다. 연구팀은 여러 가지 방법을 결합하여 Cloudflare Workers의 프로덕션 환경에서 일련의 공격을 실행했습니다. 공격자 Worker에서 메모리를 읽어낸 후, 자신들이 관리하는 피해자 역할을 하는 Worker에 미리 비밀 정보를 배치하고, 다른 Worker에서 읽어낼 수 있음을 확인합니다. 최종적으로 피해자 역할을 하는 Worker에 JWT 토큰을 배치하고, 1bit씩 내용을 읽어내는 데 성공했습니다. 여러 번의 측정 결과에서 다수결이나 임계값을 사용하여 0과 1을 판별한 결과, 이전의 매시 120bit와 비교하여 최대 360배의 읽기 속도인 12bit/초를 프로덕션 환경에서 달성했으며, 정확도는 99%를 초과했습니다. 속도를 더욱 높이는 것도 가능하지만, 정확도가 감소한다고 언급되었습니다. 아래 그림은 JWT 토큰의 첫 번째 바이트를 1bit씩 판별한 결과입니다. 측정치를 반복하여 0과 1 중 어느 것에 해당하는지 추측합니다.
한편, 기존의 DyPrIs가 공격을 막지 못했던 이유도 밝혀졌습니다. DyPrIs는 CPU의 하드웨어 성능 카운터를 모니터링하여 Spectre 공격과 유사한 Worker를 감지하고 다른 프로세스로 격리하는 메커니즘입니다. 그러나 DyPrIs는 Worker의 1회 실행이 종료된 후에 격리하는 메커니즘이었기 때문에, WebSocket을 이용하여 1회 실행을 장시간 지속하면 격리가 시작되기 전에 정보를 읽어낼 수 있었다고 합니다. 또한 DyPrIs는 분기 예측 실패 횟수를 iTLB 접근 횟수와 비교하여 공격을 판단했지만, 대량의 WebSocket 통신으로 인해 iTLB 접근이 증가하면 Spectre 특유의 동작이 덜 두드러져 보였다고 합니다. Cloudflare는 연구 결과를 바탕으로 DyPrIs에 대해 장시간 동작하는 Worker 및 입출력을 많이 사용하는 처리를 전제로 감지 방법을 개선했습니다. 더불어 V8 Sandbox 도입으로 이번에 사용된 64비트 포인터를 활용하는 공격 기법을 그대로 동작하지 않도록 하고, 2025년 9월에는 CPU의 “Memory Protection Keys(MPK)”를 사용한 프로세스 내 분리를 Workers에 도입했습니다. MPK는 동일한 OS 프로세스 내의 메모리를 여러 보호 영역으로 나누고 CPU가 메모리 접근을 허가하는 메커니즘입니다. Cloudflare Workers에서는 다른 V8 isolate의 힙을 별도의 보호 영역에 배치하여 하나의 isolate에서 다른 isolate의 메모리로 직접 접근하는 경로를 제한합니다. 이번 연구에서 사용된 isolate 간의 읽기를 방지하기 위한 추가적인 장벽이 되는 것입니다. 다만 Cloudflare는 MPK만으로 모든 Spectre 공격을 방지할 수 없다고 설명하고 있습니다. 아래 그림은 MPK로 다른 isolate의 메모리를 보호하는 이미지입니다. 접근 대상의 보호 키에 대한 접근 권한이 부여되지 않은 경우, 하드웨어 측에서 접근이 차단됩니다.
Cloudflare에 따르면 이번에 제시된 공격 기법은 이미 실환경에서 대응되었으며, 지난 3년간을 조사해도 실제로 악용된 징후는 확인되지 않았다고 합니다. 앞으로는 계산 처리 전후로 타이머와 같은 네트워크 통신을 반복하는 동작에 대해서도 DyPrIs의 감지 물질이 될 수 있는지 조사하는 것을 계속할 것이라고 밝혔습니다.
원문 보기 | 출처: Gigazine