This is a very nice intro to OpenBSD.
I’m a casual OpenBSD user (I have it installed on a server), however in my circles I’m the only person who’s used it. My colleagues ask genuinely curious questions and my responses always seem inconclusive, i.e., OpenBSD doesn’t seem to offer anything new or different from other BSDs or Linux, at first glance.
This presentation made me realize that OpenBSD is not for everybody. If saying “minimalist, very secure and open UNIX with sane defaults” doesn’t ring a bell, maybe that person is not a target user for that OS. Not all OSs are for everyone.
I always encourage them to install a copy on a VM and test it. Most of my colleagues are Linux users, so once you’ve seen a terminal you’ve seen them all. Most package managers accept the syntax package_manager install package_name and if you don’t value the default daemons and want to install Apache and Postfix, you won’t see many differences.
package_manager install package_name
OpenBSD is a system that doesn’t need much proselytism. Either you appreciate its features or you don’t. Nothing wrong with that.
Anyway, I’m definitely saving this presentation. I’ll send it to whoever asks “what is OpenBSD”, alongside with BSD vs Linux and my own first initial impressions post
Going along with your “not all OSs are for everyone” sentiment, I’m a fan of using the right tool for the job. Sometimes that’s Linux, sometimes that’s OpenBSD, sometimes that’s Plan9. For the type of work I like to do, the BSDs fit just fine. But that doesn’t mean BSD is the best fit for everything.
Exactly. I’d love to use OpenBSD on a laptop as my daily driver, but I need many tools which can’t be replaced by open source equivalents. So I’m tied to a Mac (not complaining, though).
However, none of my servers run OSX. Some are Debian, some are Ubuntu, some are FreeBSD, some are OpenBSD.
Us techies like to argue about The Best Tool, but the truth is, the best screwdriver in the world isn’t useful to cut a wooden plank.
I’m recently starting to just recommend “what works for you” when asked which is the best tool. Maybe I’m getting old, maybe I’m less willing to argue.
I’m sorely disappointed at the lack of Comic Sans. ;)
I really wish there were good ways to apply all the goodness of privsep, privdrop, chroot, pledge, etc. to programs that are run by users. Daemons that start as root are well covered, but for other programs you’d first have to elevate privileges with setuid, doas, or otherwise. And that does not sound like a great idea. Historically reducing the number of setuid binaries and indeed making things run without root has been a desirable practice, for good reasons.
Wait, what? You have to actually use setuid or risky escalation on OpenBSD to apply the better mitigations? That’s unnecessary much like the setuid risk itself. That would put them behind many of the other products for secure UNIX in terms of that design decision. I’ll let an OpenBSD developer or admin chime in before I believe this claim.
You seem to think I cannot C so I don’t know if it’s useful for me to write this but yes, quite a few techniques do require root privileges. No, OpenBSD doesn’t needlessly escalate; it’s just that these techniques simply are not applied to programs that you typically wouldn’t start as root. Which is the thing I was lamenting.
There are mitigations that work universally – most do. ASLR, strlcat, canaries, all the good randomization work and the like. Pledge works too. And so on.
But if you want to change your running program’s user to one that has very restricted access to the system (as opposed to your normal user you use for day to day work), you must be root;
The setuid() function is permitted if the effective user ID is that of the superuser, [..]
This call is restricted to the superuser.
A common pattern in daemons is to acquire resources at startup while you’re root, split the process into multiple ones to handle different tasks and make sure they have no access to resources they shouldn’t, jail them as tightly as possible (e.g. chroot into an empty directory and then pledge), and drop them to a user that has no useful permissions anywhere on the system. They only communicate via the sockets that were created for the purpose at startup.
Before you get all scared, the initialization part tends to be very simple and short. Like somewhere between a couple dozen to a couple hundred lines of code. It’s easy to review and audit and come to the conclusion that it is just fine. And in many cases daemons must be started as root anyway, because they require access to things that only root can have (e.g. bind to low ports). You seem to believe that it is impossible to write secure C code, so I don’t know what to tell you. Seriously, go take a look at the code.
You could also look at e.g. file(1), which does exactly something like this. In child(), it will drop the privileges of that process to FILE_USER, but only provided it has been started as root.
“You seem to think I cannot C so I don’t know if it’s useful for me to write this but yes, quite a few techniques do require root privileges.”
Don’t take it that way. It’s more like I wasn’t sure if you were a casual or expert user of OpenBSD. A casual user might see how it works in limited situations with a resulting obvervation that wasn’t totally accurate. An expert would see this and clarify to give me the big picture. Alternatively, you’re an OpenBSD expert or at least expert on this part of it where your word is golden. I asked for elaboration by you or others since I couldn’t be sure from one comment.
“But if you want to change your running program’s user to one that has very restricted access to the system (as opposed to your normal user you use for day to day work), you must be root;”
So, pledge drops system calls but there’s not an equivalent, non-root command to drop to a subsetted, user profile? Might make an interesting project for someone creating user subsets or groups where dropping down doesn’t take root.
“Before you get all scared, the initialization part tends to be very simple and short.”
I’ve done it on other systems. I agree this part is usually small and easy to manage. The only concern are malicious inputs or failure modes. Tiny risk compared to running app in general.
“You seem to believe that it is impossible to write secure C code, so I don’t know what to tell you. ”
Not sure why you brought up a red herring in an otherwise informative reply. My view that C is hard to write securely has basically nothing to do with a conversation on this vs that privilege scheme. We need isolation primitives regardless of the language used.
“You could also look at e.g. file(1), which does exactly something like this”
Excellent example. A simple check with a few lines of code. Easy to manage correctly. Especially if sanity checks are built into such calls. I’d likewise put very low priority on replacing it if all uses in security-critical code are this simple. Appreciate your elaboration on your original comment.
Right, this is the thing that would need some attention. Users like _file work because people don’t give them ownership of files and they aren’t members of any groups. They’re also useful because they can’t meddle with processes owned by other users. Apart from the latter, this is all by convention and not enforced at all. So technically these users could be just as privileged as any other user. There would have to be some way to tell that it is safe for a program to drop down to a specific one of these users, without letting them freely pick any user they like (and thus potentially escalate into a real user). It is beyond the traditional Unix model.
As for chroot, I feel like it should be doable by simply permitting any user to chroot deeper in the file hierarchy. But I haven’t looked into it too much. Maybe there is a catch.
Not sure why you brought up a red herring in an otherwise informative reply. My view that C is hard to write securely has basically nothing to do with a conversation on this vs that privilege scheme.
I apologize. I admit I got a little agitated over our exchange on HN and the sentiment that I have the exclusive choices of security and personal pleasure. I shouldn’t have brought it up again.
“ It is beyond the traditional Unix model.”
I figured. It does seem like a lot of trouble if one wants compatibility. I could see why they avoided trying if most privilege dropping was simple.
“I apologize. I admit I got a little agitated over our exchange on HN and the sentiment that I have the exclusive choices of security and personal pleasure. I shouldn’t have brought it up again.”
You must be clarry there. Your initial comment seemed like a wise-ass attack. It’s why I responded as I did. I stand by my claim of risk going up using it vs (example) Go in web apps. If I misread your style or intent, I do apologize for being unnecessarily aggressive in my response over there.
RE: slide 5, are guard pages actually enabled by default? I’m asking because CGJ are the options enabled by S, which is definitely not the default. I don’t see omalloc_init enabling options (aside from the default junk level & free page cache), so if there’s another place I’ve overlooked, I’d like to know.
Otto discussed this recently in this thread
Yeah, looks very much like G (mopts.malloc_guard) is disabled by default.