% Security Features in Ubuntu and Windows % Taesoo Kim % 2014-08-25 # Security Features in Modern OSes - Ubuntu 10.04~14.10 - Windows 8 # Ubuntu {.shout} # Configurations {.w} # Configurations - No open ports - SYN cookies - Password hashing (/etc/passwd, /etc/shadow) # Subsystems {.w} # Capabilities - 36 caps (as of Linux 3.16, see. /usr/include/linux/capability.h) - Process vs filesystem capabilities - Goal: dividing roles of the super user (or setuid) - Enable privilege separation on setuid programs # Filesystem Capabilities - (e.g,) CAP_SYS_BOOT, CAP_SYS_CHROOT, CAP_SYS_MODULE, CAP_CHOWN, CAP_KILL, CAP_SYS_ADMIN, etc. ~~~~~{.bash} $ getcap =ping /usr/bin/ping = cap_net_raw+ep CAP_NET_RAW * use RAW and PACKET sockets; * bind to any address for transparent proxying. ~~~~~ # Privilege Seperation w/ Capabilities - Example: ntpd - Starts with CAP_SYS_TIME, CAP_SETUID, CAP_SETGID, CAP_SYS_CHROOT, CAP_NET_BIND_SERVICE - Drop all, except CAP_SYS_TIME # Ad-hoc Design (see. grsecurity blog) - 19/36 ~= full capabilities (root!) - CAP_SETFCAP: set all caps into the file, and run? - CAP_CHOWN: /etc/shadow, /root/.ssh/* can be modified, and relogin? # Cloud PRNG seed - /dev/urandom, /dev/random, RDRAND - Entropy from Pollinate (Pollen servers) on boot - (see. Mining Your Ps and Qs: Detection of Widespread Weak Keys in Network Devices) # Seccomp: Secure Computation - prctl(PR_SET_SECCOMP, 1); - only read(), write(), exit(), and sigreturn() are allowed - New syscall filtering (Seccomp/BPF) # Mandatory Access Control (MAC) {.w} # Mandatory Access Control (MAC) {.w} - All MAC (linux-git/security/*) are implemented on LSM - AppArmor: path-based MAC - SELinux (fine-grained) & Smack (course-grained): inode-based MAC - Processes and files have context (e.g., ps axZ, ls -Z) - Huge database for the policies # AppArmor - Path-based MAC on LSM (Linux Security Module) - File access (read, write, link, lock) - Library loading - Execution of applications - etc. # AppArmor: bash ~~~~~{.conf} @/etc/apparmor.d/abstractions/bash # user-specific bash files @{HOMEDIRS} r, @{HOME}/.bashrc r, @{HOME}/.profile r, @{HOME}/.bash_profile r, @{HOME}/.bash_history rw, # system-wide bash configuration /etc/profile r, /etc/profile.d/ r, /etc/profile.d/* r, ... ~~~~~ # AppArmor: tcpdump ~~~~~{.conf} /usr/sbin/tcpdump { capability net_raw, capability setuid, capability setgid, # for -D capability sys_module, @{PROC}/bus/usb/ r, @{PROC}/bus/usb/** r, # for -z /bin/gzip ixr, /bin/bzip2 ixr, ... } ~~~~~ # SELinux & Smack # SELinux # Smack - Course-grained alternative to SELinux - So, similarly (sigh) - But, MeeGo (mobile OS) actually uses it! - Flexible enough to implement information flow control # Filesystem encryption # Filesystem encryption - Threat model? - Should I enable eCryptfs on my server? - Personal laptop? or company's? # Userspace Hardening # Userspace Hardening # Stack/Heap Protector - Stack: gcc's -fstack-protector (randomized stack canary) - Better than terminator canary? - Heap: double-free protections, checking consistency of metadata # Example: Stack Protector ~~~~~{.nasm} push %ebp mov %esp,%ebp ... leave ret ~~~~~ # Example: Stack Protector ~~~~~{.nasm} push %ebp mov %esp,%ebp mov %gs:0x14,%eax ; load stack canary using gs mov %eax,-0xc(%ebp) ; save it in the stack frame xor %eax,%eax ; clear the register mov -0xc(%ebp),%eax ; load canary xor %gs:0x14,%eax ; compare against one in gs je end call __stack_chk_fail leave ret ~~~~~ # Pointer Obfuscation - Glibc: protect function ptr in heap (writable memory) - atexit(func) - setjmp/longjmp(jmp_buf) - etc. # Glibc: setjmp/longjmp() ~~~~~{.c} // &main = 0x400753 void main() { if (setjmp(jump_point) == 0) {...} } // &jump_point -[JB_BX] 0 0x6012c0: (nil) ![JB_BP] 1 0x6012c8: 0x939a81f2bc976cfb -[JB_12] 2 0x6012d0: 0x400640 -[JB_13] 3 0x6012d8: 0x7fff3315a600 -[JB_14] 4 0x6012e0: (nil) -[JB_15] 5 0x6012e8: (nil) ![JB_SP] 6 0x6012f0: 0x939a81f2bef76cfb ![JB_PC] 7 0x6012f8: 0x6c64e759e60f6cfb (-> around 0x400753) ~~~~~ # Address Space Layout Rand. (ASLR) ~~~~~{.bash} $ diff <(cat /proc/self/maps) <(cat /proc/self/maps) ... 00400000-0040c000 r-xp ... /usr/bin/cat 0060b000-0060c000 r--p ... /usr/bin/cat 0060c000-0060d000 rw-p ... /usr/bin/cat -01a14000-01a35000 rw-p ... [heap] +00f0a000-00f2b000 rw-p ... [heap] -7f2fd4d52000-7f2fd4ef6000 r-xp ... /usr/lib/libc-2.19.so +7f6caefd5000-7f6caf179000 r-xp ... /usr/lib/libc-2.19.so -7fff8b878000-7fff8b89a000 rw-p ... [stack] +7fff5786d000-7fff5788f000 rw-p ... [stack] ... ~~~~~~ # Address Space Layout Rand. (ASLR) - /proc/sys/kernel/randomize_va_space: 0 (off), 1 (on), 2(w/ brk ASLR) - Stack ASLR - Libs/mmap ASLR - Exec ASLR (-fPIE or -pie) - Brk ASLR - VDSO ASLR (sysenter) # PIE-enabled programs # PIE enabled programs ~~~~~{.bash} $ ./checksec.bash --dir /sbin | grep "PIE enabled" Canary found PIE enabled /sbin/dhclient Canary found PIE enabled /sbin/init No canary found PIE enabled /sbin/initctl Canary found PIE enabled /sbin/mkntfs No canary found PIE enabled /sbin/mntctl Canary found PIE enabled /sbin/mountall No canary found PIE enabled /sbin/mount.fuse Canary found PIE enabled /sbin/ntfsclone Canary found PIE enabled /sbin/reboot Canary found PIE enabled /sbin/runlevel ~~~~~ # Built with Fortify Source - -D_FORTIFY_SOURCE=2 (in gcc) - Convert sprintf/strcpy to safe alternatives - Enforce checking of return values (e.g., system, write, open) - Require umask() # Example: strcpy ~~~~~{.c} char buf[0x100]; strcpy(buf, s); ~~~~~~ # Example: -U_FORTIFY_SOURCE ~~~~~{.c} // strcpy(buf, s) mov 0x8(%ebp),%eax ; load parameter `s` to eax mov %eax,0x4(%esp) ; save parameter for strcpy lea -0x108(%ebp),%eax ; count `buf` in eax mov %eax,(%esp) ; save parameter for strcpy call 8048320 ~~~~~ # Example: -D_FORTIFY_SOURCE=2 ~~~~~{.c} // strcpy(buf, s) -> __strcpy_chk(buf, s, buflen) movl $0x100,0x8(%esp) ; save value 0x100 as parameter mov 0x8(%ebp),%eax ; load parameter `s` to eax mov %eax,0x4(%esp) ; save parameter for strcpy lea -0x108(%ebp),%eax ; count `buf` in eax mov %eax,(%esp) ; save parameter for strcpy call 8048370 <__strcpy_chk@plt> ~~~~~ - (ref. https://idea.popcount.org/2013-08-15-fortify_source) # Built with RELRO - "read-only relocation" - Partial RELRO: mark the relocation table read-only after loading - Full RELRO: fully resolve addresses and mark the table readonly - Prevent overwriting of GOT/PLT # Built with RELRO ~~~~~~{.bash} $ ./checksec.bash --dir /sbin | head RELRO FILE Partial RELRO /sbin/a2p Partial RELRO /sbin/a52dec Partial RELRO /sbin/aafire Full RELRO /sbin/dhclient ... ~~~~~~ # Built with BIND_NOW - Resolve all dynamic symbols at start-up - GOT/PLT can be made entirely read-only # Non-Executable Memory - Non-eXecute (NX) or eXecute-Disable (XD) ~~~~~{.bash} $ dmesg | grep NX [ 0.000000] NX (Execute Disable) protection: active $ cat /proc/cpuinfo | grep nx flags : ... tsc msr pae apic mtrr pge ... nx $ ./checksec.bash --dir /sbin | head NX FILE NX enabled /sbin/a2p NX enabled /sbin/a52dec ~~~~~ # Etc - /proc/$pid/maps - Symlink restrictions: owner should be matched in world-writable dirs - Hardlink restrictions: ditto (+ quota bypassing) - Ptrace scope: attachable to only descendants of the debugger # Kernel Hardening # 0-address protection - Prevent NULL dereference (will see ret2dir to workaround this) ~~~~~{.bash} $ sysctl -a | grep mmap_min_addr vm.mmap_min_addr = 65536 ~~~~~ # /dev/mem protection - Only non-memory can be read or written (e.g, Xorg) ~~~~~{.c} int devmem_is_allowed(unsigned long pagenr) { if (pagenr <= 256) return 1; if (!page_is_ram(pagenr)) return 1; return 0; } ~~~~~ # Etc - Block module loading - Read-only data sections (CONFIG_DEBUG_RODATA) - Stack protector - Module RO/NX - Kernel Address Display Restriction - printk("%p") -> masked (also block /proc/slabinfo) - Blacklist Rare Protocols - Block kexec()