strugee.net

Posts categorized as "security"

Default-secure systems

So recently I presented on operational security and then started in on the nightmare that is HTTPS deployment. And like I did with language-level security (I still need to write part 2 of that post), I thought to myself, this is so difficult. Why isn't there something that will do this for me? That's what my latest project is.

Here's the tl;dr:

type(app)
=> Django/Express.js/etc. app
secure_system(app)
=> Docker image

Or in other words, you'll be able to take an existing web app that you've written, run it through this system, and it will spit out a complete, reasonably-secure system image.

Let's step back.

The status quo

Currently, when a developer wants to run a web app, they can either use something like Heroku, which is fully manged, or a VM from DigitalOcean or Amazon EC2 or something. There are a variety of reasons you might not want to use Heroku, but the only other option is a VM - and with a VM, you get a bare system where you have to set up everything from scratch. Lots of developers just don't have the operational experience to do this properly or securely, but it's not like they can go and get an operations team to do it for them. So they end up with systems that may have active security problems as well as little to no defense-in-depth mitigations for when security inevitably fails. Security is just another operational concern the developer has no time and no expertise to deal with, so it just doesn't happen. The developer spins up a VM, gets it to where it "works" and then moves on. This is not good enough.

I don't want to create a false dichotomy, though: this is not the developer's fault. Everyone has conflicting priorities and it's unreasonable to expect the developer to spend lots of time learning to administrate systems so that they can then spend even more time, you know, administering systems. The problem is that there just isn't enough options available - we have to provide something better.

A middle ground

This is what my project is about: creating a middle ground between fully-managed deployment platforms and barebones, setup-from-scratch VMs.

