Languages and security: a short reading list

Ivan Krstić, former director of One Laptop per Child and all around computer security guru, has a few humorous thoughts on the current intersection between security and programming language design in Languages and security: a short reading list.

If I had to grossly overgeneralize, I’d say people looking at language security fall in roughly three schools of thought:

1. The "My name is Correctness, king of kings" people say that security problems are merely one manifestation of incorrectness, which is dissonance between what the program is supposed to do and what its implementation actually does. This tends to be the group led by mathematicians, and you can recognize them because their solutions revolve around proofs and the writing and (automatic) verification thereof.

2. The "If you don’t use a bazooka, you can’t blow things up" people say that security problems are a byproduct of exposing insufficiently intelligent or well-trained programmers to dangerous language features that don’t come with a safety interlock. You can identify these guys because they tend to make new languages that no one uses, and frequently describe them as "like popular language X but safer".

3. The "We need to change how we fundamentally build software" people say that security problems are the result of having insufficiently fine-grained methods for delegating individual bits of authority to individual parts of a running program, which traditionally results in all parts of a program having all the authority, which means the attack surface becomes a Cartesian product of every part of the program and every bit of authority which the program uses. You can spot these guys because they tend to throw around the phrase "object-capability model".

Now, while I'm already grossly overgeneralizing, I think the first group is almost useless, the second group is almost irrelevant, and the third group is absolutely horrible at explaining what the hell they’re talking about.

