From owner-freebsd-security@FreeBSD.ORG Sat Mar 31 17:16:10 2012 Return-Path: Delivered-To: freebsd-security@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 9337C106564A for ; Sat, 31 Mar 2012 17:16:10 +0000 (UTC) (envelope-from schultz@ime.usp.br) Received: from netuno.ime.usp.br (netuno.ime.usp.br [143.107.45.90]) by mx1.freebsd.org (Postfix) with ESMTP id 310928FC08 for ; Sat, 31 Mar 2012 17:16:09 +0000 (UTC) Received: from arachne.ime.usp.br (arachne.ime.usp.br [143.107.45.22]) by netuno.ime.usp.br (Postfix) with ESMTP id C83F61278D11 for ; Sat, 31 Mar 2012 14:08:30 -0300 (BRT) Received: by arachne.ime.usp.br (Postfix, from userid 112) id BFCC836D6001; Sat, 31 Mar 2012 14:08:20 -0300 (BRT) Received: from bd65dbab.virtua.com.br (bd65dbab.virtua.com.br [189.101.219.171]) by webmail.ime.usp.br (Horde Framework) with HTTP; Sat, 31 Mar 2012 14:08:20 -0300 Message-ID: <20120331140820.101653608997tekk@webmail.ime.usp.br> Date: Sat, 31 Mar 2012 14:08:20 -0300 From: schultz@ime.usp.br To: freebsd-security@freebsd.org MIME-Version: 1.0 Content-Type: text/plain; charset=ISO-8859-1; DelSp="Yes"; format="flowed" Content-Disposition: inline Content-Transfer-Encoding: 7bit User-Agent: Internet Messaging Program (IMP) H3 (4.3.10) X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on netuno.ime.usp.br Subject: FreeBSD Security in Multiuser Environments X-BeenThere: freebsd-security@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "Security issues \[members-only posting\]" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 31 Mar 2012 17:16:10 -0000 Hello, I would like to raise a discussion about the security features of FreeBSD as a whole and how they might be employed to actually derive some meaningful guarantees. I have found myself administering a system with many potentially untrusted users. Furthermore, some users do not trust some of the programs they run and are thus allowed to ask for some "slave" accounts. A "slave" account is a user account accessible only to root and the "master" user. This can lead to a hierachy of authority. Also, each account has potentially confidential data that may be accessed only by the account itself and its "ancestor" accounts. This includes when a user is logged on and what the user is running. Finally, the system must always be up so no user untrusted by root may trash it. This is a pretty harsh set of restrictions and is almost unmanageable. However, I have taken three steps to ensure security: base system hardening, using sudo for privilege granting and using rctl(8) for resource accounting and control. Gathering enough information in these three areas has been an ongoing task for almost half a year, and I would like to discuss some problems of my approach. In terms of system hardening, I have: * Encrypted the whole (except /boot) system with geli(8) (HMAC/SHA256 and AES-XTS). It is not as nice and much slower than proper filesystem-level checksumming but it is what FreeBSD provides (ZFS is too unstable). * Disabled useless and potentially dangerous services: cron, devd and sendmail. * Removed every setuid bit. The system works even then. * Hardened /dev: every non necessary device has had the 0007 bits stripped. Optional groups were created (e.g. audio, mixer and mic for devices /dev/{mixer,dsp,audio}*). * Hardened the sysctls: - security.bsd.see_other_uids=0: Users can only see own processes. - security.bsd.unprivileged_proc_debug=0 - security.bsd.unprivileged_read_msgbuf=0: The log is considered sensitive information. - security.bsd.hardlink_check_uid=1: Avoid hardlinks to old SUID binaries. - kern.log_console_output=0 - kern.coredump=0 - vm.overcommit=1: This avoids retarded Linux-like behaviour on OOM conditions. * Changed permissions on /root to 0700: root deserves privacy. * A boot script changes some permissions: - /var/log to 0750: the logs are considered sensitive information. - /var/run/dmesg.boot to 0640: this is also sensitive information. * Added a group sudoers and made sudo setuid only to users in sudoers: would have avoided trouble with recent sudo exploit if only trusted users have slaves. As for using sudo to grant privilege, for each master-slave relationship between users u and v, I have added a line like "u ALL = (v) NOPASSWD: ALL" to /etc/sudoers. Then the user u is supposed to become v by issuing "sudo -i -u v" and to execute a command as v by issuing "sudo -i -u v ...". It is worth noticing that sudo closes all file descriptors greater than or equal to 3. It is important not to let your pseudo-terminal leak through file descriptors 0, 1 and 2 if you have a shell connected to it. Also, the "-i" is mandatory because otherwise a file descriptor open at directory "." is leaked via the cwd file descriptor. I believe this is enough, but since this is not properly documented, I am not sure. As for resource limiting via rctl(8), for each user u root does not trust, I have added three rules: * user:u:vmemoryuse:deny= * user:u:maxproc:deny= * user:u:pseudoterminals:deny=0 Here and are limits on total virtual memory usage and total occupied entries in the process table for process u, respectively. Furthermore, I never give access to pseudo-terminals to untrusted users because all sessions are started from ssh or ptys of trusted users. Also, ptys must be available otherwise trusted users can not work on the machine. Finally, I have noticed "rctl -u user:u" reports a single pty open for user u no matter how many open ptys u has (except of course if u has no open pty, in which case 0 is reported). One naively would expect these restrictions to be enough to prevent abuse (trashing or DoS) as long as the sum of the MEM values (rounded up to page size) is less than or equal to the total physical memory plus swap space less the system (and trusted users') memory usage and the sum of the PROC values is less than the process table size minus the number of trusted processes. I sincerely do not know if this is the case. However, using vmemoryuse as a limit is overkill: it counts the total mapped pages, not the total anonymous pages, which are the ones that actually take resources. Of course, this assumes the memory management data structures (including the page table) are accounted as anonymous memory of the corresponding process, since it is easy (especially on amd64), to map pages sparsely to greatly increase the size of the page table. However, I do not know if this assumption holds on FreeBSD. What I would like here is a vmemoryuse-like switch that would count anonymous pages only. Programs such as mmap(2)ping torrent clients tend to have a virtual memory usage that far surpasses the anonymous memory usage. Having read getrlimit(2) and having set a rctl(8) rule of the form "user:u:swapuse:deny=" (with vm.overcommit=3) hoping it would have a similar effect to RLIMIT_SWAP, I got several kernel panics if was low enough (32M when it happened). Also, the reports from "rctl -u user:u" were inconsistent. I would like to discuss with anyone interested in this topic, especially about further precautions and the effectiveness of the above ones. FreeBSD, as I can see, is the best operating system out there in terms of security (and I have tried several), even compared to Linux and OpenBSD. However, it is really insecure out of the box like most others. To secure it, one must perform contrived configurations and tweaks, so I wonder why those are not default. P.S.: If you want to attain desktop security, matters get even more complicated. If anyone is interested, I can discuss what I did there (basically virtual X servers and building ports as regular users). Also, thanks for Capsicum, it sure is useful.