Skip to content

Instantly share code, notes, and snippets.

@aphyr
Created October 3, 2011 05:34
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save aphyr/1258495 to your computer and use it in GitHub Desktop.
Save aphyr/1258495 to your computer and use it in GitHub Desktop.
The riak-users list receives regular questions about how to secure a riak
cluster. I'd like to take a step back and discuss what application security means in general, and talk about what layers you can implement various security policies at.
Theory
======
You can skip this, but it may be a helpful primer.
Consider an application composed of agents (Alice, Bob) and a datastore (Store). All events in the system can be parameterized by time, position (whether the event took place in Alice, Bob, or Store), and the change in state. Of course, these events do not occur arbitrarily; they are connected by causal links (wires, protocols, code, etc.)
If Alice downloads a piece of information from the Store, the two events E
(Store sends information to Alice) and F (Alice receives information from
store) are causally connected by the edge EF. The combination of state events with causal connections between them comprises a directed acyclic graph.
A *secure* system can be characterized as one in which only certain events and
edges are allowed.
A system is *secure* if all possible events and edges fall within the
proscribed set.
Strategies
=====
There are a couple of common ways that security can fail. Sometimes the system, as designed, allows insecure operations. Perhaps a check for user identity is
skipped when accessing a certain type of record, letting users view each
other's paychecks. Other times the *abstraction* fails; the SSL channel you
presumed to be reliable was tapped, allowing information to flow to an
eavesdropper, or the language runtime allows payloads from the network to be
executed as code. Thus, even if your abstraction (for instance, application
code) is provably correct, it may not be fully secure.
There are some overall strategies you can use to mitigate these risks. One of
them is known as *defense in depth*. You use overlapping systems which prevent
insecure things from happening at more than one layer. A firewall prevents
network packets from hitting an internal system, but it's reinforced by an SSL
certificate validation that verifies the identity of connections at the
transport layer.
You can also simplify building secure systems by choosing to whitelist approved
actions, as opposed to blacklisting bad ones. Instead of selecting *evil*
events and causal links (like Alice stealing sensitive data), you enumerate the
(typically much smaller) set of correct events and edges, deny all actions,
then design your system to explicitly allow the good ones.
Re-use existing primitives. Standard cryptosystems and protocols exist for
preventing messages from being intercepted, validating the identity of another
party, verifying that a message has not been tampered with or corrupted, and
exchanging sensitive information. A lot of hard work went into designing these systems; please use them.
Create layers. Your system will frequently mediate between an internal
high-trust subsystem (like a database) and an untrusted set of events (e.g. the
internet). Between them you can introduce a variety of layers, each of which
can make stricter guarantees about the safety of the edges between events. In th
e case of a web service:
0. TCP/IP can make a reasonable guarantee that a stream is not corrupted.
1. The SSL terminator can guarantee (to a good degree) that the stream of bytes you've received has not been intercepted or tampered with.
2. The HTTP stack on top of it can validate that the stream represents a valid HTTP request.
3. Your validation layer can verify that the parameters involved are of the correct type and size.
4. An authentication layer can prove that the originating request
4. An application layer below that can verify that the parameters represent a va
lid
Minimize trust between discrete systems. Don't relay sensitive information over channels that are insecure. Force other components to perform their own authenti
cation/authorization to obtain sensitive data.
Finally, I advise maintaining a comprehensive set of tests to experimentally ver
ify the correctness of your system. Probabilistic methods like Quickcheck or fuz
z testing can be useful here.
Databases
=====
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment