mardi 24 janvier 2012

Linux security in 2011, or my LKML’s yearly digest

Linux security in 2011, or LKML’s yearly digest

  • False boundaries of (certain) capabilities: Brad Spengler describes 19 capabilities (of 35) which can be used to regain full privileges. Coincidentally, Vasily Kulikov discovered a “funny” behavior of CAP_NET_ADMIN which permit to load any modules available in /lib/modules/ instead of limiting to network related modules only, AFAIK, this vulnerability was closed but the fix got reverted some weeks later because of some userspace breakages.
  • PaX team introduced a new range of stuff using the new GCC plugin infrastructure. At compile-time, pro-active code is automatically added to potentially dangerous paths:
    • constify_plugin.c enforces read-onlintroduces new constraints (__do_const and __no_const) enforcing read-only permissions at compilation-time and run-time. PaX then makes usage of theses new constraints by patching most of the “ops structures”. The plugin also automatically protects structures where all members are function pointers, this patching on-the-fly is required because patching directly the source kernel would never be integrated upstream.
    • stackleak_plugin.c adds instrumentation code before alloca() calls. This code checks that stack-frame size does not overlap with kernel task size. It circumvents techniques described in "Large memory management vulnerabilities" by Gaël Delalleau (2005) and "The stack is back" by Jon Oberheide (2012).
    • GCC 4.6 introduced named address spaces. It was initially specified for embedded processors but PaX team uses this feature to represent user and kernel space. checker_plugin.c thus introduces __user, __kernel and __iomem namespaces to spot non-legit flows between address spaces.
    • kallocstat_plugin.c produces statistics about the size given in parameter to various memory allocation functions
    • kernexec_plugin.c enforces non-executable pages like the KERNEXEC PaX feature, but without huge performance impact on AMD64.
  • pagexec also managed to compile Linux Kernel with clang by patching both Linux and clang. Now that gcc integrated plugins, it is less interesting  but llvm was the solely compiler with easy access to its internal structure, allowing external applications to perform static analysis...
  • A user space interface to kernel Crypto-API was submitted to kernel developers, an interesting use-case was to offer a way to deport key material between processes. Imagine process A in possession of private keys and another one, B, actually performing encryption / decryption stuff part. The idea was to initialize a “crypto socket” in A and pass this file descriptor to B (via a classic ancillary message).
  • Pseudo-files in /proc/<pid>/ have a different security model than “normal” files because of its ephemeral nature: checks need to happen during each system call and not at open() time because permissions can change at anytime. Halfdog discovered (and Kees Cook reported it to LKML) that not all files were protected accordingly. If a program opens /proc/self/auxv and keeps this file descriptor opened. Then, even after a execve() of a setuid binary, the file descriptor would still be available, leaking information! Fixing this vulnerability has been a long road and a pretty solution came up with the introduction of revoke(), a new syscall invalidating file descriptors. Unfortunately, the thread didn’t survive and ideas were lost... (by the way, it is funny that this kind of problem resuscitated in CVE-2012-0056 lately...)
  • As one goes along, execve() became almost magical, it had to support Set-User-Id, capabilities, and file capabilities. Each feature added complexity and different legacy behaviors to maintain. Instead of dropping these POSIX features, OpenWall 3.0 took a different approach by removing Suid binaries from its base install, thus preventing execve’s voodoo. This change is just a line in Owl’s changelog but is in fact a major achievement: it required them to re-architecture important softwares like crontab or user management tools.
    /bin/ping is setuid-root because it opens a raw socket and injects its packet on the wire directly. A new socket type, PROT_ICMP, was developed by Openwall team, it makes possible to send ICMP Echo messages without special privileges (caller’s GID has to be included in a range stored in a sysctl key). It is interesting to note that only replies (based on ICMP identifier field) are sent to userspace, not the whole ICMP traffic like in Mac OS X.
  • TCP Initial Sequence number is now a 32-bits random number using MD5. ISN was previously the concatenation of 24 random bits (MD4 of TCP end points with a secret rekeyed every 5 minutes) and an 8 bits counter (number of times secret key was regenerated)
  • Vasilily tried to push upstream additional checks for copy_{to,from}_user() (by checking if requested size fits boundaries fixed at compile time), this patch was a cut down version of PAX_USERCOPY but was NACKed by Linus asking him for more “balance and sanity”. However, he didn’t reject the idea itself, saying that a cleaner version might be accepted...