Tongue in cheek? Absolutely, but probably not that far off when it comes to the languages that the mainstream uses today (except, arguably, for the quibble that #2 is applied to some extent in all of the most popular "managed" language runtimes).

As the name of article suggests it has some good links for further study into current lines of research.

Which directions are likely to be the most fruitful in the coming years? And what other directions are being missed?

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.

Offline Security and More

Though some people on the 'erights.org' sites are working on them, the sort of offline, blinded, transferable exclusive rights needed for e-money, vending tickets, and secure operation during disruptions that partition the network. This is a variation of item (3), of course, but is something I'm excited about digging into once I'm in a position to utilize them (which won't be soon).

Some of my own work has been towards assigning trust (via certificates) to platforms holding a public key, along with assigning trust requirements to secrets (which are simply identified as actor names rather than data). The idea is to prevent platforms without the required trust certificates from accidentally learning a secrets while simultaneously supporting automatic mobility and distribution. (It does not resist inside jobs.) Use of E-style 'vats' is (IMO) too cumbersome for network distributed data fusion or command and control.

An area that hasn't been touched in the above list is auditing. To perform auditing requires contracts (or expectations) with measurable requirements and meaningful penalties. Seeing these integrated into programming languages is not something I've studied deeply, but is an area I think worth looking into as we start using languages that close off the primitive vectors for attack. Auditing can potentially be heuristic and can raise alarms rather than close off capabilities, and can greatly aide human work in detecting or alerting them to potential insider attacks.

Finally, there is a great deal more work to do with ensuring service is provided: accessibility, resistance to denial of service, graceful degradation, and rapid recovery after situation improves are ALL important to computer security as it is traditionally defined.

... and more

A couple more areas of study that also imply 'groups of people' and how they understand security:

IP protection - keeping work from being stolen while allowing it to interact with client machines. Usually requires a trusted computing base, but other approaches studied include various forms of secure obfuscation that guard the algorithm from casual reverse engineering (but not the input or output). For the most part I'm not fond of this form of security, which is likely why I forgot to mention it.

Secure computation on untrusted machines - transforming difficult problems so both the problem and answer is secured, then partition the problem out to untrusted computation resources (grids, end-user machines, etc.) to take advantage of said computation resources without leaking any secrets. Fairly useful for 'embarrassingly parallel' problems. Example application would be running AI decision algorithms or certain classes of computations regarding updates of a large virtual world while taking advantage of the powerful CPUs owned by the players.

Anti-cheating - peculiar to the gaming industry, and all about preventing players from obtaining "unfair" advantages over other players. This is a frustratingly difficult problem given that it is balanced against the need to pre-cache data and simplify computations to achieve reasonable performance. Example problems: how do you keep the user from, say, taking advantage of disabling or making semi-transparent textures in the hardware in order to see through walls via wireframe? Can you level lags? Can you detect a headscript (a script that helps a player in a shooter game target the opponent's heads)? I suspect that most of the problems here are going to be impossible to solve without controlling the hardware.

School (3): Object capabilities

... security problems are the result of having insufficiently fine-grained methods for delegating individual bits of authority to individual parts of a running program, which traditionally results in all parts of a program having all the authority ...

Authors of a program who let third parties build plugins can use ocaps to prevent trojan attacks. Example of what NOT to do: Firefox.

Now, while I'm already grossly overgeneralizing, [snip] the third group is absolutely horrible at explaining what the hell they’re talking about.

Ocaps are for controlling the interface. The model is fine grained because that is its inherent nature.

I don't see how ocaps change the way we program. Does anyone not ever think "should object A be allowed to access object B in this manner?" Like everything else in security, it is a trade-off. I may be willing, to save precious time, to risk that my implementation of A has no bugs and will not allow a privilege escalation attack through B. (My confidence is due to me being an übermensch and I can never make mistakes. However, school (1) may allow a lesser being the same.) Case study: buffer-overflow attacks.

OT: I would like to see a greater effort on libraries bringing ocaps to programs written for common languages rather than solely making new languages. I would do this myself if I understood the ramifications better.

libraries bringing ocaps to

libraries bringing ocaps to programs written for common languages rather than solely making new languages

This can be done in memory-safe languages (where you can't forge capabilities by pointer arithmetic) under the additional conditions that one eschews all static variables and cuts off all access to 'global' capabilities to the Operating System as are available through 'System' and such. (Instead, 'System' would be a new object passed to 'main' upon initial startup - at least conceptually, if not in implementation. One could wrap 'System' in a non-static object via library.)

I'm not certain how one would go about adding this to existing languages by use of libraries, but a viable alternative might be source and (for 3rd party plugins) bytecode verification.

About the only component I can see being put into a library would be a communications protocol for capability-secure communications, similar to VatTP used for E language. (VatTP could be adopted, instead.)

I don't see how ocaps change

I don't see how ocaps change the way we program. Does anyone not ever think "should object A be allowed to access object B in this manner?"

Capabilities are inherent to non-trivial programs; the question is really at what level should we manipulate them (who does the enforcement?). The ocap community is traditionally at the dynamic end, where the programmer does, but you can imagine an XACML-like system for objects where authority is specified by orthogonal policies and enforced with transparent means. In both, we are indeed manipulating ocaps, but 1) I would claim only the former is 'programming' (imperatively) with ocaps and 2) forces the developer to enforce an implicit policy, which is a change in how he/she programs.

I would like to see a greater effort on libraries bringing ocaps to programs written for common languages rather than solely making new languages. I would do this myself if I understood the ramifications better.

Joe-E and Caja are two popular examples of this, leaving, in terms of mainstream targets .NET and SQL -- not so bad :) Focusing on new languages helps iteratively figure out which features are safe.

Somewhat unifying your questions & comments, we recently wrote a paper on distributing objects in JS (e.g., sharing DOM nodes between principals in a browser such as different scripts, frames, and extensions). Instead of directly passing objects from one principal to another, we showed how one principal may share a membrane with another. (a membrane is ocap speak for a shadow proxy wrapper around an object that lazily generates more shadow proxies whenever a proxied method would return a reference to a non-proxied object, guarenteeing raw references are always wrapped in an un-unwrappable proxy when passed to the receiving principal). Furthermore, we showed that, instead of creating a generic system of proxies that are either all on or off (one 'gatekeeper'), we generalized the set of proxied objects to be controlled by a (mutable) declarative policy that the principal doing the sharing can specify. Furthermore, instead of the policy being permit/deny decisions, we made it an advice system (e.g., you can log any calls to some method invoked by the receiving principal). Stepping back to your post, that means we have 1) advocated programming securely by sharing (declaratively) custimizable views, changing how we program, and 2) helped make the existing JS language safer through library support.

OT: As is usual with these things, it also helped make clearer fundamental security flaws in how JS is implemented or deployed (e.g., every principal should have control of a unique {}.prototype or otherwise be able to seal it, to avoid prototype poisoning attacks) -- but it's hard to do a rigorous security proof when the language's operational semantics is 70 pages.

(edited to fix quoting)

4. Three words ...

Rylands v. Fletcher.

Someday an enterprising member of the plaintiff's bar will decide that those SHOUTY DISCLAIMERS we are all used to seeing but not reading aren't worth the bits used to encode them, and then we'll see secure, reliable, maintainable software constructed by actual engineers.

And I'll probably have to find another scam^H^H^H^Hline of work.

Was this parody?

I agree that the current state of affairs surrounding license agreements and other forms of legal-ease is rather nonsensical, but moving to strict liability for software makers in all cases seems equally so. Analogous reasoning to what you've written is that if we just held doctors accountable, people wouldn't die in hospitals.

Haha, only serious.

I think there was some humor intended, though to make a serious point. I tend to agree with both you and John. Legislation might motivate people to take their work more seriously, but you cannot simply legislate technical solutions.

I found the Rylands vs Fletcher case fascinating... but then I find industrial accidents in general to be fascinating. It very much reminds me of the Lake Peigneur disaster back in 1980, which was far funnier, and more spectacular. Fortunately no humans died in either incident.