Created
October 3, 2011 05:34
-
-
Save aphyr/1258495 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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