mercredi 2 novembre 2011

ld-linux.so ELF hooker

TL;DR
Stéphane and myself are releasing a new tool injecting code at runtime, just between the ELF loader and target binary. It is an alternative to LD_PRELOAD, just a little bit more intrusive but 100% reliable :)



When a binary is execve(), the kernel extracts from the ELF headers the interpreter to be launched, usually  /lib/ld-linux.so.2The kernel creates a new process and prepares the environment (arguments and auxiliary data). The target ELF entry point is set in auxiliary vector of type "ENTRY".


Then the kernel opens the requested interpreter, maps the memory regions and start its execution at ld's ELF entry point. Then the loader analyzes the target ELF file, performs its loader work and sets EIP to target ELF entry point (extracted from auxv). At this point, main()'s program is eventually executed.


Our goal was to permit the execution of code for abitrary dynamically linked binary without patching each of them. So our interest moved on the loader, the common point between most executables. Thus, we decided to patch a normal ld in order to inject code. My awesome colleague, Stéphane Duverger (the ramooflax author!) and myself wrote ld-shatnerIts task is to patch ld-linux.so file accordingly:

  1. After ELF header, we shift "ELF program header" a few pages away
  2. In this new section, we inject a "loader routine" (hooked.s) and embedded code to be executed at runtime
  3. After having been saved in our section, ld's ELF entry point is overwritten to jump directly on our routine. This routine extracts from auxiliary vectors the target ELF entry point and overwrites it with a pointer to our embedded code (func() in the payload).
  4. Original ld's entry point is called and ld works as usual
  5. Eventually, it calls entry point set in auxiliary vector (which was replaced by a pointer to our payload)
  6. Embdded code runs
  7. It returns to our routine which finally jumps on original target entry point
Some pictures before/after ld-shatner voodoo:

ld-shatner voodo

Screenshot

$ make clean all
$ cp /lib/ld-linux.so.2 /bin/ls .
$ ./ld-shatner ld-linux.so.2 obj.elf
$ sudo cp ld-hook.so /lib/
$ ./interpatch ls
$ ./ls 
ld-hook <---------------------- output of obj.elf
[...]

(Ok, we cheat for the moment because we have to patch ls binary but we will not have to do that eventually)

So what?

My ultimate goal for ld-shatner is to use this method for starting applications in my sandbox project, seccomp-nurse. For the moment, I rely on LD_PRELOAD feature but this approach is... hackish and I have to work around some bugs because of this special context...



dimanche 25 septembre 2011

Introducing a bit of Web paranoia into my habits...

When I'm not slacking in Emacs, I now spend most of my time in Google Chrome. Almost everything I do is in the "cloud" (I hate this buzz word): mail, blog, chats, voip and even version control.

With the explosion of "social buttons" everywhere, I became really more paranoid than before about my privacy. And when I see new Facebook 'Frictionless sharing' feature, I don't regret my move. What did I do? Simple, I'm just using dedicated browser profiles for each task:

  • The most sensitive: the one I use only for my mail account and nothing else. I even think to use the clever proxy hacks mentionned by Chris Evans to only authorized outbound connections to my mail provider. I didn't do it yet because it would prevent me from reading HTML mails linking to external image (OK this is not a big loss and a potential privacy issue but useful sometimes). This is a dedicated profile because if you have access to mails, you have access to every web sites (ie "I lost my password")
  • Then there is my main profile (using it for Google Reader, Google+, Twitter and Facebook). My biggest fear is to be tracked because of social buttons or because I clicked a link somewhere. So I changed my habit and instead of clicking, I drag and drop interesting pages to my sandbox profile
  • The sandbox profile is where I do searches, browsing web pages, etc. It is configured to never send anything, or to store information on disk. I never use this profile to log on a website and if I have to do that, I get back to the main profile.
To do this efficiently, when I boot, I spawn these browsers with specific profile directory (using --user-data-dir  Chrome option) and they are never closed. My window manager is configured to display the sandbox and my main profile side-by-side on the same workspace in order to switch rapidly.

