The slides of my 'defeating trojans' talk at the OHM2013 festifal in Geesterambacht.
The talk is about how applying encapsulation, decomposition, attenuation and, most important of all, delegation to multiple granularity levels can lead to tighter, more user friendly and more flexible security. How applying these general concepts can help reduce the size of the trusted code-base and why this is essential if we want to defeat Trojans and mitigate the impact of software vulnerabilities.
After laying down some general guidelines for achieving this, the talk goes into how the AppArmor/MinorFS/E stack and to a lesser extend the AppArmor/MinorFS/C++ stack allowed these concept to be applied for building custom high integrity systems by 'taming' the system's persistent mutable state. The talk is than concluded with an outline of how the upcoming MinorFS2, with the help from AppArmor, will try to retrofit this taming of mutable state to programs not explicitly written to use MinorFS, while at the same time providing convenient APIs for interpreters and programs with special needs, thus creating an essential building-block for defeating Trojans and mitigating the effects of software vulnerabilities.
3. Lets get some facts straight
● The user is NOT the weakest link !
4. Lets get some facts straight
● The user is NOT the weakest link !
● Sharing security tokens is NOT stupid !
5. Lets get some facts straight
● The user is NOT the weakest link !
● Sharing security tokens is NOT stupid !
● Security and usability are NOT mutually
exclusive.
6. Lets get some facts straight
● The user is NOT the weakest link !
● Sharing security tokens is NOT stupid !
● Security and usability are NOT mutually
exclusive.
● MOST software vulnerabilities are
irrelevant.
7. Delegation
● Users are 'programmed' to handle delegation.
● Delegation != Abdication
– Delegate 'authority' NOT 'identity'
● Authority must be decomposable.
● Authority should be attenuable.
● Authority could be revocable.
20. Public/global mutable state
● Makes composite systems hard to analyze or
review.
● Makes composite systems hard to test.
● High potential for violating the Principle of Least
Authority.
● Giant hurdle for reducing trusted code-base size.
23. The file-system as global mutable state
● Why does Sokoban
need access to
$HOME?
24. The file-system as global mutable state
● Why does Sokoban
need access to
$HOME?
25. The file-system as global mutable state
● Why does Sokoban
need access to
$HOME?
● Why does Bitcoin
need to store
sensitive data in
$HOME?
26. The file-system as global mutable state
● Why does Sokoban
need access to
$HOME?
● Why does Bitcoin
need to store
sensitive data in
$HOME?
● Why is Sokoban part
of Bitcoin's trusted
code-base?
27. The file-system as global mutable state
● Why does Sokoban
need access to
$HOME?
● Why does Bitcoin
need to store
sensitive data in
$HOME?
● Why is Sokoban part
of Bitcoin's trusted
code-base?
● Programs need
privacy too!
28. Weak links
● The user
● Disregard for socio-genetic security-awareness
● Identity centric security models
● Single-granularity abstractions
29. Weak links
● The user
● Disregard for socio-genetic security-awareness
● Identity centric security models
● Single-granularity abstractions
● Public/global mutable state
30. Weak links
● The user
● Disregard for socio-genetic security-awareness
● Identity centric security models
● Single-granularity abstractions
● Public/global mutable state
● Massive size of trusted code-base
31. Weakest link?
● The user
● Disregard for socio-genetic security-awareness
● Identity centric security models
● Single-granularity abstractions
● Public/global mutable state
● Massive size of trusted code-base
32. Weakest link?
● The user
● Disregard for socio-genetic security-awareness
● Identity centric security models
● Single-granularity abstractions
● Public/global mutable state
● Massive size of trusted code-base
33. Basic guidelines
● Use homo-sapiens friendly security abstractions
● Use cross-granular abstractions
● Don't overuse identity
● Limit public/global mutable state
● Share authority tokens
– Decompose and/or attenuate authority
– Use the Principle Of Least Authority.
● Minimize the trusted code-base
34. Capabilities
● Authority-only security tokens (no identity)
● Capabilities both designate and authorize
● In fact: designation IS authorization
● Cap patterns ∩ Social patterns = significant
● Dynamic least authority.
35. Sparse capabilities
● Capability 'as data'.
● Basically a strong password without an identity
● Some well known examples
– Rumpelstiltskin
– https://docs.google.com/file/d/0B_sqxoHXGz5ZcEhCOMJWRzRjbmM/edit
● CapFS:
– /minorfs/cap/rw-5BA7FFDP4HM1L887BZAK7G857GKJHAUEAK992HCH5DGH59GHWB1S
● Non human-memorable 'authority' token
36. Object capabilities
● More secure than sparse capabilities
● Basically object-reference as capability
● Ambient-authority and static-mutable-state free
subset of Object Oriented Design principles.
37. Process-Persistence
● Transparent serialization for conceptually
persistent processes.
● Delegated authority survives reboots.
● E-Language
– Combines Persistent VATs with object capabilities.
● Ken
– Crash-restart resilience for distributed applications.
● Where do we securely store process
serialization?
39. MAC & (extreme) DAC
● Classic UNIX DAC and MAC are a bad fit.
● SELinux MAC and sparse-cap DAC are a bad fit.
● AppArmor: Permissive-privileges MAC model.
● AppArmor MAC and sparse-cap DAC are
complementary.
40. AppArmor
● Security module (MAC) for Linux kernel.
● No MSc required for profile management.
● Simple permissive-privileges
● Restricting 'possibly vulnerable' software.
45. MinorFS & E
● MinorFS+AppArmor:
– Pseudo-persistent-process private $HOME
– Reduces trusted code-base for private persistent
mutable state.
● E-Language:
– Uses protected private process serialization
– Further reduces the trusted code-base
46. MinorFS and native code
● C++
– No memory safety
→ No trusted-code-base reduction
→ Reduced memory integrity
– Native → Easy PP-PID calculation for MinorFS
– RAII → Non-memory resource management integrity
– Templates → Generics as code-base reduction tool.
● Multi-process programs
– Use processes as overweight object
– Delegate attenuated sub-trees between processes
47. '..' considered evil
● Special '..' directory normally designates parent
● Capabilities: designation implies authorization
● The '..' brakes delegation of sub-trees.
48. CapFs and '..'
● /minorfs/cap/
– Dead-end stub '..' for any CapFS node
– Listing returns an empty directory.
49. MinorFS (1) shortcommings
● Poor fit for desktop/console applications.
● Poor fit for most retrofitting purposes.
● No read-only attenuation
● Poor scalability and performance
● Tricky installation dependencies
50. MinorFS2: goals and use-cases
● Defeating Trojans: retrofitting tamed mutable state
● Standard dependencies (Ubuntu/Suse)
● Confidentiality on shared network storage
● Scalability and performance
● Read-only attenuation
● Convenient GranFS/CapFS APIs
– NodeKen like server platforms
– Multi-process browsers
– Bitcoin like systems
51. MinorFS2: performance & scalability
● AES256 encrypted overlay
– Yet : sparse == sparse
● Sqlite based lookups → digest-only lookups
● Client side attenuation.
● Perl → C++
52. CapFS2: Rumpelstiltskin tree-graph
● HMAC/SHA256 operation based
● Client or server side read-only attenuation:
– ROcap = H(“#ro”,RWcap)
● Server side decomposition:
– childRWcap = H(childname + H(“#ro”,parentRWcap), secret)
– ChildROcap = H(“#ro”,H(childname + parentROcap, secret))
● ROcap doubles as file encryption key:
– FEK = ROcap
● Path on underlying file-system derived from FEK:
– Path = H(“#store”,FEK)
54. The '.program' convention
● Convention to create a '.program' file or directory
in the users $HOME directory.
● Base assumption:
– '.' prefixed content in $HOME assumed user+program
private
– Other $HOME content assumed user-global.
● HomeFS2:
– /minorfs/home shows merge-transform of multiple
granularity levels
– Default use of the '.' prefix split
– Config may define different mappings.
55. MinorFs2: layered design
● CapFs2:
– Encrypting sparse-friendly sparse-capability file-system.
● TmpFs2:
– Delegates process-lifetime CapFs dir to non-persistent process.
● GranFs:
– Multi-level process property registration.
– Delegates different persistent CapFs dirs using process properties.
● HomeFs2
– Creates home like view with links to GranFs delegations and $HOME
56. LibMinorFs2 (C/C++)
● Allowing simpler MinorFs awareness.
● Stub implementations non AppArmor systems.
● Query available privacy process property sets.
● Multi-level process-property registration.
● Process property set → CapFs object.
● Directory traversal/decomposition/attenuation
abstractions.
57. Roadmap
● Complete MinorFs 2.0 before the spring 2014
AppArmor feature-freeze
– Any help here is extremely welcome !
● Get MinorFs 2.0 accepted in AppArmor
● Complete MinorFS 2.1:
– More process properties for GranFS
– LibMinorFS
● Get projects to include LibMinorFs usage:
– The Dr-SES stack
– BitCoin
– Chrome/chromium
Hi everyone, I am going to talk about the role of the file-system security model in our battle against Trojans. Half a decade ago I wrote a set of user space file-systems called MinorFs that were geared towards creating high-integrity systems. At this moment I'm working on a redesign and rewrite of this system that will have a different goal: mitigating the effects of Trojans and some other client and server software vulnerabilities.
In order to solve some of the most tenacious information security problems, we need to reexamine a few widely accepted 'truths'. I'll share four insights that many of you will probably disagree with. The first half or my talk explains these insights and shows how they lead to a different set of guidelines, that are useful in solving a surprisingly large segment of the world's security problem.
Most importantly, the user is 'not' the weakest link. I'm not saying the user is a particular strong link, the user has major shortcomings and weaknesses, sure. The user however also has some untapped strengths. Strengths that we have not only disregarded, we've actually spent energy training and conditioning our users into not applying them.
One of the most harmful things we've tried to teach users the idea that sharing security tokens is stupid. Sharing security tokens is not only 'not stupid', its an essential ingredient of any security model that actually allows things to get done and to get done securely.
A third widespread misconception is the idea that usability and security are mutually exclusive.
My final controversial statement is that 'most' software vulnerabilities are in fact completely irrelevant. The exploitability of most vulnerabilities stems from a perimeter security view on the world. By taking a least authority view, most vulnerabilities are in parts of the software that should never have had so much authority to abuse.
Lets start with my users not being the weakest link thesis. Delegation is one of our users most fundamental strengths. We as humans have been cooperating in relatively secure cooperation patterns for thousands of generations. These cooperation patterns demand delegation. Non of the empires in human history could have risen without delegation. Non of them could have persisted as long as they did if delegation implied abdication, as many security people seem to think. Delegation as a concept is woven into the very fabric of our socio-genetic selves. For this, authority must be decomposable. If possible it should probably also be attenuable, and in some cases revocation can also be an important property.
So looking at weak links, we have the user...
But on the other side we have the problem that we, as information security community, are structurally disregarding the users strengths by not tapping into their built-in socio-genetic security awareness.
A second issue stems from conditioning. Conditioning can be a force for good or for bad. The classic example of conditioning is Pavlov's well known experiment. Mr Pavlov conditioned his dog to start drooling at the sound of a bell by turning the sound of a bell into a conditioned stimulus that was correlated to food.
On many occasions our security solutions, such as those by Microsoft or Ubuntu in the picture here, are doing to the user what Pavlov did with his dog. The user is conditioned to enter his or her password, click on agree, etc etc. We're conditioning the user into a much weaker link than he would be naturally. We are in fact turning the user into the perfect phishing victim
I think we can all agree on the fact that passwords suck. What we might not agree on is 'why' passwords suck. Passwords can be seen as tokens of identity, and from that point of view, its a problem that this identity can be delegated. In many cases however, passwords are also the 'only' available tokens of authority . When you look at passwords from an authority point of view, passwords still suck, but for a completely different set of reasons. The fact that they can be delegated importantly is not one of those reasons.
So when we are setting out to find a more secure alternative for passwords, better authentication would be great. But fixing just the identity side of things may actually make things worse.
The problem is that in the digital world we are using 'identity' for way to many things. We are using identity in places where in the analog world any sane person would be using a key rather than his passport and a guest-list
So if we want to replace passwords with stronger authentication , we should first think about providing a better alternative for authorization keys. We need security tokens that 'do' allow security compatible with the human talent for working with patterns of secure delegation. We need better authorization much more desperately than we need better authentication.
Taking these aspects into consideration, we can add two more items to our list of weak links.
The fact that that we are massively using an identity centric security model, also in places where an authority centric model would me more suitable.
And secondly that, with this, we are using abstractions that do not scale up and don't scale down well to other levels of granularity.
And there are more weak links. One of the most essential weak links that MinorFs tries to address for the file-system is 'public' or global mutable state.
The problems with global and static mutable state could hardly be overstated. …. Ones you manage to fully grasp the implications of this, you will realize that there is large potential in measures that encapsulate mutable state outside of the global scope.
Lets look at the concrete problem of global mutable state and the file-system. On your desktop system you run many different programs. Some of these programs need to store sensitive data, for example sparse capabilities or Bitcoin wallets. Basically the only place to store this sensitive data is the $HOME folder. We must realize that , at process granularity, this $HOME directory must be viewed as one big global variable. You have many pieces of software running on your PC including for example Sokoban and Bitcoin. Bitcoin depends on $HOME to securely store your wallet. Other software, for example distributed capability systems may rely on $HOME for storing capabilities.
Now consider the possibility that one program, for example Sokoban, somehow got trojanized. Alternatively you might have a trojan plug-in in your browser, or instead of trojans, consider exploitable vulnerabilities in clients, plug-ins or viewers.
Bitcoin and other programs use $HOME to store sensitive data. Sure, they may use crypto and password protection, but that won't stop the Trojan from making an encrypted copy, wiping the original and holding the wallet hostage. We could ask ourselves the question: why does Sokoban need access to $HOME.
But basically that is the wrong question. We're thinking perimeter security and we need to start thinking multi-granular least authority based security. There are some other questions however we 'do' need to ask.
Basically if Bitcoin is forced to store all its persistent mutable data in the shared $HOME directory, than Sokoban basically becomes part of the Bitcoin trusted code-base.
What it boils down to is that programs and processes need privacy just as that users need privacy. Without this privacy, the trusted code-base for any program that needs to store essential mutable data expands to include the code-base of each and every program running under the same user id.
So with the global mutable state issue, we can add two more weak links to our list.
The massive overuse of public or global mutable state.
And, partially as a result of this global mutable state, the fact that the size of the trusted code-base has become enormous.
We now have a list of six important and related weak links regarding information security. Witch one of these weak links is the weakest? I honestly won't dare to point a single one out.
What I do know is, that given this list, and its impact on what we ask of our user, the user won't become the weakest link until we fix each and every one of the other five issues first.
Given this list of five weak links, I've come up with a a set of six simple guidelines. If we follow these guidelines structurally as an information security community, we could potentially achieve much higher levels of security than we have now. Its my believe if we structurally apply these guidelines, it should become possible to reduce the impact Trojans and software vulnerabilities of by at least two orders of magnitude .
With these guidelines in place its time to look at the authorization tokens we so desperately need. The last few years we've seen a renaissance of a half a century old information security paradigm known as capability security. Capabilities basically are authority-only security tokens. Its intriguing to see that, there is a rather large overlap between capability patterns and social patterns patterns of delegation.
One old form of capabilities are so called sparse capabilities. A good and simple approximation for a sparse capability is the name of the evil imp 'Rumpelstiltskin' from the well known fairytale. That is, its an unguessable authority token that both designates and yields authority. A modern day example can be found in Google docs sharing links, or the links used by Mega. One problem with sparse capabilities as password replacement is that while they are strong, and are granularity agnostic, they aren't memorable. We basically need to be able to delegate the task of remembering these security tokens to 'small' pieces of 'trusted' code.
If we agree that reducing the trusted code-base size for any given unit of mutable state, than next to sparse capabilities we also should look at so called object capabilities. … There is a small set of programming languages that are called object capability languages that use these object capabilities. The most interesting one at this moment is probably the Secure EcmaScript effort.
An interesting concept related to applications holding capabilities is the concept of process persistence and crash-restart resilience. An interesting examples is 'the E-Language', an object capability language with persistent VATs. A second interesting example is the Ken library. Basically both examples use transparent serialization that conceptually allows your running program to survive reboots without the need for re-delegation. One problem, the serialization goes to the file-system and the only place to store the data is the $HOME that is shared with all other untrustworthy programs, basically defeating the trusted-code-base reduction that object capabilities gave us.
Within a single domain of administration and at relatively course granularity levels, its often a good idea to create and enforce policies that hinder the freedom to delegate. That is, creating 'mandatory' access controls. While these policies can lead to tighter security, they don't scale up that well to inter organizational interaction, neither do they scale down very well to the finer granularity levels of individual objects. Mandatory access control policies are notoriously hard to create and maintain once you start to approach the granularity levels of processes. On the other side of the granularity spectrum, cross-domain mandatory control remains a challenge
When we look at access control on Linux we see the old UNIX discretionary access controls for the file-system. When we look at sub-user authorization granularity on Linux, we get into the area of Linux security modules that implement mandatory access controls. These two models can seriously get into each-others way. The best known Linux security model without any doubt is SELinux. SELinux is amazing for military organizations and government agencies working with classified documents and security clearances. If your main concern however are Trojans and software vulnerabilities, you will want to use an alternative that doesn't require system administrators to have master degree in information security. AppArmor, used by Suse and Ubuntu Linux, is such a security module. AppArmor's mandatory model and the sparse-cap based model also happen to be quite complementary.
… While AppArmor is more aimed at protecting the system from the software and not at allowing software to protect itself from other software, there are developments coming in one of the upcoming 3.x versions that will change this in an essential way.
AppArmor allows you to create profiles that explicitly grant read or write access to specific directories. Just like capabilities, the model used is permissive-privileges based and therefore relatively easy to parse. No explicit permission means no access. In the example here we see the 'W' flag indicating for example that the programs that use this profile will have write access to $HOME and $TEMP.
As we have seen, $HOME is a pretty dangerous place to live. We have good static security from AppArmor and good dynamic security from capabilities. If we want to allow capabilities and other data that is important from either a confidentiality or integrity point of view, than we need a bridge that helps us avoid falling of the dangerous $HOME cliffs. When we add MinorFs to the picture, it becomes possible to allow capability based design, either with o-cap languages or a native priv-sep approach, to use the file-system without
To do that in a rather blunt way, we disable write access to $HOME in the AppArmor profile..
And add some access flags for MinorFs. We have a relatively broad read only priviledge for the whole of minorfs. This should allow MinorFs to delegate different private $HOME like directories to different processes. The CapFs mountpoint is given write access also, but given that a spares-cap is needed to access anything in CapFs, there is no ambient access to any global $HOME.
When we combine MinorFs with the persistent o-cap language 'E', something that was an important usecase for MinorFS1, we see that E and MinorFS are also highly complementary. As E supports the notion of having a persistent program instance, and MinorFS1 basically worked at the single granularity level of pseudo-persistent-processes, in situations where E is a viable option we see an amazing reduction of the size of the trusted code-base using the AppArmor/MinorFs/E-language stack.
Where E is absolutely amazing, there is an other, somewhat less granular way to work at reducing the size of the trusted code-base. C++ as a language has some very bad but also some very good properties from a security perspective. The lack of memory safety is an absolute horror that will basically make multi process priv-sep the only way to do any security-wise meaningful reduction of the trusted code-base. On the good side, being native makes it much simpler for MinorFs to determine a reliable persistent process id. Secondly, C++ is one of only two languages with a unified approach to resource management for non-memory resources. This property can be pretty important when trying to build high-integrity systems.
If we look at the native variant, delegating sub-trees between different processes becomes very important. Classically however every directory has a '..' entry that designates its parent. If you want to do any least authority work, the authority graph will likely need to remain a so called polytree.
CapFs basically implemented a single directed acyclic graph with a primary tree structure of directories and files, and the possibility for additional directed arcs in the form of symbolic links. Looking how this graph is projected into the primary view on the file-system, the '..' directory for an addressed node always pointed to the mount-point Listing the mount-point simply showed an empty directory. This basically means that all authority that could be implies by '..' would be nullified.
So far for the existing MinorFs1. Now before I can talk about my work on MinorFS2, I must list some of the shortcomings of the first MinorFS. ...
From this we get to the specifications, usecases and goals that I hope to address in MinorFS2. ...
When we look at the performance and scalability, these are a few of the things I'm addressing Using cryptography as a scalability measure may come as a bit of a surprise. The concept is that using encrypted overlays allows using 3th party administered network storage. Doing so should elevate scalability. ...
Getting rid of SqLite is an important scalability and performance booster. To accomplish this I'm using HMAC/SHA256 hashing in a way that auto-creates sparse-caps, crypto-keys and storage-mapping using only this one operation basically. My Rumpelstiltskin tree-graph algorithm allows for more speed improvement by allowing client side attenuation. Decomposition needs to happen server side and is a two step operation using the child node name. The attenuated read-only cap in my algorithm doubles as file encryption key, and an other hashing operation is used to calculate the file-system mapping.
While the Rumpelstiltskin tree-graph algorithm ads attenuation and better performance and scalability to CapFS, the main reason for rewriting MinorFs lies in functionality that is implemented by the other MinorFs file-systems. The fact that not just newly custom built high-integrity software needs privacy, but existing programs need it too. For some programs to take full advantage of MinorFS by using a simple API, but for most programs without making chances to the code.
One interesting insight regarding to the most basic level of privacy is the use of the '.program' convention. While we will want to make our HomeFS2 file-system configurable to map in different ways, the 'default' mapping could be that only dot prefixed files and directories at the top level are mapped to a program+uid private directory. This should catch 80%+ of all retrofitting privacy needs.
MinorFS2 will consist of four user space file-systems. CapFs2 is the sparse-cap heart of MinorFs. Two file-systems TmpFs2 and GranFs do first level delegation using symbolic links. TmpFs2 maintains process lifetime bound private directories. GranFS does so for persistent directories for different sets of process properties. MinorFS aware programs should be able to use an API to pick the post appropriate properties for their privacy needs. For retrofitting purposes, the new HomeFS2 will create a combined view using the default '.program' convention or a custom profile.
As Stated, allowing programs to become MinorFS aware is important. For this I'm planning to also create a library with a convenient API.
I hope you enjoyed this talk, and I hope some of you will keep taps on my progress on MinorFS2. If anyone is inspired by my talk and would like to contribute to my project, please come and talk to me later or send me a message. But if there is anything I hope most of you will take with you from this talk its that we should embrace delegation. The slides and some more background information is available at this url. If there is any time left for questions ….., I'dd like to know if there are any questions/You can approach me after the talk or contact me.