Circumventing kernel signing

John Richard Moser nigelenki at comcast.net
Wed Jan 2 16:31:40 EST 2008


So far I have come up with two untested, theoretical ways to circumvent 
the kernel signing mechanism and boot an unsigned kernel.  These are 
both dead simple so I'll keep the explanation short.  Both require an 
activation key, neither require a developer's key; in other words, if 
you can boot normally, you can do this.

First, here is how I understand the current boot process.

    Open Firmware
    -> Load kernel
       -> Check digital signature on kernel
          -> Bail if invalid/missing
       -> Execute kernel
          -> Check for activation key
             -> Bail if invalid/missing
          -> Execute init

After this point, we're done with checks.  Beyond here the laptop's 
owner has root access, but can't really replace the kernel.  This 
exercise only addresses replacing the kernel; I do not attempt to 
address replacing the base system or running unsigned applications.

My two attack vectors are kexec() and unsigned module based; the 
unsigned module method just suggests that it's possible to rewrite 
kexec() as a module, possibly an ugly one but it's doable nonetheless. 
The solutions to these are simple as well:

  * kexec()
    * CONFIG_KEXEC=n
    * OR add code in kexec() to check for a signed kernel
  * Module rewrite of kexec()
    * Sign modules and boot with 'enforcemodulesig'

Beyond this point is fluff.  It's what I just said, but with bigger words.


VECTOR 1:  kexec()

    Open Firmware
    -> Load kernel
       -> Check digital signature on kernel
          -> Bail if invalid/missing
       -> Execute kernel
          -> Check for activation key
             -> Bail if invalid/missing
          -> Execute init
             -> S00bootkernel
                -> kexec -l vmlinuz --command-line=nos00
                -> kexec -e
          -> Execute kernel

~# cat /boot/config* | grep "CONFIG_KEXEC"
CONFIG_KEXEC=y

A user could load a copy of the kexec binary for i486 onto the system, 
and execute a new kernel.  Further, the user could replace the entire 
system but keep the AK in /security/ and set up a S00bootkernel init 
script to load and execute a new kernel if the current version is the 
OLPC version.  This would allow the user to boot a stripped-down Debian 
or Ubuntu Server system with their own custom built kernel, using the 
OLPC kernel as a boot loader; it would also realistically allow loading 
BSD or Minix or any other OS, if the OS could physically boot on the XO.


VECTOR 2:  unsigned module

    Open Firmware
    -> Load kernel
       -> Check digital signature on kernel
          -> Bail if invalid/missing
       -> Execute kernel
          -> Check for activation key
             -> Bail if invalid/missing
          -> Execute init
             -> S00bootkernel
                -> modprobe my-hacked-kexec-module
                -> kexec -l vmlinuz --command-line=nos00
                -> kexec -e
          -> Execute kernel

As far as I can tell, OLPC does not sign modules.  Fedora and RHEL use 
signed modules and will refuse to load unsigned or invalidly signed 
modules if the kernel gets the "enforcemodulesig" command line parameter.

kexec() is not black magic and can be forced in as a module.  It just 
has to modify the syscall() table and take over the world (i.e. freeze 
every other process in the kernel, abduct the scheduler).  Someone would 
have to possibly rewrite kexec() in an ugly way, but it could be done.

Aside from needing a little more programming skill or a modularized 
kexec() implementation, this is the same attack vector as Vector 1.
-- 
Bring back the Firefox plushy!
http://digg.com/linux_unix/Is_the_Firefox_plush_gone_for_good
https://bugzilla.mozilla.org/show_bug.cgi?id=322367



More information about the Devel mailing list