Skip to content

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_FORCE kapalı): imzasız ya da doğrulanamayan bir module yine de yüklenir ama kernel'i 'E' karakteriyle taint eder.
  • Restrictive (CONFIG_MODULE_SIG_FORCE açık ya da boot parametresi module.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:

$ scripts/sign-file sha512 kernel-signkey.priv kernel-signkey.x509 module.ko

(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