This person means well, but suffers from the same myopia a lot of security-first people do: making these changes to default settings is a huge violation of expectations, and the changes need to be widely publicized once they are decided upon. Suddenly dropping support mid-cycle for tons of things will result in pitchforks and torches from people who, despite the constant insinuations of this document, do in fact know what they are doing.
This document, in short, makes a great to-do list but completely ignores the roadbuilding that needs to happen to get people ready and on board.
This is what's wrong with infosec. The majority of security people seem to have no concern for any other issue, resulting in them giving a lot of ham fisted advice that gets ignored. In the end security is worse as a result.
I worked in infosec for a while and saw it at the org level:
1. Security recommends something with no concern for how it inconveniences (or worse) the users.
2. Users ignore or even actively work around security.
3. Users get pwned and blame security.
4. Security gets mad, calls users stupid, goes back to making ham fisted recommendations that everyone ignores because they have to get their work done.
5. Goto 1.
In the end I concluded that we (security) were at fault. In many cases there were user sensitive options and I would make an effort to find them, but most of security actively had contempt for anyone outside security and didn't care.
This isn't about myopic security recommendations. These are just plain bad defaults and a failure to manage tech debt. No one that "knows what they are doing" wants to accept these risks and addressing them doesn't hurt users. Fixing these problems is totally realistic.
Some of these are bad defaults, some of these are common defaults that turned out to be bad, some of these are not easy to fix. Many of these things just take time to do right. Examples:
ntpd is clearly not great software, but OpenNTPD is maybe a little bit too minimal. When ntimed is worthy, I'm sure it'll make it into FreeBSD base, but it's most likely going to be in a .0 release, so it'll be a while and people will be impatient.
OpenSSL is hard. software in base needs libcrypto and libssl, so you need to pick a version and stick with it throughout the release cycle; but the FreeBSD release cycle is longer than the OpenSSL cycle; OpenSSL has also historically not been very good at keeping ABI compatibility. There's a lot of smart people working on this, but I think the least bad option is to not use openssl from base for anything outside of base.
Firewall: I don't think default to no firewall is a problem -- if you want something, you can set it up.
> Five months after this document was published, FreeBSD disabled DSA hostkey and SSHv1 server support in their bundled version of OpenSSH. This was done more than a year after upstream OpenSSH removed them, and both will remain enabled the 10.x branch until its end of life date.
This decision upsets the author, but is the right thing to do. You don't turn off things that people may be depending on in a .x release, you do it in a .0 release. 11.0 was the first .0 release since he wrote this, so it was done as fast as possible. As a FreeBSD user, I appreciate that the .x releases do not contain major changes that break things I may have been depending on. I accept that I need to carefully read the release notes for a .0 release, to see what things I can expect to be broken.
> Firewall: I don't think default to no firewall is a problem -- if you want something, you can set it up.
I'm very curious about this one ...
As far as I know, any remote holes without a firewall on a default install would be a ground-breaking, DEFCON-1 level security event to server admins. Complete with CVEs, news coverage on various sites, etc ... right? The only time in history I recall this being a problem was with Windows XP, which led to Blaster and Sasser.
Now I'm absolutely in favor of firewalls, but whenever I spin up a new VPS, there's going to be a window of about 20-30 minutes where I need to get in there, upload my SSH public keys, secure SSHD, tweak my sysctls, write out my pf firewall rules, and then activate them. There are also times when I need to test why a connection is failing, and one of the steps to testing is to turn off the firewall momentarily.
I know that attacks are basically incessant against any server on the net. I see dozens of IPs trying brute-force root login SSH attempts a day against my boxes.
How much danger is there, honestly speaking (not hypothetically), in this window? Would it be worth it to petition VPS providers to allow us to specify our own IP address, and have them enable a default "deny everything except from this one IP" firewall setup on new instances, or is that just total overkill?
Out of the box, FreeBSD is going to have sshd, ntpd, and syslogd (i think) listening on wildcards.
sshd is ok enough -- PermitRootLogin is default off, would be nice if password login was disabled, but that's a pretty hard default to change because it's going to affect a lot of people.
ntpd isn't great, but the out of the box config is pretty restricted, so it's probably fine for a while
syslogd is weird, it probably shouldn't be open to the world -- but that's more likely to fill up your disk than to be owned.
I don't think there's a problem with running a firewall and I usually do, it provides a simple way to enforce your intent; but there's no sensible default rules. Api said it well, don't run services you don't need, and don't bind to external interfaces if you don't intend to serve the world.
Awesome, thanks for this! So it sounds like no real issues, then.
But all the same, I should add syslogd_flags="-ss" as soon as possible on a new install.
Also worth noting, Vultr 'helpfully' adds "PermitRootLogin yes" at the very bottom of sshd_config on their new installs of FreeBSD. Ostensibly so you can log in without their VNC-in-a-web-browser client, and just use SSH for the initial setup. Which I quite like a lot. They give a really strong password that looks to be around 64^16 in terms of entropy, so that's probably fine. I always turn off root login and password login as soon as I add my authorized_keys to a user account anyway.
I've never understood the argument for system-level firewalls at at all. If a service is listening on a port from the network, presumably that's for a reason and you're going to end up writing a firewall rule for it anyway. If you have complex rules that try to filter out "bad guys" then your firewall is a complex piece of software full of parsers and the like, probably written in C "for performance", and you're exposing it to external packets - that's a bigger attack surface than not having a firewall. If your services are using sockets for local communication, bind to 127.0.0.1 or use a unix domain socket.
Quite a few services bind to all interfaces by default. Redis used to, elasticsearch used to, iirc mongodb as well. The list is probably long. While this is a bug in the software, having a firewall that denies by default is an additional layer that prevents turning a slip-up into an RCE.
If you assume lack of cooperation and separation of duties it can sometimes make a microscopic amount of sense. So security says thou shall not VNC and configures a very tight system level firewall, preventing some jerk end user from compiling and running a VNC server over port 10000 because the system level firewall blocks everything that's not explicitly permitted. Oh you've "broken" the system SSHD such that I can't even use it, I'll just compile and run my own sshd as an end user and run it on port 11000 or whatever.
In practice I'd agree with you in that an org where security, admins, and users are pulling opposite directions is going to have massive problems in general and a mere system level firewall isn't going to patch over all of it.
For a distant historical example I've worked at places where for temporary use I've had to shut down apache on port 80 and run sshd there on port 80 for a few moments, just to copy a config file over. A REALLY smart deep packet inspection firewall would notice the conversation on port 80 was very SSH like not HTTP like, but whatever.
Speaking of VNC that made me LOL at the linked article suggestion to block X11 traffic, an end user who "really wants GUI" will simply fire up an unauthenticated possibly passwordless VNC server on some port. Security would have been a lot better off with SSH trying to be secure rather than VNC not trying at all. Some end users are just crazy some times. Oh I'm not allowed to run NFS because "security theatre", well OK them I'll just set up anonymous FTP because that's not blocked. I've seen some stuff...
> A REALLY smart deep packet inspection firewall would notice the conversation on port 80 was very SSH like not HTTP like, but whatever.
Hahahah, I've abused this at a previous employer as well. They filtered out all outbound traffic other than ports 80 and 443; so I put my home SSH server on port 443, and then used a SOCKS5 proxy via dynamic port forwarding. Luckily their packet inspector wasn't smart enough to tell SSL from SSH; and apparently nobody in networking was manually reviewing traffic logs.
You have a firewall. It's called "don't run services you don't need or don't understand" and "if it binds a non-localhost port it better be secure."
It's easy to use netstat to list all bound ports for TCP and UDP. I know on Linux there is also a flag to show the owning pid. Do that and then investigate any you don't recognize. If you don't need it turn it off. Otherwise check it's security record and config.
I’m fairly new to FreeBSD; I've been using it for various small projects off and on since 9.x. I also previously worked for MIT for over a dozen years and worked fairly closely with network security colleagues.
To me, the attitude of we're not going to change the defaults the neckbeards cut their teeth on 20 years ago regardless of the insane threat environment we exist in today and if you get hacked, owned or worse, it's your own damn fault for not knowing all of the tweaks that could have saved your ass that we decided not to make defaults even if they are defaults upstream is the height of Unix elitism IMHO.
In the world we live in, having defaults stay the same for the sake of not inconveniencing people who already know better is incredibly shortsighted. And it makes it way more difficult for newbies who don't have time to cobble together best practices from all the relevant IRC chat rooms, email lists and blog posts to learn FreeBSD’s best practices.
It doesn't make a lot of sense to have a default install of FreeBSD that allows users new to the platform and who are looking around and kicking the tires that also allows users to shoot themselves in the foot unnecessarily.
Thanks to the author’a article, I now disable the default settings for OpenSSH, use OpenNTPD, encrypt swap and build everything I can against libressl-devel.
The fact that so many of what are mostly common sense proposed defaults are perceived as breaking some kind of FreeBSD oath of obfuscation doesn't help grow the FreeBSD community in the long run. That's something to also consider.
I'm reminded of OpenBSD's move in 6.0 to enforce W^X on binaries. This breaks the use of my cooperative threading library: in order to avoid requiring specific compilers/assemblers (for the portion that's impossible to write in pure C), I use ~50 bytes of pre-compiled code so that it'll compile anywhere. To do that, I have to mark the block R|X. But I can't know with 100% certainty that the codepage doesn't overlap with something that was writable (since there is no mgetprotect), so I have no choice but to set R|W|X.
So probably what I'll have to end up doing is allocate at least three codepages at run-time, set to R|W, copy the code there, then set R|X, and take a performance penalty for needing a pointer to the code block.
What I would like to see FreeBSD do to help with migrating to stronger security is something like "freebsd-harden" that you run once after a new installation or version upgrade, and it will walk you through a series of yes/no prompts, and advise, "if you aren't sure, say no."
(Note: I agree with your main point that changing defaults can cause problems, and security needs to balance with usability or people won't use it.)
For that 50-byte block of code, on most platforms, you could tell the compiler or linker to put it in the text section directly along with the rest of the code, rather than in the data section. A linker script or a section attribute can do that. Then you can just call it using the appropriate symbol.
I just tested this, with a manually assembled array of bytes, using both of those methods, and both of them work.
Glad I could help. Thank you for building awesome software.
> Does Clang support this as well?
Clang supports __attribute__((section)).
For linker script support, it'd depend on what linker you use. GNU ld and gold have complete support for linker scripts. LLVM's lld has some support for linker scripts, plenty enough to do things like this, though it may lack some features that GNU ld and gold support.
> It looks like I don't need the main.o(.text) line either, which is good because that would be a large burden on users of the library.
When I attempted to link without that, the linker complained that it couldn't find main. Interesting that it worked for you without that. You can also use wildcards to match all object files, if that helps, and then use "ld -T thescript.ld *.o" to link.
> Also, just noting for others, I had to use .text : { libco.o(.rdata); } since my char array was const.
Sadly, read-only sections vary a bit more; some compilers use .rdata, some use .rodata.
You could use __attribute__((section)) to explicitly put the array in a specific section, then name that section in the linker script; that avoids the warning and any platform-specific inconsistency.
The theory being that the const will put it into either .rdata or .rodata (since nobody can decide on one or the other it seems); and then by forcing the alignment to a page boundary and also filling a page boundary, we make sure the VirtualProtect or mprotect call won't affect anything other than our co_swap function. But even if it does, it'll most likely be more read-only data, and it's not the end of the world if that gets marked executable.
The downside is of course that the page size isn't really known at compile-time. On ?nix, it's a run-time call to sysconf(_SC_PAGESIZE); but on Windows I'm not sure how to get that value. However, I'm pretty sure it's going to be 4K on any x86/amd64 systems.
So, these seem to be all of our possible options:
1. we use inline assembly; and now you require a specific assembler (MSVC and GCC inline ASM syntax are totally different) or additional tools like nasm/yasm. I really don't understand why at least three people have favored this solution now; but since they haven't elaborated any reasons, I'll just have to politely agree to disagree here :/
2. we use __attribute__((section)), and get unsuppressible warning messages, and the command also won't work with MSVC.
3. we use __attribute__((section)) with our own name, and use a linker script to suppress the warning message, losing compatibility with MSVC.
4. we use __attribute__((aligned(4096))), risk the page size being wrong, and the attribute won't work with MSVC.
5. we use #include <stdalign.h> [when _MSC_VER isn't defined] + alignas(4096), risk the page size being wrong, and require C11 instead of C89 to compile. [_Alignas probably isn't going to be in MSVC due to their hatred of C99 and above.]
For the latter two, we can have #ifndef/#define LIBCO_PAGE_SIZE 4096, for convenient command-line overrides.
Probably the most pragmatic route will be to support multiple options and let the user override if one of them doesn't work out on their platform for some reason.
EDIT: here we go:
SYSTEM_INFO si;
GetSystemInfo(&si);
int page_size = si.dwPageSize;
Then for good measure, we throw in:
assert(LIBCO_PAGE_SIZE == si.dwPageSize); //or for ?nix, == sysconf(_SC_PAGESIZE)
"text" isn't the right section name; that'll create a new data section named "text", and then you'll segfault trying to execute out of a data section.
Specifying ".text" causes the toolchain to attempt to create a data section named ".text", which causes the "changed section attributes" message; the array then correctly ends up in the executable ".text" section, though. I'd like to see a way to declare a section without attempting to make it a data section, but I think the compiler folks' answer to that would probably be "use a linker script". And I don't know a way to disable the warning.
What I would like to see FreeBSD do to help with migrating to stronger security is something like "freebsd-harden" that you run once after a new installation or version upgrade, and it will walk you through a series of yes/no prompts, and advise, "if you aren't sure, say no."
Actually, they now have such a post-install script:
Very cool! And I can use this menu over a VPS SSH session (so no color support) after the initial install? Usually I think of bsdinstall as being run pre-install, not post-install.
HardenedBSD[1] is FreeBSD pre-hardened. This is one of the few times I agree with a parallel sister project over multi-paradigm design, since they make pretty significant changes to the Kernel+World[2] that aren't necessarily beneficial to home users.
That turns the address from a compile-time constant into a pointer. This function is used tens of millions of times a second, so that cost would add up. I covered this in my initial post, though :/
Yeah, I take a lot of flack from this from other people. But I'm sorry; I'm not going to write the code in GNU as (and that godawful AT&T syntax) or nasm/yasm (and require another tool to build the library), require a second compiled object for the library, and lose compatibility with Visual C++ and Clang.
Also, apologies to HN. I wasn't trying to turn this into a "help me with my problem" discussion. I was just pointing out how adding extra security can have unintended consequences to other applications with an actual example.
It sounds like he needs an OS built on "default deny" principles. The best one for that is OpenBSD, and he recommends porting over three or four packages from OpenBSD. Really, he'd be happier running that, I think. I know I was when I first started exploring the BSDs. I tried FreeBSD, PC-BSD, and DragonflyBSD before settling on OpenBSD.
Default deny makes the most sense if you are interested in security. Sure, it can be a PITA to set up .conf files at first and get the packages you need, but once past the learning curve, it's the simplest thing to maintain.
FreeBSD reminds me a lot of various flavors of Linux I've tried in the (distant) past. All kinds of stuff running by default, old packages for compatibility, etc.
Security may not be important for many people till it's too late, but it's one of those things that pays dividends in what doesn't happen. Hard to sell if you've never been pwned.
If you are suggesting NetBSD has more things enabled by default than OpenBSD I would bet that is incorrect. I have tried a lot of different projects and NetBSD is the best I have seen for not enabling anything. It forces you to figure things out.
Whenever I read OpenBSD mailing lists or blogs, they often seem more aggressive in trying to make their users adhere to the default system provided. That's fine, but NetBSD generally does not do this. Users are not assumed to be idiots and are not discouraged from experimentation.
The BSD projects share more similarities than differences. None of them require anyone to use the entire base system or the defaults. Users can compile their own kernels, write their own configs e.g., based on examples provided, and cherry pick utilities.[1] In my opinion this is made just a tad easier than with Linux.
1. But if you do this with OpenBSD and advertise it, I think you may draw some criticism. Frankensystem, etc. They are not encouraging experimentation, they are encouraging conformity.
A lot of these points have been addressed in one way or another - 11.0-RELEASE has a new installer dialog[0] with multiple hardening options available. These are OFF by default in 11.0-RELEASE due to POLA principle, but they are to be enabled to ON by default in future releases (hopefully in 11.1).
Why would high performance networking be dropped from the default? I learned of its existence a few weeks ago and was wondering when it would make it in.
Not to mention he doesn't understand what flipping these defaults actually will do.
They sound great but without understanding exactly what happens when some of these switches are flipped you're going to wind up breaking other things because you simply do not have the knowledge to understand these features in depth.
His heart may be in the right place but he needs more experience and wisdom on how things work on a more fundamental level.
My least favorite FreeBSD default: permissions for CD/DVD burning.
I get the high-minded position FreeBSD takes here, but it is also a total PITA and it seems pretty clear that if you are putting a CD/DVD in a host's tray, you have console access.
Yeah, it's pretty nuts having to study the output of camcontrol and /dev, creating a devfs ruleset, adding that to /etc/rc.conf, adding your CD drive into /etc/fstab, and then tweaking a sysctl, just to burn a CD.
I am hard-pressed to think of the security risks involved in a user being able to burn a CD. Short of some kind of highly-confidential server with no internet access, where you'd probably want the whole machine inside a locked cage anyway.
There's a cd in the tray, but we don't know who put it there. Maybe if you're logged in on a specific terminal?
I could contrive some scenarios where it would be undesirable though: Maybe if there's a rewritable (or not finalized write once) disc also in the system for something important? Let's say, a diskless system without pxe support, so it boots from a cd drive, but doesn't mount it. An unauthorized user with access to the burner could disrupt the next boot.