Loadable Kernel Integrity Tools Eric Brandwine ericb@uu Todd
35 Slides836.00 KB
Loadable Kernel Integrity Tools Eric Brandwine [email protected] Todd MacDermid [email protected]
What is a kernel module? Code dynamically loaded into the operating system There is no interruption in OS services Code does not run IN the OS, it IS the OS New functionality can be provided, or existing functionality can be augmented or replaced
Kernel modules and security The Problem: The kernel is implicitly trusted Black Hat kernel mods are relatively recent – First public reference: Phrack 50-5, April 1997 Detection of malicious kmods is difficult to impossible – System tools use (and trust) system services – Evil kmods can lie about their existence
Kernel modules and security (cont.) As black hat tools move into the kernel, so must white hat tools Few kmod tools exist, and very few in-kernel – – – – – kstat chkrootkit rkscan carbonite lionfind, etc.
Kernel mode vs. user mode No UIDs/PIDs in kernel – No permissions checks, everything is super-root Kernel has direct access to hardware Kernel can bypass memory mapping hardware Primary entry point for kernel land is system calls – Excellent choke point for monitoring kernel/user interaction – strace/truss
System call table and wrapping Addresses of all syscalls are listed in table – kernel calls table entries, NOT sys *() Table entries can be replaced with address of module code Syscalls can be wrapped to alter, rather than replace functionality – Can alter arguments before passing on to original syscall – Can alter return value before returning to user A single system call can be wrapped multiple times Little evidence is visible in user space
Syscall wrapping and the stack user user syscall module2 module 1 syscall user module 1 syscall
Examples of published KRK Adore – http://www.team-teso.net – Hides files based on owner uid kmod – http://www.itsx.com/kernmod-0.2.tar.gz – Presented at Black Hat 2000 by Job de Haas – Solaris based - issues with 64 bit kernels? http://packetstorm.securify.com/groups/thc/LKM HACKING.html – Tutorial on Linux LKMs – Multiple kmods included
Objectives of fnord Kernel integrity checking – tripwire for the kernel – NOT to guarantee kernel/system integrity (impossible?) – Attempt to guarantee notification of integrity breach Stealth for itself – We assume that attackers are aware of fnord’s existence – We must hide from active searchers, not just casual inspection – No security through obscurity
Objectives of fnord (cont.) Flexible, configurable stealth for others – Traditional security tools can be hidden (tripwire, etc.) – Administration of fnord must be as secure as possible Silent alarms and logging – Intruders know and circumvent system logging – They can’t disable logging that they can’t see In addition for general system integrity, this is ideal for a honeypot
How fnord differs from known kmods Designed for widespread deployment Designed to have no operational impact Separates security administration from systems administration Can be administrated and configured while still in stealth mode No special tools required to administrate – Does not use non-standard ioctl()s
fnord feature list TTY-like management interface Covert logging channel fnord alters it’s behavior based on environment variables Hide files by dev/inode Alter selected file contents Kernel enforced (silent) append only files In-kernel verification of kernel data structures
How to talk with fnord (interactively) Motivation: Must be able to get status/configure module while “live” fnord can register a pseudo device for interaction with users TTY-like interface accepts human readable commands – Simple to work with – No special tools requires (e.g. cat works)
How to talk with fnord (interactively) Can specify files/processes/network connections to hide or show Can configure logging Can request status
Registering the TTY interface Problem: Occupying a char major number would be detectable, due to small number of char majors Solution: dynamically register and unregister the interface – If a (leet) process mknod()s a char special with a name that matches the hardcoded SECDEV string, the interface is registered on the major number of that node – If a (leet) process unlink()s a char special with the major number of the i/f, and a name matching SECDEV, the i/f is unregistered
How to talk with fnord (non-interactively) Problem: Must be able to gather status from module without polling (scalability!) Solution: logging channel parallel to standard kernel logging – provides sprintk() to kernel. Is not exported beyond module – provides /proc/skmsg to user space – similar to printk() and /proc/kmsg Is hidden by fnord
How to talk with fnord (non-interactively) Can attach a modified klogd/syslogd to /proc/skmsg – Reads private (hidden) config file – Is also hidden by fnord All changes to module configuration are logged for audit purposes
How to authenticate to fnord Special environment variable (LEETVAR) hardcoded into module MD5 of special value (LEETSTR) hardcoded into module – LEETSTR cannot be recovered from module If a process has LEETVAR LEETSTR in its environment, it is “leet” – All hidden files are visible to the leet process – File contents are not modified – can cause (de)registration of admin interface
Keeping a low profile: filesystem Files are hidden based on dev/inode – Currently hidden dev/inode pairs are stored in a linked list – orig stat called on each file access attempt Benefits of dev/inode hiding – All links to a file are hidden – No chance of string collision, no spurious files are hidden – Files in any location can be hidden, there is no special dir Problem: Raw disk access
Keeping a low profile: filesystem (cont.) getdents() is wrapped to remove entries for hidden files – we orig stat() the dirp to obtain the dev value – mount points cannot be hidden All syscalls that take char *path are wrapped to return -ENOENT if the path is hidden – What to do for syscalls that take char *path for destination (e.g. link())? Process hiding is a simple case of file hiding (/proc/PID)
Keeping a low profile: file contents open() is wrapped so that files meeting certain criteria cause the resulting fd to be marked – Based on different criteria, fds can be marked for different kinds of alteration close() is wrapped so that it removes the marked fds from the alteration list lseek() is wrapped to return appropriate offsets – This is a non-trivial problem Problem: fork() and dup() change PID/fd
Keeping a low profile: file contents (cont.) read() is wrapped to do the actual work – As needed, a buffer is read in, internal to the module – This buffer is modified (records deleted, added, or changed) – user request is satisfied from this buffer – read()ing a byte at a time will not fool us. – Sliding buffer window catches all interesting records – User is returned data from this buffer
The sliding read() buffer User read()s n bytes, internal buffer filled 4000 bytes Buffer gets modified 4000 /- m bytes User request satisfied from buffer 4000 /- m - n bytes When buffer is down to 1000 bytes, shift left, and repeat 1000 bytes
Keeping a low profile: file content alteration (cont.) Files that get altered: – – – – – – /proc/modules /proc/net/udp /proc/net/tcp /proc/device /proc/PID/environ /dev/kmem (fools kstat!)
Keeping a low profile: (misc.) /proc/module content alteration is not sufficient, due to query module() query module(VOID, QM MODULES,.) triggers content hiding as well.
fnord & system integrity: logfiles Files can be marked append-only in fnord – Works regardless of fs type open() is wrapped such that opening O WRONLY or O RDWR without O APPEND will trigger – Silent alarm via /proc/skmsg – Unaltered version of file saved off (and hidden) – open() then proceeds normally Lulls attackers into a false sense of security
fnord & system integrity: misc Traditional tools can be hidden – – – – Tripwire Host IDS Honeypot monitoring Snort Root is no longer all-powerful Systems administration and security administration are separated
fnord & kernel integrity The real reason we wrote fnord, most of the rest is support for this Kernel data structures cannot be modified for an inkernel viewer sys call table[] entries can be compared to exported kernel symbols – Will catch already installed kmod rootkits Can be extended to other kernel data structures
Syscall integrity checking All syscalls that can be wrapped are. Previous and new addrs are recorded Each time a syscall is called, the addr in the table is compared against the recorded addr. A change alarms Periodically, on the kernel timer, all syscall addrs are compared. All discrepencies alarm. Syscalls that are not easily wrapped: – execve – sigreturn – rt sigsuspend
Attacks against fnord kernel integrity Renaming exported symbol before initial checks are run Unwrapping system calls before each check, and rewrapping (requires knowledge of timer) Still an arms race. Whoever gets there first wins.
Summary of fnord capabilities Can be loaded into an already running kernel in an unknown state – Will detect previously installed kmod root kits (if they're still installed), including itself Protects systems from future kmod based root kits Hides itself virtually without trace – Cannot be easily detected through the filesystem layer or standard OS services – Cannot be easily detected through /dev/kmem
fnord capabilities (cont.) Can hide other devices/processes/network connections, dynamically Provides covert logging channel that does not rely on system logging Protects log files, silently Can be administered without special tools, without disabling stealth – Hashed authentication string prevents easy reversal
Future work Tcpdump mangling, so that selected traffic is invisible to our machine Loose source routing, so all traffic gets routed through a selected box Verification of more kernel structures Solaris port
Stumbling blocks Overflowing the kernel stack Processes exiting without exit() Re-wrapping syscalls (and overwriting exported symbols) Improperly exported orig stat Calling syscalls via int 0x80 within kernel, causing strace oddness – syscall wrap.o Reading into kernel buffers
Alternative approaches to kernel integrity BSD securelevels – Control access to kernel and /dev/kmem Cryptographic signature checking of modules Linux Security Module interface – Currently under development – Extensible set of hooks – http://mail.wirex.com/mailman/listinfo/linux-security-module