This project rests on the idea that operational security (at least, in a single-server, single-admin context) flows from consistency, least privilege, and proactive, defense-in-depth security measures. Here are a couple core design goals:

  1. Meet developers where they are. Configuration management like Puppet is a great way to enforce consistency, but it adds a level of indirection and is just another thing that people running hobbyist projects don't have time to learn.
  2. Tight integration with apps - this excludes more obscure types of web applications, but gives us a better footing to set up a solid deployment environment. It also may let us integrate more tightly with things like Content Security Policy in the future.
  3. Support virtual hosting. The ability to run multiple apps while paying for a single VM is a compelling reason people go with VMs over e.g. Heroku - we won't be helping anyone if we leave this out.
  4. Upgrades are optional. Any system image created by this project will present a system that is organized and can be maintained and modified by hand without breaking everything.
  5. Upgrades are possible. Tight app framework integration will aid with putting data into well-known places that can be backed up and migrated to a new image generated by a newer version of this system.
  6. Not designed for "real" production environments. Any project that has a dedicated operations person should not be using this; they should be rolling their own custom environments with something like Puppet. Accordingly, there won't be compromises in security in favor of flexibility - it's designed to cover 75% of cases "pretty well", which is still better than the status quo for smaller projects (almost 100% of cases don't have any security at all).

I'd also like to highlight one really important decision: the output is complete system images. Probably at first this will mean Docker containers but this could easily be turned into VM images. This is a critical part of the design because it allows us to make broad, sweeping changes - for example, preferring system components written in memory-safe languages, replacing OpenSSL with LibreSSL, or creating systemd unit files that lock down service runtime environments to reduce the impact of a compromise. These improvements aren't possible unless we control the whole system. And because upgrades are optional but possible, the developer can get security improvements by "just" upgrading a component that they use, in the same way that they'd upgrade a library or something, as opposed to security being a continuous process they have to worry about. Again, obviously not perfect - but much better than the status quo.

I hope to have a MVP out Real Soon Now™. But in the meantime, if you have thoughts, feel free to reach out.


New programming language part I: Handlers

So my latest project at the Recurse Center is a new programming language, as yet unnamed. Basically this was inspired by my security design presentation in which I laid out a couple ways you can improve programs' security designs, like process separation. And it occurred to me: why is this so difficult? Something should be doing this for me. Enter... whatever the hell I end up calling my language.

One of the most important building blocks of the language is something that I'm currently calling a "Handler". A Handler is basically a segregated piece of application code that handles some task or problem domain. For example, a Handler for outgoing DNS requests (syntax subject to change, obviously):

Handler DNS {
    function getAddressFromHostname(hostname) {
        // Very much pseudocode - all function calls here are example OS calls

        sendDnsQuery(hostname);
        while (!haveDnsResult()) {
            sleep(1);
        }
        
        return getDnsResult();
    }
}

This Handler has one simple method, getAddressFromHostname(). It sends a DNS query, blocks until it has a result, and then returns the result.

What's cool about this Handler is that it will be run in its own process - in other words, each Handler is automatically transformed into a privilege-separated process. However, getAddressFromHostname() can still be called from other, high-level Handlers! The language will do all the data marshalling for you, so from a language perspective it looks like a regular function call even though in practice it's going cross-process.

Now, let's improve our Handler a little bit. It's pretty unfortunate that we can only make one DNS request at a time (since it's blocking), so let's use an event loop.

Handler DNS is eventLoop {
    function getAddressFromHostname(hostname) {
        // Still pseudocode

        return sendDnsQuery(hostname, function(address) {
            return address;
        });
    }
}

We specified that the DNS Handler is an event loop, so the language automatically set up a Node-style event loop - we never actually called anything to enter an event loop, it just sort of happened as a construct of the language. Note also the nice async-aware return syntax - the result of sendDnsQuery() is returned to getAddressFromHostname()'s caller, and the result of sendDnsQuery() is specified by the return value of the anonymous function callback.

We can improve correctness even more by specifying that the Handler is not allowed to make syncronous I/O calls at all:

Handler DNS is eventLoop, async {
    // ...
}

Handlers let you pick and choose different elements and design choices for different parts of your application. For example, if you had a Handler responsible for processing data, it might make sense to restrict it to being entirely functional:

Handler incomingData is functional {
    // ...
}

In such a Handler, any functions with side effects wouldn't be callable, enforced at compile-time (possibly parse-time, depending on whether I can make it compiled or not given the type system). Perhaps you want to spawn a new sandbox process for each piece of incoming data (OpenSSH does this, for example, when first receiving authentication data from untrusted users):

// The `ephemeral` keyword will probably be something better, but for now...
Handler incomingData is functional, ephemeral {
    // ...
}

If your application requires root - for example, if you were writing an NTP daemon that needed to call setTimeOfDay() - that's also specified at the Handler level:

Handler incomingData is root {
    // ...
}

This should give you some idea of why Handlers are really interesting, even beyond the process separation concept that underlies them. (It's also worth noting that while I've focused mostly on daemons, this can also be used to securely implement e.g. file.) I'm really excited to get these ideas out there so I'll stop for now, but pretty soon I'll write another blog post talking about the type system.


Surveillance priorities

For several years now I've been really interested in technology policy - things like security, privacy and censorship, and especially how those things relate to both mass surveillance and freedom-respecting software. That's why I follow organizations like Fight for the Future and the EFF, and why I e.g. participated in the movement to stop SOPA and PIPA, the internet censorship bills.

But a week or so ago I had a realization: I'm not interested in surveillance law anymore.

It's clear to me that Congress is completely busted. The 113th Congress came very, very close to being the least productive Congress in modern history. Our current Congress isn't particularly good either, although they are (as far as I know) not as bad as the 113th - but they're still not good enough that I'm confident in their ability to actually, you know, pass laws. Even if we could get Congress to pass laws at all, it's unclear whether we could actually get them to pass laws curtailing mass surveillance. Over and over again we see Congress trying to pass misguided laws that weaken encryption, damage the DNS, and do all sorts of other seriously nasty (and hacky!) things - it just doesn't seem very reasonable to me to assume that they'd change their minds and decide to do (what we think is) the right thing[1].

This is why I'm not interested in surveillance law anymore. I find it to be a waste of time. Instead, I've shifted my focus towards systems that are fundamentally designed to resist surveillance and censorship. That's why I advocate for Signal and why I work on pump.io: because these are both systems designed from the ground up to, among other things, essentially be unaffected by surveillance law. Who cares if Congress passes a law that says they can surveil pump.io users? Congress saying a bunch of words doesn't change the fact that technically speaking, that's quite hard to do. Certainly it's more difficult than surveilling e.g. Facebook.

As Moxie Marlinspike puts it in this talk on PKI's flaws and an alternative system called Convergence:

And, you know, with this legislation that's been coming up recently like COICA and PROTECT IP and this kind of thing, you know - to me the real lesson here isn't whether this passes or not because there's been, you know, some kind of heroic efforts to prevent this legislation from going through. But I think, you know, the thing to take away from this is that they're trying. To pass regulation that messes with this stuff. And maybe one day they'll succeed.

Trying to make Congress do the right thing is, I feel, akin to an endless arms race: they don't seem to be getting the message and it's doubtful that they'll stop in the near- or medium-term future.

A much better solution is this: implement secure-by-default, freedom-respecting, encrypted and/or federated systems, and be done. Forever.

[1]: honestly, I think a big problem with this is that a lot of Congress is old white guys. Emphasis on old. The problem of people in the legal sphere not understanding technology, especially technology relating to security, privacy and encryption, has cropped up before. Consider, for example, the judge who ruled that a Tor user had "no reasonable expectation of privacy" because he literally could not wrap his head around how Tor worked and what the FBI did.


Pump.io 1.0.0 is now available!

Pump.io 1.0.0 is officially available! Whoooo!

I just wanted to write up an announcement real quick to celebrate. Here's a sample what's gone into this release:

  • Node 4.x support
  • Lots of security improvements including a better cross-site scripting scrubber and security-related headers that help protect the web UI (most notably, the web UI now declares a Content Security Policy)
  • Minor improvements to the API to make it (slightly) smarter
  • LibreJS support
  • Numerous dependency upgrades, most notably Connect
  • And of course, tons of minor bugfixes and improvements

For more details, see the brand-new change log.

And of course since we're now past 0.x.x releases, we're now officially making a commitment to the community to make only API-compatible changes going forward (or at least, until 2.0.0!).

As this release does improve security and fixes a lot of bugs, node administrators are encouraged to upgrade as soon as possible. If you have a global, npm-based install, you can upgrade with:

sudo npm install -g pump.io

And with a source-based install:

git pull
git checkout v1.0.0
npm install --production

If you're upgrading from 0.3.0, everything should Just Work(tm). Don't forget to restart your daemon!

One final note - the rumors are true. While we're not doing so yet, we are, in fact, planning to deprecate running under Node.js 0.10 and 0.12 very soon. Also, if you upgrade to Node.js 4.x early, the new, better XSS scrubber will be enabled - however, be aware that pump.io is far less tested under Node.js 4.x and you are likely to run into more bugs than you would under 0.10 or 0.12. This is an unfortunate situation, but sadly there's really nothing to be done about it. :(

Special thanks to Menno Vossen, Laura Arjona, Evan Prodromou, Jan Kusanagi and all the other volunteers who did so many different things to make this release happen. It truly wouldn't have happened without you.

Enjoy the release!

With <3,

AJ


~