Module signature enforcement¶
Kernel, yüklenebilir her module'ün trusted bir key'den gelen geçerli, eklenmiş bir PKCS#7 imzası taşımasını gerektirebilir; enforcement açıkken, imzasız ya da doğrulanamayan module'ler yalnızca kernel'i taint etmek yerine reddedilir.
Mechanism¶
Neden çalışır
Yüklenebilir bir kernel module, tam ring-0 ayrıcalığıyla çalışır, bu yüzden
saldırganın sağladığı bir .ko'yu yüklemek arbitrary kernel code execution'a
eşdeğerdir. CONFIG_MODULE_SIG doğrulama ekler: module dosyasının sonuna bir
digital signature eklenir, sondaki ~Module signature appended~. string'iyle
işaretlenir ve kernel bunu kernel içinde trusted keyring'lerindeki key'lere
karşı kontrol eder (insmod/modprobe hiçbir doğrulama yapmaz — kontrol
init_module()/finit_module() içinde olur).
Policy düğmesi enforcement sıkılığıdır:
- Permissive (
CONFIG_MODULE_SIG_FORCEkapalı): imzasız ya da doğrulanamayan bir module yine de yüklenir ama kernel'i'E'karakteriyle taint eder. - Restrictive (
CONFIG_MODULE_SIG_FORCEaçık ya da boot parametresimodule.sig_enforce=1): yalnızca geçerli imzalı module'ler yüklenir; geri kalan her şey reddedilir (load başarısız olur). Bu, defender'ların istediği invariant'tır — kernel'in güvendiği bir key tarafından imzalanmamış hiçbir kod kernel'e girmez.
İmza ELF container'ının dışında yaşadığı için, imzalı bir module kırılgandır: imzalandıktan sonra strip edilmemeli, yoksa eklenmiş block kaybolur ve doğrulama başarısız olur.
Walkthrough¶
1. Özelliği ve enforcement durumunu doğrula.
$ zcat /proc/config.gz | grep MODULE_SIG
CONFIG_MODULE_SIG=y
CONFIG_MODULE_SIG_FORCE=y
CONFIG_MODULE_SIG_ALL=y
CONFIG_MODULE_SIG_SHA512=y
CONFIG_MODULE_SIG_KEY="certs/signing_key.pem"
# enforcement can also be turned on at boot:
$ cat /proc/cmdline
... module.sig_enforce=1 ...
CONFIG_MODULE_SIG_ALL, make modules_install sırasında tüm module'leri otomatik
imzalar; o olmadan elle imzalarsın.
2. scripts/sign-file ile bir module'ü elle imzala. Hash algoritmasını,
private key'i, public key'i (X.509) ve module'ü alır:
(Private key yolu, RFC 7512'ye göre bir PKCS#11 URI'si de olabilir.)
3. Enforcement'ın imzasız/değiştirilmiş bir module'ü reddettiğini gözlemle. Enforcement açıkken, trusted bir imzadan yoksun bir module'ü yüklemek başarısız olur:
$ sudo insmod ./unsigned.ko
insmod: ERROR: could not insert module ./unsigned.ko: Key was rejected by service
$ dmesg | tail -2
module: unsigned.ko: module verification failed: ... (ENOKEY)
Permissive modda aynı load başarılı olur ama 'E' taint flag'ini ayarlar
(/proc/sys/kernel/tainted'da ve dmesg'te görünür).
Desteklenen imza hash algoritmaları
CONFIG_MODULE_SIG_SHA256, CONFIG_MODULE_SIG_SHA384,
CONFIG_MODULE_SIG_SHA512, artı SHA-3 varyantları
CONFIG_MODULE_SIG_SHA3_256 / _384 / _512. Signing key varsayılan olarak
certs/signing_key.pem'dir (CONFIG_MODULE_SIG_KEY); ekstra trusted cert'ler
CONFIG_SYSTEM_TRUSTED_KEYS'ten gelir.
Build key'i koru — ve ideal olarak imha et
Kernel dokümanları, private signing key'in "ya imha edilmesi ya da güvenli bir
konuma taşınması ve kernel source tree'sinin root node'unda tutulmaması"
gerektiğini vurgular. Leak olan bir key, saldırganın kendi module'ünü imzalayıp
enforcement'ı tamamen yenmesine izin verir. Ayrıca bir module'ü imzaladıktan
sonra asla strip etme — eklenmiş imza ELF'in dışındadır ve kaybolur.
Detection¶
/proc/sys/kernel/tainted ('E' için bit), permissive modda imzasız bir
module'ün yüklendiğini işaretler. Enforcement açıkken, başarısız load'lar dmesg'te
module verification failed / Key was rejected by service (ENOKEY) olarak görünür.
Mitigation¶
(Güçlendirme.) CONFIG_MODULE_SIG_FORCE'u (ya da module.sig_enforce=1)
etkinleştir, signing key'i build host'unun dışında tut ve module/firmware
dosyalarının doğrulanmış read-only bir volume'den gelmesi için
LoadPin ile, enforcement'ın kendisinin runtime'da disable
edilememesi için de Secure Boot / lockdown ile birleştir.
References¶
- Linux kernel docs. Kernel module signing facility. — https://docs.kernel.org/admin-guide/module-signing.html