├── .gitignore ├── LICENSE ├── README.md ├── chkcryptoboot-profilealert.sh ├── chkcryptoboot.conf ├── chkcryptoboot_hook └── chkcryptoboot_install /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2015, Giancarlo Razzolini 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | 7 | * Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 10 | * Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation 12 | and/or other materials provided with the distribution. 13 | 14 | * Neither the name of mkinitcpio-chkcryptoboot nor the names of its 15 | contributors may be used to endorse or promote products derived from 16 | this software without specific prior written permission. 17 | 18 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 21 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 22 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 24 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 25 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 26 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | 29 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # mkinitcpio-chkcryptoboot 2 | 3 | ## Introduction 4 | Archlinux mkinitcpio hook to check if the bootloader was modified and warn the user to not enter his root device password. Based on chkboot. 5 | 6 | This effectively makes the bootloader code tamper evident, while allowing the root luks device to be more tamper resistant, by demonstrating to the user that the bootloader was modified. This can only be used with a bootloader that knows how to unlock an encrypted boot partition, like GRUB with it's CRYPTODISK feature. 7 | 8 | It does support both MBR bootloaders and UEFI bootloaders. In the case of UEFI, the ESP partition must be left unencrypted, and a separate encrypted boot partition must be created. 9 | 10 | ## Attacks 11 | Your BIOS must be secured with a password, if it's possible. And you should disallow booting from other medias. Except, in the case of booting from an external device to try to thwart an evil maid attack. In either case, if your BIOS is modified, It might trick you into booting from a compromised bootloader. This bootloader can try to change your boot partition, after it's decrypted, to make the initramfs hook not to run, try to boot another kernel, etc. In this case, there will be no warn and you will probably end up typing your root device password. If you use chkboot in conjunction with this hook it will probably detect the changes and warn you, after the fact. But, since the bootloader configuration, kernel and initramfs are kept in the encrypted boot partition, this kind of attack is much harder to accomplish, because the attacker does only have minimal information about the bootloader being used. It does not have information about bootloader menu entries, kernels being used, etc. The compromised bootloader would need to account for all these things. 12 | 13 | For this reason, the user can create a customized kernel cmdline parameter, that can be checked upon boot, to try to detect if you booted from a compromised bootloader or if your boot partition was bypassed. Since this is entirely up to the user, and, to make the parameter user friendly, it must have the name=value form. Much care must be taken with the name, to avoid colliding with common parameters. I suggest using two hashes, created from a RNG input, one for the name and other for the value. After root gets mounted, it can try to detect if the cmdline has the name=value, and warn the user. Just keep in mind the cmdline has a limit in size, including spaces, between 256 and 4096, depending on the architecture. All this adds complexity into the mix, hopefully making a compromised bootloader a very hard task to accomplish, while making it easier to detect. 14 | -------------------------------------------------------------------------------- /chkcryptoboot-profilealert.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # chkcryptoboot-profilealert.sh: copy to /etc/profile.d/chkcryptoboot-profilealert.sh and change its permissions to executable 4 | # 5 | # author: Giancarlo Razzolini 6 | # heavily based on chkboot: https://github.com/inhies/chkboot 7 | 8 | source /etc/default/chkcryptoboot.conf 9 | 10 | if [ -n "$CMDLINE_NAME" -a -n "$CMDLINE_VALUE" ]; then 11 | #checks if the name value pair was configured and checks for them in the kernel's cmdline 12 | for param in `cat /proc/cmdline` ; do 13 | if [ $param = $CMDLINE_NAME=$CMDLINE_VALUE ]; then 14 | return 0 15 | fi 16 | done 17 | fi 18 | 19 | #will never hit if the check above succeeded. 20 | echo -e "CHKCRYPTOBOOT ALERT!\n" 21 | echo -e "You boot partition was probably bypassed!\n" 22 | echo "Please check your kernel cmdline and your chckcryptobook configuration!" 23 | return 1 24 | -------------------------------------------------------------------------------- /chkcryptoboot.conf: -------------------------------------------------------------------------------- 1 | ############################### 2 | ##CHKCRYPTOBOOT Configuration## 3 | ############################### 4 | 5 | #Boot Mode: mbr or efi 6 | BOOTMODE= 7 | 8 | #Boot disk (in case of mbr. the disk you GRUB is installed) 9 | BOOTDISK= 10 | 11 | #BIOS boot partition (in case of mbr with GPT. the BOOTDISK partition where GRUB stage 1.5 is installed) 12 | BOOT_PARTITION= 13 | 14 | #ESP mount point (where your ESP partition is mounted) 15 | ESP= 16 | 17 | #BOOTLOADER EFI stub (in case of efi) 18 | EFISTUB= 19 | 20 | #Kernel cmdline parameter name 21 | CMDLINE_NAME= 22 | 23 | #Kernel cmdline parameter value 24 | CMDLINE_VALUE= 25 | -------------------------------------------------------------------------------- /chkcryptoboot_hook: -------------------------------------------------------------------------------- 1 | #!/usr/bin/ash 2 | 3 | check_mbr () 4 | { 5 | if [ -n "$BOOTDISK" -a -s /etc/chkcryptoboot/disk-head.sha512 ]; then 6 | dd if=$BOOTDISK of=/etc/chkcryptoboot/disk-head bs=446 count=1 7 | cd /etc/chkcryptoboot 8 | sha512sum -c disk-head.sha512 9 | if [ $? -ne 0 ]; then 10 | echo -e "\nCHKCRYPTOBOOT ALERT!\n" 11 | echo -e "CHANGES HAVE BEEN DETECTED IN THE BOOT LOADER CODE INSTALLED IN YOUR MBR!\n" 12 | cd - 13 | return 1 14 | else 15 | echo "Your boot loader code mbr hash was verified successfully." 16 | cd - 17 | return 0 18 | fi 19 | fi 20 | } 21 | 22 | check_core () 23 | { 24 | if [ -n "$BOOTDISK" -a -s /etc/chkcryptoboot/grub-core.sha512 ]; then 25 | if [ -n "$BOOT_PARTITION" ]; then 26 | dd if=$BOOT_PARTITION of=/etc/chkcryptoboot/grub-core bs=512 count=62 27 | else 28 | dd if=$BOOTDISK of=/etc/chkcryptoboot/grub-core skip=1 bs=512 count=62 29 | fi 30 | cd /etc/chkcryptoboot 31 | sha512sum -c grub-core.sha512 32 | if [ $? -ne 0 ]; then 33 | echo -e "\nCHKCRYPTOBOOT ALERT!\n" 34 | echo -e "CHANGES HAVE BEEN DETECTED IN THE BOOT LOADER CORE!\n" 35 | cd - 36 | return 1 37 | else 38 | echo "Your boot loader core hash was verified successfully." 39 | cd - 40 | return 0 41 | fi 42 | fi 43 | } 44 | 45 | check_efi () 46 | { 47 | if [ -n "$ESP" -a -s /etc/chkcryptoboot/efistub.sha512 ]; then 48 | resolve_device "$ESP" 49 | mount $ESP 50 | sha512sum -c /etc/chkcryptoboot/efistub.sha512 51 | if [ $? -ne 0 ]; then 52 | echo -e "\nCHKCRYPTOBOOT ALERT!\n" 53 | echo -e "CHANGES HAVE BEEN DETECTED IN YOUR BOOT LOADER EFISTUB!\n" 54 | return 1 55 | else 56 | echo "Your boot loader efistub hash was verified successfully." 57 | return 0 58 | fi 59 | fi 60 | } 61 | 62 | check_cmdline () 63 | { 64 | if [ -n "$CMDLINE_NAME" -a -n "$CMDLINE_VALUE" ]; then 65 | #checks if the name value pair was configured and checks for them in the kernel's cmdline 66 | for param in `cat /proc/cmdline` ; do 67 | if [ $param = $CMDLINE_NAME=$CMDLINE_VALUE ]; then 68 | echo "Your kernel cmdline contain the correct parameters." 69 | return 0 70 | fi 71 | done 72 | fi 73 | echo -e "\nCHKCRYPTOBOOT ALERT!\n" 74 | echo -e "YOUR KERNEL CMDLINE DO NOT CONTAIN THE PARAMETERS THAT ARE IN\n" 75 | echo -e "THE CHKCRYPTOBOOT CONFIGURATION!\n" 76 | echo -e "THIS INDICATES YOUR BOOT LOADER CONFIGURATION WAS PROBABLY BYPASSED!\n" 77 | return 1 78 | } 79 | 80 | warning_confirm () 81 | { 82 | while true; do 83 | { 84 | echo -e "YOU ARE STRONGLY ADVISED NOT TO ENTER YOUR ROOT CONTAINER PASSWORD!" 85 | echo -e "\nPlease type uppercase yes to continue:" 86 | read YES 87 | if [ $YES = YES ]; then 88 | break 89 | fi 90 | } 91 | done 92 | } 93 | 94 | run_hook () 95 | { 96 | if [ -s /etc/chkcryptoboot/chkcryptoboot.conf ]; then 97 | source /etc/chkcryptoboot/chkcryptoboot.conf 98 | if [ $BOOTMODE = "mbr" ]; then 99 | check_mbr 100 | mbr_check=$? 101 | check_core 102 | core_check=$? 103 | check_cmdline 104 | if [ $mbr_check -ne 0 -o $core_check -ne 0 -o $? -ne 0 ]; then 105 | warning_confirm 106 | fi 107 | elif [ $BOOTMODE = "efi" ]; then 108 | check_efi 109 | efi_check=$? 110 | check_cmdline 111 | if [ $efi_check -ne 0 -o $? -ne 0 ]; then 112 | warning_confirm 113 | fi 114 | else 115 | echo -e "\nCHKCRYPTOBOOT WARNING!\n" 116 | echo -e "YOUR CHKCRYPTOBOOT CONFIGURATION CONTAIN ERRORS!" 117 | warning_confirm 118 | fi 119 | fi 120 | } 121 | 122 | run_cleanuphook () 123 | { 124 | if [ -s /etc/chkcryptoboot/chkcryptoboot.conf ]; then 125 | source /etc/chkcryptoboot/chkcryptoboot.conf 126 | if [ $BOOTMODE = "efi" ]; then 127 | if [ -n $ESP ]; then 128 | umount $ESP 129 | fi 130 | fi 131 | fi 132 | } 133 | -------------------------------------------------------------------------------- /chkcryptoboot_install: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | build () 3 | { 4 | # Are we even needed? 5 | if [ ! -s /etc/default/chkcryptoboot.conf ]; then 6 | error "There is no chkcryptoboot configuration file; exit" 7 | return 1 8 | else 9 | source /etc/default/chkcryptoboot.conf 10 | fi 11 | 12 | # if TMPDIR is set leave it alone otherwise set 13 | [ -z $TMPDIR ] && TMPDIR='/tmp/mkinitcpio-chkcryptoboot' 14 | 15 | # check if TMPDIR exsists if not make it 16 | [ -d $TMPDIR ] || mkdir -p $TMPDIR 17 | 18 | add_dir /etc/chkcryptoboot 19 | 20 | if [ -z $CMDLINE_NAME -o -z $CMDLINE_VALUE ]; then 21 | error "You must configure the cmdline name/value pair; exit" 22 | return 1 23 | fi 24 | 25 | if [ -n "$BOOTMODE" ]; then 26 | if [ $BOOTMODE = "mbr" ]; then 27 | if [ -n "$BOOTDISK" -a -b "$BOOTDISK" ]; then 28 | #only backup first 446 bytes of disk 29 | dd if=$BOOTDISK of=$TMPDIR/disk-head bs=446 count=1 30 | cd $TMPDIR 31 | sha512sum disk-head > $TMPDIR/disk-head.sha512 32 | add_file $TMPDIR/disk-head.sha512 /etc/chkcryptoboot 33 | 34 | if [ -n "$BOOT_PARTITION" -a -b "$BOOT_PARTITION" ]; then 35 | #read first 62 sectors from BIOS boot partition 36 | dd if=$BOOT_PARTITION of=$TMPDIR/grub-core bs=512 count=62 37 | else 38 | #read first 62 sectors from post-MBR gap 39 | dd if=$BOOTDISK of=$TMPDIR/grub-core skip=1 bs=512 count=62 40 | fi 41 | sha512sum grub-core > $TMPDIR/grub-core.sha512 42 | add_file $TMPDIR/grub-core.sha512 /etc/chkcryptoboot 43 | else 44 | error "No BOOTDISK configured; exit" 45 | return 1 46 | fi 47 | elif [ $BOOTMODE = "efi" ]; then 48 | if [ -n "$ESP" ]; then 49 | if [ -n "$EFISTUB" -a -s "$EFISTUB" ]; then 50 | findmnt $ESP --fstab -n --output=source,target,fstype,options,freq,passno > $TMPDIR/fstab 51 | if [ $? != 0 ];then 52 | error "Your ESP mount point was not found in /etc/fstab; exit" 53 | return 1 54 | else 55 | add_module `findmnt $ESP --fstab -n --output=fstype` 56 | add_dir `findmnt $ESP --fstab -n --output=target` 57 | fi 58 | #hash grub efistub 59 | sha512sum "$EFISTUB" > $TMPDIR/efistub.sha512 60 | add_file $TMPDIR/efistub.sha512 /etc/chkcryptoboot 61 | add_file $TMPDIR/fstab /etc/fstab 62 | add_binary /usr/bin/findmnt 63 | else 64 | error "Wrong EFISTUB configuration; exit" 65 | return 1 66 | fi 67 | else 68 | error "No ESP mount point configured; exit" 69 | return 1 70 | fi 71 | else 72 | error "Wrong BOOTMODE configured; exit" 73 | return 1 74 | fi 75 | else 76 | error "NO BOOTMODE configured; exit" 77 | return 1 78 | fi 79 | 80 | add_binary /usr/bin/sha512sum 81 | add_file /etc/default/chkcryptoboot.conf /etc/chkcryptoboot 82 | 83 | add_runscript 84 | 85 | } 86 | 87 | help () 88 | { 89 | cat<