과거 애플 맥이 Intel 기반에서 ARM 기반으로 전환한다는 예고의 칼럼[1]이 작성된 지 1년이 채 되지 않아 M1 칩 전체에 영향을 끼치는 취약점이 발견되었습니다.
이번에 발견된 취약점은 두 프로세스가 메모리, 소켓, 파일과 같은 운영체제의 기능을 이용하지 않고 데이터를 교환할 수 있도록 해주는 취약점입니다. 이는 다른 유저, 운영 레벨간의 통신도 가능하며 OS의 개입 없이 은닉하여 데이터를 통신해야 할 때 사용할 수 있습니다.
이 취약점은 리눅스를 Apple의 M1칩에서 구동시키는 것을 목표로 하는 AsahiLinux 커뮤니티에서 제보되었습니다. 어떻게 이 취약점이 발견되었고 원리는 무엇인지 함께 알아봅시다. 아래 이미지를 클릭하면 데모 영상으로 이동합니다.
Aarch64 (ARM64) 시스템 레지스터
CPU가 프로세스를 실행하고 제어하기 위해 범용 레지스터를 사용하는 것처럼, Aarch64 아키텍처는 프로세서를 구성하고 제어하기 위해 시스템 레지스터를 사용합니다.
시스템 레지스터는 MOV
, LDR
과 같이 CPU에서 일반적으로 사용하는 데이터 이동/참조 인스트럭션을 통해 접근할 수 없습니다. 시스템 레지스터에 접근하기 위해서는 X0
, X1
과 같이 범용 레지스터로 시스템 레지스터의 값을 읽고 쓰는 특수한 인스트럭션을 사용해 접근해야 합니다.
아래는 시스템 레지스터에 접근할 때 사용하는 MRS
, MSR
인스트럭션입니다.
MRS Xd, <system register> // Xd 범용 레지스터에 <system register>의 값을 복사
MSR <system register>, Xd // Xd 범용 레지스터의 값을 <system register>로 복사
시스템 레지스터는 SCTLR_ELn
, TTBR0_ELn
과 같이 각각의 이름을 가지고 있지만, 실제로 인스트럭션에 사용될 때에는 이름으로 접근하지 않습니다.
MRS X0, SCTLR_EL1
인스트럭션의 경우 실제로는 MRS X0, #0, c1, c0, #0
인스트럭션으로 표현되며, <system register>
영역에 어떤 상수 값들이 오는지에 따라 접근하는 시스템 레지스터가 달라집니다.
그렇다면, <system register>
에 들어갈 상수 값들을 무작위로 넣어본다면 CPU에 숨겨진 레지스터나 기능을 알아낼 수도 있지 않을까요?
접근 방식
해당 취약점을 발견한 AsahiLinux 커뮤니티는 Apple의 M1칩에서 여러가지 실험을 해보기 위해 m1n1
프로젝트[2]를 진행하였습니다. m1n1
프로젝트의 일환으로 <system register>
에 들어갈 상수 값을 무작위로 넣어보는 실험도 함께 했는데요.
테스트 결과 EL1 (커널 모드)과 EL0 (유저 모드)에서 모두 접근할 수 있는 시스템 레지스터인 s3_5_c15_c10_1
레지스터를 발견하게 되었습니다. m1n1
프로젝트에서 위 실험에 사용된 코드는 https://github.com/AsahiLinux/m1n1/blob/main/proxyclient/m1n1/find_regs.py 에서 확인할 수 있습니다.
이렇게 CPU에 무작위로 값을 변경하며 테스팅하는 방법이 이번에 처음 진행된 것은 아닙니다. 과거 x86 아키텍처에서 CPU 단 백도어를 찾기 위해 랜덤한 옵코드를 생성하고 실행하는 rosenbridge
프로젝트[3] 역시 진행된 적이 있습니다.
그 결과 실제로 유저 모드에서 커널 모드의 메모리에 접근할 수 있도록 해주는 백도어가 발견되었습니다. 데모로 작성된 권한 상승 코드는 https://github.com/xoreaxeaxeax/rosenbridge/blob/master/esc/demo.c 에서 확인할 수 있습니다. 참고로 백도어가 발견된 CPU는 대만의 비아 테크놀로지에서 개발된 VIA C3 Nehemiah CPU
이기 때문에 우리가 사용하는 CPU에서 같은 취약점이 발생할 염려는 하지 않으셔도 됩니다. 😄
이처럼 퍼징과 같이 무작위의 데이터로 테스트하는 기법은 비단 소프트웨어 뿐만 아니라 CPU와 같은 하드웨어에도 적용할 수 있다는 것을 알 수 있습니다.
취약점 소개
s3_5_c15_c10_1
시스템 레지스터는 EL0 (유저 모드)을 포함한 모든 권한에서 접근이 가능하며 읽고 쓰기가 가능한 두 개의 비트가 존재합니다. 따라서 프로세스 간 통신을 위해 OS가 제공하는 기능을 사용하지 않고, 해당 시스템 레지스터를 사용해 통신이 가능합니다.
해당 취약점의 PoC 코드는 https://gist.github.com/marcan/52dd78985635bd75ca9b3b5b0ebe1e20 에서 확인할 수 있습니다.
이 취약점은 CPU 하드웨어 자체의 버그이기 때문에 소프트웨어 업데이트를 통한 패치가 불가능합니다. 하지만 이를 가지고 로컬/원격에서 임의의 코드를 실행하는 것은 불가능하기 때문에 패치하지 않는다고 해서 큰 문제가 발생하지는 않습니다.
결론
CPU 자체에 대한 보안성 연구는 계속되고 있으며, 새롭게 출시된 M1 칩에 대한 연구도 꾸준히 진행되고 있습니다.
비록 이번 취약점이 치명적인 취약점은 아니었지만, 새로운 대상에 대해 끊임없이 도전하는 점을 본받아 우리도 호기심을 가지고 연구해 나갈 수 있기를 희망합니다.
출처
- https://m1racles.com/
- https://developer.arm.com/documentation/102374/0101/Registers-in-AArch64---system-registers
- https://asahilinux.org/