% 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()