OpenBSD's new file(1) is now priv-separated
marc.info
marc.info
https://marc.info/?l=openbsd-cvs&m=143014212727213&w=2
https://marc.info/?l=openbsd-cvs&m=143014250427343&w=2
There are unfortunately a lot of people who depend on file(1); and many of them also run it as root.
Also previous HN discussion: https://news.ycombinator.com/item?id=9439778
Most programs I write I would be happy, fairly soon after startup, to drop to "just read and write handles I've already got". It would make me feel much better about my badly written parsers!
If you want to go a step further and sandbox, use setrlimit(2)/chroot(2). And if it's appropriate, use technologies like systrace(4) or Linux seccomp(2).
There are many examples of this in OpenBSD's base system, including some most people don't know about.. like tcpdump(8)
All file needs to do is scan for some magic bytestrings, and optionally print the numbers at a handful of offsets. It currently does much more than that, which is why it's insecure and hard to fix.
If you feel the command does more than it needs to, could you call out a few examples of bloated features that you would cut?
But I haven't seen anything to disagree with file being similarly problematic. A quote like
To sum up: If somebody uses 'file' in an unconstrained OS environment on untrusted inputs, and he gets pwnd in the result, then it's not a security problem, it's an incompetence problem - and IMO it should be discussed elsewhere.
does not suggest that the program is very well designed.
Scanning for byte strings with no possibility of security flaw is a solved problem.
Given the correct input, at least a month ago, it could do all of those things.
(I am not sure that attempting to enforce this within the file(1) binary is optimal... after all, even though the attack surface is much reduced, file(1) could still have a bug somewhere prior to the sandboxing. If you could do a "chpriv -write_to_disk -socket -run_external_program /bin/file" that the OS would enforce, that would be cool. Someone should create that.)
If by "open sockets" you mean open existing sockets in read-only mode, it's so that it can identify them as sockets. If by "open sockets" you mean create new sockets, I don't think it does do that:
https://github.com/threatstack/libmagic/search?utf8=%E2%9C%9...
> write to arbitrary files
It appears it only does this if running on OS/2 and investigating what's inside a compressed file. Under these conditions, a temporary file is necessary for platform-specific reasons:
https://github.com/threatstack/libmagic/blob/3dea7072b8d7e92...
https://github.com/threatstack/libmagic/blob/3dea7072b8d7e92...
It also writes to a non-arbitrary mmapped file (the magic database), because that's how such databases work; you query them by writing to them in a particular way:
https://github.com/threatstack/libmagic/blob/3dea7072b8d7e92...
> run external programs
I can't find any examples where it does that. Do you know of any?
This is what I am saying...given the right input, file(1) could do anything and everything. Yes, it's only due to a bug in file(1), but still that's kind of ridiculous.
We have all sorts of things in place to protect against other bugs (for example, segmentation faults), and there's 27 years of evidence that we need some more help.
I point again to:
http://en.wikipedia.org/wiki/Halting_problem
If you are reading in from a file, and you make decisions that are complex enough to be S- and K- combinators (or a concept of "if" and "jump", or some other minimal set), then you have given an attacker a Turing machine.
But what I'm saying is that the Turing machine should not be connected to a gun. And being hooked up to an idle gun should not be the default for every program.
Well, there's not code in file(1) to do that, but there's code that reads data in and makes decisions based on that data. Which means, if your attacker is more careful than the programmer was, you have possibly given that attacker a Turing machine.
Welcome to the joys of parsing.
Quoting from the first:
> An attacker who can cause file(1) to be run on a maliciously constructed input can cause file(1) to crash. It may be possible for such an attacker to execute arbitrary code with the privileges of the user running file(1). ...
> No workaround is available, but systems where file(1) and other libmagic(3)-using applications are never run on untrusted input are not vulnerable.
And from the third:
> There are a number of denial of service issues in the ELF parser used by file(1). ...
> An attacker who can cause file(1) or any other applications using the libmagic(3) library to be run on a maliciously constructed input can cause the application to crash or consume excessive CPU resources, resulting in a denial-of-service.
I didn't realise openbsd had a seccomp equivalent, but I'm happy it does! (And it did make the news again)
It's too bad, I think system calls are a very good place to apply security policies. I think the issue is that one can modify the memory structures pointed to by a system call after it has been "approved" by systrace policy, but before the kernel acts on it. While the ownership of such data structures are in userspace, its perfectly fine to modify such regions.
It's too bad, I think its possibly the most straight-forward approach compared to SELinux or MAC