Home > 졸업프로젝트 > UEFI DXE 바이너리 취약점 분석기 프로젝트_7

UEFI DXE 바이너리 취약점 분석기 프로젝트_7
UEFI Ghidra

GCM쪽 취약점 추정부 자세히 분석하기

 저번에 찾았던 GCM 암호화 과정에서 진짜 취약점이 발생할 수 있는지를 좀 더 분석해봤다.
제목
해당 부분이 현재 의심을 하고 있는 코드이다. 이때 FUN_003d71 옆 XREF를 보면 총 4군데에서 해당 함수를 호출하는 것을 볼 수 있다. 우선 제일 처음 호출하는 부분을 보았다.
제목
(이 부분부터 각 부분이 어떤 함수인지 이해하는 과정에서 애를 좀 먹었다..)
 OpenSSL의 구조는 다음과 같다.

  1. 최상위에 OpenSSL의 초기화 및 세팅을 담당하는 함수가 존재한다. 해당 함수는 시스템 부팅 시점에 호출되어 대칭 키 알고리즘, 비대칭 키 알고리즘, 해싱 알고리즘 등 큰 범주들의 알고리즘 단위로 등록을 하는 함수를 호출한다.
  2. 각 알고리즘 단위로 등록하는 함수들은 부모 함수의 지시를 받아 라이브러리가 가진 각 알고리즘에 해당하는 알고리즘들의 구조체 주소를 가져와 해시 테이블에 매핑을 한다.
  3. 각 알고리즘들의 구조체에는 해당 알고리즘의 초기화 함수, 실행 함수, 복호화 함수 등의 포인터 주소들이 들어있다.
  4. 이 함수들은 각 알고리즘을 실제 수행하는 파이프라인을 실행하는 함수다.
  5. 그 안에 실제 연산을 수행하는 함수들이 존재한다.

이러한 구조는 OpenSSL 라이브러리 내의 수많은 암호화 API들을 하나로 묶어주기 위한 구조로써, 이때 이런 구조를 EVP(EnVeloPe)라고 한다. 내용은 이 블로그OpenSSL 깃허브에서 참고하였다.
 다시 본론으로 돌아가면 우린 거꾸로 올라가고 있는 중이므로 의심을 한 부분이 실제 연산을 수행하는 함수임을, 방금 본 함수는 해당 함수를 호출하여 파이프라인을 수행하는 상태 머신 정도로 볼 수 있을 것이다. 그리고 예상이 맞다면 해당 함수를 호출하는 부분은 구조체가 될 것이다. 해당 함수를 호출하는 첫 번째 부분으로 들어가보자.
제목
역시나 구조체가 있는 것을 확인할 수 있었다. 그리고 해당 구조체를 사용하는 함수는 하나였고,
제목
제목
해당 함수는 OpenSSL 초기화 과정에서 큰 분류의 알고리즘 내에 속하는 알고리즘들을 해싱 테이블에 등록하는 함수였다. 상태 머신의 형태를 가지는 함수가 가졌던 다른 XREF들 역시 해당 함수로 이어졌다. 그리고 이 함수를 호출하는 부분 역시 하나였으며,
제목
제목
그 함수는 바로 OpenSSL의 초기화 함수였다.
제목
초기화 함수의 디컴파일된 코드와 edk2 안에 있는 OpenSSL의 init.c 코드와 비교해보면 동일한 형태를 띄고 있는 것을 확인할 수 있었다.


 구조는 파악이 끝났고, 이제 남은 건 그래서 실제로 해당 부분에 접근이 가능한가일 것이다. 여기서 나올 수 있는 경우는 세 가지라고 생각하였다.

  1. SMI 핸들러에서 함수 포인터가 담긴 구조체를 호출하는 뭔가가 있다.
  2. SMI 핸들러가 해당 상태 머신으로 데이터를 보내는 무언가가 있다.
  3. SMI 핸들러가 런타임에 OpenSSL의 초기화 루틴 함수를 호출한다.

여기서 1번, 2번은 위에서 확인한 바와 같이 통하는 길이 초기화 루틴 함수 외에는 존재하지 않았다. 그리고 3번의 경우 설령 초기화 함수를 실행한다 하더라도 해당 초기화 함수는 파싱 테이블에 함수 주소들을 등록만 하는 역할을 수행할 뿐 실제 해당 포인터를 실행시키는 부분은 존재하지 않았다. 이에 따라 지금까지의 결론을 아래와 같이 내렸다.

2021년 2월에 릴리즈된 edk2의 VariableSmm 내에서 OpenSSL의 GCM 암호화 부분에서 SMM Callout 취약점이 발생할 수 있는 바이너리가 존재하였다. 하지만 런타임에 SMI 핸들러 중 해당 알고리즘을 사용하기 위해 호출을 하는 부분은 보이지 않았고, OpenSSL의 초기화 함수가 트리거될 수는 있어 보이나 이는 테이블에 등록만 하는 역할을 수행하고 실제 해당 암호화 로직을 실행하지는 않았다. 결론적으로 SMM Callout 취약점을 일으킬 수 있는 로직은 물리적으로 존재해 보이나 런타임에 이를 악용하기 위해 접근할 수 있는 지점이 존재하지 않는, 즉 죽은 코드(Dead Code)로 추측하며, 이의 원인으로 OpenSSL의 암호화 API들을 하나로 묶어주기 위한 구조인 EVP에서 기인한 디블로팅(Debloating)이라 생각한다. 하지만 제조사 내부자, 또는 펌웨어 공급망을 가진 누군가가 핸들러 내부에 악의적으로 해당 부분을 호출하는 코드를 작성한다면 위험할 수도 있지 않을까…생각한다.