Safety and Security
from a Language Engineering Perspective
A brief heads-up on today’s WJAX talk
When I started my writing
here on Medium, I planned to write original stuff (as I did in all my posts so
far), but also to “reuse” other stuff I’ve been producing for other media. This
is the first post in this second style; it’s shorter, because it references
other material, slides in this case. I gave a talk at the WJAX conference today
with Bernd Kolb called Safer Software Through Better Abstractions and Static Analysis.
A few years ago, Gary McGraw
published a book called Software
Security, where he looks at flaws in the implementation of a software
system that can be exploited maliciously. Traditionally, security is seen more
like a process issue (education/awareness, reviews, pen testing) or a matter of
architecture (authentication, encryption, DMZs, runtime monitoring). And of
course, both of those are very relevant. But bugs in the implementation are also
a problem as we know from loads of security exploits in SSL libraries (Heartbleed, goto fail) or blockchain contracts (the DAO and
several other more recent ones). Many others examples exist. I liked Gary’s
book, and we expand on this perspective by looking at language extensions that
prevent security problems constructively, and to other extensions that make
analysis or review simpler. Of course, many of the ideas are “the usual
language engineering stuff”, but applying them to security is relevant, I
think.
Check out the slides here; I add a few more comments below.
Here are some of the core ideas:
· Security, Safety and Robustness cannot be
separated. In some sense,
security are maliciously exploited robustness issues, safety issues are just
“unfortunate”. You also hear sentences like “this exploit constitutes a massive
safety risk”, further illustrating the relationship. Yes, there are some
particular security risks as well (e.g., making sure key material cannot be
read from a memory image). But there’s a lot of overlap.
· By using better languages, many low level
errors are avoided. Things
like mbeddr’s statemachines, a first-class extension for gotofail-style error
handling or wiping of the stack when a leaving a scope (for key material) can
be supported by the language directly.
· Advanced type systems, such as those that support option
types (to avoid null dereferencing), number ranges (to avoid overflows) or
support tagging (to track tainted data) are relatively easy to build and are
a quick win.
· Program verification techniques, such as SMT solving or model checking, can find non-trivial
problems. Sure, trying to use those for the high-hanging fruits is very
non-trivial. But the low hanging ones are easier to reach and should be
harvested.
· High Quality Tests are crucial. Measure coverage, generate test cases,
use mutation testing. The tools exist. Learn them!
· Better abstractions and notations, such as tables, state machines, or
mathematical formulas are much easier to read than “code”. They make
review easier, and thus, make the code more trustworthy.
· Make programs simulatable by stakeholders, because, again, this helps program
understanding and thus reduces the likelihood of unintended behaviors.
Just to repeat: we are not
suggesting that “classical” security techniques like penetration testing are
not needed or not useful. But we do think the stuff in these slides is very
relevant as well.