For each profile, I use these Chrome extensions:
This setup works really well for me, I'm using it for more than 6 months now and it's cool :)

The next step is to use dedicated UIDs for each profile, I didn't do it yet because there is no "perfect solution" because of Xorg design: any X11 client can mess with other X11 client...

samedi 27 août 2011

net2pcap revival

net2pcap is a packet capture tool written by Philippe Biondi back in 2003. It was designed to be as secure as possible in order to be run in hostile environment. To do so, its code is minimalist without any complicate feature, the result is 406 lines of simple C. On top of its security, it is also the most reliable tool I have ever used on high traffic link regarding packet loss, even dumpcap does not perform better.

Unfortunately, feature requests and bugs were lost in the middle of hundreds of spams in Phil's bug tracker. To not lost patches, I have set up a net2pcap repository on github. This is not a fork, this is still maintained in collaboration with Phil, this is just a way to relieve him of the maintenance burden.

For those interested in the project, the following patches were already applied:

  • Privileges drop
  • Chroot
  • Compatible with 64 bits architecture
  • Large file support on x86_32
If you have any feature request or bug report, feel free to submit a ticket!

mercredi 6 juillet 2011

HOWTO authenticate ssh server through certificates

In August 2010, OpenSSH 5.6 added support for certificate authentication (release notes), unfortunately, no documentation really exists at the moment (you are on your own with sshd_config(1)ssh-keygen(1) and ssh_config(1), good luck with that).  This is a surprising because this feature is awesome for system administrators, even for a small deployment.

Certificates allow you to sign user or host keys. In other words:
  • Thanks to a unique file (CA certificate) on the server, it can accept any (signed) user keys transparently
  • If every servers' host keys are signed, clients only need to carry the CA to authenticate every servers of your network, which means no more "The authenticity of host foobar can't be established. Fingerprint is..." message
Here is the HOWTO for the latter case.

Geek summary: Sign SSHd host key


$ ssh-keygen -f ~/.ssh/cert_signer
$ scp foobar.example.org:/etc/ssh/ssh_host_rsa_key.pub foobar.pub
$ ssh-keygen -h                             \ # sign host key
             -s ~/.ssh/cert_signer          \ # CA key
             -I foobar                      \ # Key identifier
             -V +1w                         \ # Valid only 1 week
             -n foobar,foobar.example.org   \ # Valid hostnames
             foobar.pub                       # Host pubkey file
$ scp foobar-cert.pub foobar.example.org:/etc/ssh/ssh_host_rsa_key-cert.pub

On foobar.example.org, add "HostCertificate /etc/ssh/ssh_host_rsa_key-cert.pub" in sshd_config and reload sshd. Now, configure the ssh client to use this authority:

$ (  echo -n '@cert-authority * '; \
     cat ~/.ssh/cert_signer.pub ) > ~/.ssh/known_hosts_cert
$ ssh -oUserKnownHostsFile=~/.ssh/known_hosts_cert foobar.example.org

At this point, you can connect to every servers without any annoying messages. You don't even have to care when the server is replaced without conserving its old ssh keys.

lundi 11 avril 2011

no-release of seccomp-nurse


This post in a nutshell
This was a draft since my presentation at Ekoparty, I will force myself to not procrastinate this time. This post announces the no-release of seccomp-nurse (it is not a release because it is still an advanced proof of concept). Quick links:

seccomp-nurse is a generic sandbox environnement for Linux, which doesn't require any recompilation. Its purpose is to run legit applications in hostile environment, I repeat, it is not designed to run malicious binary.

lundi 3 janvier 2011

Linux Security, one year later...

This post (tries to) describe what happened in 2010 about GNU/Linux security. What this post is not is a long list of vulnerabilities, there are some people doing it way better that me.

The first part of this post is dedicated to new vulnerability classes where the second one focuses on the defensive side, analyzing improvements made to the Linux kernel. Before closing this post, some selected quotes will be presented, pointing the finger at some of the Linux failures.

This post being (very) long and being syndicated by a few "planets", I will cut this post on my feed, even if I know that a lot of people dislikes this behavior.