The Security Struggle with Lisp

From Soma-notes
Revision as of 11:42, 29 July 2021 by Soma (talk | contribs)
Jump to navigation Jump to search

Anil Somayaji, July 29, 2021

Recently I read the transcript of Rich Hickey's 2017 talk on Effective Programs, which really was a talk about the benefits of Clojure (as a kind of Lisp and as its own thing). He made several points that resonated with me, including:

  • Type systems are partial, incomplete specifications of program semantics, and so time invested in using complex type systems are at most a partial solution, one that can have a high cost.
  • Strict type systems can cause problems when trying to express communication in heterogeneous, distributed systems.
  • Programmers can be sucked in to solving puzzles that don't actually help address the problem at hand.

But what struck me about this essay was that he discussed communication and distributed systems without making a single reference to security or trust. And this got me thinking.

I've long been a fan of Lisp and Lisp-like systems, and when I develop in other languages (which is almost always) I find myself trying to use techniques that I first learned with Lisp and Scheme. However, in the world of security, the values that are celebrated by Lisp-like systems are denigrated if not outright rejected. For example, many security practitioners have a strong aversion to treating code as data, because then attackers can inject data and turn it into code, subverting the security properties of the system. As a security measure, data pages in process memory are no-execute by default nowadays and code pages are read only. Systems that want to treat data as code, such as just-in-time compilers, must constantly switch pages between being writable and executable. Anything that is truly Lisp-like, however, treats code as just another data structure to be manipulated by code and even includes facilities for dynamically changing the semantics of code on the fly. Such mechanisms can be amazingly powerful in the hands of a skilled developer; the same mechanisms, however, can be equally powerful in the hands of an attacker.

In his talk, Hickey discusses how Clojure is good at interacting with other systems because it assumes an open world while classic strongly-typed systems assume a closed world. If the entire solution is in a given language, then strong typing can be used to assert relationships consistently throughout the code base. In an open world, however, your code is always a partial solution embedded in a larger system, and as such, you'll often have to work around the type system in order to express interconnections with those other pieces.