OpenBSD has this reputation of having some god-like security where it's leaps and bounds above every other OS. I believe its security is actually relatively similar to alternative OSs like linux, and perhaps even less as containerization seems to be getting really popular on linux right now which allows linux to somewhat catch up to what I consider to be one of the biggest advantages OpenBSD had (pledge).
Most of the advocacy I see about OpenBSD security seems to be misleading and/or vague. OpenBSD's own website[1] proudly claims that OpenBSD has had "Only two remote holes in the default install, in a heck of a long time!". What is "a heck of a long time", and where's the info about any vulnerabilities other than an RCE in the default installation?
They still pop up every few years or so.
Patches for vulnerabilities are listed per release on https://www.openbsd.org/errata.html
If you need certificates from the Web PKI (for your SMTP server, or your IRC server, or any other TLS server, but most obviously your web server) you likely want to talk ACME to Let's Encrypt or another CA.
The popular way to do this is Certbot, a program written in Python. Clearly that's a lot of dependencies and thus potential attack surface area so not ideal.
A popular alternative is acme.sh which is Unix shell code. So this is potentially a far smaller attack surface but shell is hardly the most auditable or secure language by default...
OpenBSD ships acme-client which is written in C.
Now, acme-client uses lots of OpenBSD flavour tooling to improve on its security, components of acme-client are sandboxed off from themselves and the rest of the system using pledge() and so on such that components with access to your private keys are not also doing TCP/IP. On the surface then although it's written in an unsafe language this looks like a good trade and it exactly fits OpenBSD's approach.
However, the thing about ACME is it's built out of existing standard components such as Certificate Signing Requests. So instead of attack surface in Python, or Bash, or C, and trying to mitigate it with local sandboxing, you can choose to hand the CSRs to a completely separate system and so to literally airgap your private keys and all the TLS server code from your ACME implementation if you want.
You can use CSRs with Certbot, you can use CSRs with acme.sh, but, they aren't an option with OpenBSD's acme-client at all.
acme-client is the Beast so that a US President can be driven somewhere very dangerous and most likely get out of there alive - but just using CSRs is having him just make a video call and never leave the safety of the Oval Office.
> You can use CSRs with Certbot, you can use CSRs with acme.sh, but, they aren't an option with OpenBSD's acme-client at all.
acme-client uses a privilege separated process model (using pledge and unveil) so that private keys are never loaded or accessible to the network-facing process.
And it's not just acme-client that does this. Most OpenBSD service daemons, like httpd and smtpd, perform private key operations in a privilege-separated subprocess. The technique won't win any awards for request throughput, but it reflects OpenBSD's "secure by default" ethos, which of course always has to be understood in the context of what they're trying to accomplish.
Air-gapping the long-term account private keys for a semi-automated Let's Encrypt renewal process sounds more aspirational than anything. If you're going to attempt that, the lack of support in acme-client is the least of your problems in terms of initial and long-term operational complexity.[1]
OpenBSD tools are primarily designed for the needs of OpenBSD maintainers, and secondarily for the needs of typical OpenBSD users. These people aren't trying to build the next AWS using OpenBSD, nor are they trying to secure Apple's or the NSA's proprietary key escrow system root of trust key. "Secure by default" has to be understood in that context. And so the fact other tools support more features, some of which can be used to theoretically implement hypothetically more secure systems is sort of beside the point. Moreover, a general rule of thumb is complexity is anathema to security, and OpenBSD is rigorous about providing the fewest knobs possible while minimizing administrative burden and effective risk for their typical user base. This is why the utility and pervasive use of pledge and unveil are simply incomparable to the Linux equivalents, seccomp and filesystem namespaces; and why the fact that OpenBSD services privilege separate private key operations is something most OpenBSD users, let alone non-OpenBSD, don't even realize.
I don't really care about the exploit writers' opinions of OpenBSD. How many of them host and use their own public-facing web or e-mail servers? Attackers and defenders have completely different perspectives that sometimes lead to completely different opinions. And I definitely don't care about the consensus opinion of the security community considering that over the past decade the majority of self-described and even employed "security engineers" are neither experienced systems programmers nor experienced system administrators. Prowess with nmap and Wireshark seem to make for "hacker" credentials in this community. The depth and sophistication of their knowledge is about the same as many Node.js-cum-Rust programmers who write "parsers" and "servers" by stitching together a bunch of crates. That's not nothing, but I'm not going to attach much worth to their opinions regarding complex architectural or algorithmic problems. How many Kubernetes engineers can even understand the value of, let alone conceptualize or even implement, a pipelined series of network daemons that rigorously preserves backpressure? Why would I value their opinion on how to efficiently scale services when their measure of scalability and survivability is the ease with which you can throw more hardware or AWS account credits at a problem, and generate more Prometheus data sets?
People who use OpenBSD over the long term know perfectly well what "secure by default" means, even when they themselves might have made different choices.
[1] Not that I think air gapping is generally impossible or impractical. I've defended DNSSEC on multiple occasions for preserving this ability. And I do a lot of work with HSM, secure enclave, and smartcard integration, so I very much agree with and promote the idea of moving private key operations entirely off network-facing hosts, whether air-gapped or not. But WebPKI infrastructure tends to be operationally quite shallow and quite dynamic, making manually administered key signing operations less practical at any scale. But if someone can make it work, more power to them. In general this use case is too niche for OpenBSD to emphasize--either not enough potential utility, or invites too much complexity. The exception would be OpenSSH's recent embrace of FIDO HID USB keys, but it's not really an exception considering typical interactive ssh workflows, and considering the implementation complexity relative to the traditional ecosystem involving PKCS#11, PC/SC, PIV, etc. I don't think those latter standards are deal killers, but I totally understand and appreciate why they wouldn't see much attention from OpenBSD developers. OpenBSD continues to embrace and enhance IPSec and IKE despite the complexity, even as they integrate Wireguard; they're capable of making context-sensitive analyses.
I regretted it shortly after adding that part, but decided to leave it as I feel it dishonest to hide such comments after the fact. FWIW, I think Node.js, Rust, and Kubernetes are great technologies that fully merited their enthusiastic adoption. But it's precisely their ability to enable engineers to implement often sophisticated functional solutions that means the fact of doing so is much less a reflection of an engineer's experience and knowledge with the underlying problem space than was the case with different (often older) systems. Case in point: somebody arguing that Make is the dumbest, most useless tool and/or syntax, Go or Rust/Cargo are the gold standards for build systems, and then adding as an aside the observation that they don't work well in multi-language contexts or when needing to apply ad hoc (i.e. non-blessed) source transformations, which can sometimes be a hassle. It makes your head explode. Their opinion isn't even wrong; it's just oblivious to the design goals and the broader problem space, and that in some respects they're comparing apples and oranges despite providing nominally similar high-level functionality. How many Go or Rust/Cargo advocates even point out the problems with relying on timestamps? It's totally outside their focus despite being one of the most indisputable short-comings. (Though, at the same time also being one of the easiest to explain and justify given context--lack of forward monotonic change counters provided by filesystem APIs and the costs of adding a default file watcher capability to a tool that by original design was stateless between invocations.) Bazel engineers, of course, are quick to point this out, but they're also perfectly willing to boil the oceans in an attempt to more comprehensively solve the various problems in wrangling the chaotic world of FOSS software; more power to them.
> some of the “novel features” to improve security seem to have inaccurate or outdated threat models behind them
Can you name one technique? I'll even make it easier for you--name one that the Chrome architecture team would outright categorically oppose adding today were they maintaining OpenBSD? (There are plenty of things the team can't or won't add to Chrome for very pragmatic reasons.) The only one that comes to mind might be syscall-origin-verification, but even then it's too early to tell, and implications are beyond inaccurate that the OpenBSD team was oblivious to its limitations. (And FWIW, when I first read about it also seemed completely pointless to me until I dug up context from the mailing list to understand the motivations and goals.)
OpenBSD was one of the first systems (arguably the first, depending on how you define things), to comprehensively implement and integrate ASLR, stack protectors, W^X, and various privilege separation techniques. (And I say that having contemporaneous knowledge of pre-existing examples, such as patches to GCC; that is, I know these techniques didn't originate with OpenBSD by any stretch.) At the time people said everything they say now about modern mitigations--circumventable, little effective security, more rigorous alternatives, etc--despite the fact that they've become table stakes today even while circumventions have become more sophisticated and in some cases even automatable.
For years people argued you absolutely had to distinguish /dev/urandom from /dev/random, and only in the past couple years have people finally come around to understanding that theoretical and practical security are different, and that the practical benefits of a unified approach are undeniably superior.
I mean, just go through the list here: https://www.openbsd.org/innovations.html
Which ones even today are so useless that their continued use is unsupportable? Obviously in many cases there can be differences of opinion regarding relative merit, both then and now, but that's a far cry from saying that OpenBSD developers were naive or ignorant about their utility. In fact, in every case I can think of the naysayers were proven wrong--not because they were wrong about basic facts like circumvention, but because their calculus regarding cost/benefit was mistaken, often for precisely the reasons I stated before--e.g. exploit writers aren't implementing and hosting services, don't appreciate the relative costs and burdens from a systems programmer perspective (particularly one interested in targeting OpenBSD), and tend to assume that OpenBSD is choosing one approach in lieu of another. IIRC, on ARM and MIPS, for example, OpenBSD has removed almost all ROP gadgets even while continuing to add substantially less comprehensive ROP mitigations to cover other architectures and subsystems where it's been more difficult to remove gadgets.
AFAIU, the Linux PaX team has had a low opinion of OpenBSD. Of course, they had a low opinion of many mainline Linux kernel maintainers, too. I never cared to follow the debates and recriminations, but objectively speaking much like OpenBSD their choices seemed to have generally been vindicated over the long term. AFAIU, almost every mitigation they implemented and advocated for the Linux kernel was eventually added in substantially similar form to Linux and its ecosystem, even though it took well over a decade in some cases.
If history is any guide, criticisms of syscall-origin-verification will soften. I'm hardly of the opinion that OpenBSD design decisions are the most rigorous and appropriate answers to more abstract security dilemmas. But if you start from the perspective of maintaining and extending the received Unix application programming environment, and doing so for something more than running and orchestrating hypervisors, Erlang servers, WASM modules, etc, then their track record is incredible. I still think Capsicum is underappreciated, and if I had the time and inclination (which I don't), were I an OpenBSD maintainer it's something I would emphasize. (Ditto for FreeBSD, where the Capsicum API is nearly complete--I'd focus on increasing usage throughout the system.) But that's different than saying I think unveil and pledge are inferior alternatives.
As for an overall summary, I think it is accurate to say that the OpenBSD people are obviously not idiots, and that they do make a lot of right choices. However, those decisions are (as I have mentioned elsewhere: https://news.ycombinator.com/item?id=26911420) mixed with some questionable ones. Overall I think they do adopt a lot of the right things–the ones you mentioned–and I do agree that they are fairly quick to do so, although sometimes they seem like they want to claim a bit more credit about being "first" or designing something than they really should. But those are social issues, so it's not really worth talking about them here.
My main issue is that some of the OpenBSD mitigations seem to be designed by people who either have an outdated view of how modern exploits work, or are just entirely wrong. Like, they sound plausible for a bit if you just think about them, but if you look at real exploits you realize that they are not worth it, or they are just not how real chains look like. Ok, let's break this apart a bit.
What does it mean to have an outdated view of exploits? This means that you're protecting against things that nobody does these days, because other mitigations exist to prevent it. If your mitigation protects against something that people used to do when NX didn't exist and ASLR was nonexistent or weak (perhaps due to lack of VA space), then it's clear that you're living in the past. Similarly, if your mitigation is intended to protect against some form of attack, but if these kinds of attacks never actually happen in the wild, or protecting against them opens up an alternative vector that you leave open, then your model is incomplete. Finally, when judging a mitigation, you don't look at what fraction of some exploit it mitigates when it is working perfectly–you need to consider it in the context of other things failing. ASLR is a "weak" mitigation because one partial, mildly controlled read might be enough to break it. Privdrop is a "strong" mitigation because there it requires a full kernel chain to undo. That doesn't mean they aren't both good to have, but it is important to keep this in mind when evaluating this kind of stuff. Anyways, onto some of the worse mitigations.
Syscall origin verification seems like a weak hardening technique, designed with a lack of understanding of what kind of attacker might exploit it. The reasoning seems to be to prevent an attacker from doing things like writing a syscall into a JIT region, but generally attackers at that point can easily craft shellcode that gives them arbitrary R/W (or have this already), which lets them jump through libc anyways. As such, the general understanding is that it is pretty much useless at stopping an attacker at the level of control it claims it can protect against.
ROP gadget removal is similarly problematic, because "removal" in this case doesn't mean "full removal", it means "reduction in their frequency". A ROP chain doesn't actually take that many gadgets, though, so you can do things like remove half or even more of all gadgets with pretty much zero impact on the ability to ROP. (And I'm not even going to get into the fact that using dumb gadget finding scripts, like OpenBSD did, is not how you measure gadget reduction.) And even once you have all the ROP opportunities removed, you need to then start looking at JOP, because that's what attackers are going to pivot to (heh), which AFAIK is not yet being considered.
I'll do one more, but hopefully you get the idea by now: trapsleds are basically considered to be a joke. They are meant to protect against ROP nop sleds, except it fails to understand that these don't exist. When people ROP they jump precisely to where they want to go. It sounds good on paper, but in reality the mitigation just doesn't match up with any real attacks.
There's a lot of good going on in OpenBSD, but there is also some places where they seem to not have caught up with what is going on in the real world. And I think people's general criticism towards the mitigations follow along those lines.
TYVM for this healing missive, but especially the nugget I pull-quoted. That sums up a lot of what I had come to think about "security" as a career: You need to be an engineer first.