4 ms·
Something that can respond to a DNS request can put whatever it wants in the response. If there's a bug in that program, then whoever controls that bug can put
by geocar 9y ago
Something that can respond to a DNS request can put whatever it wants in the response. If there's a bug in that program, then whoever controls that bug can put whatever they want in the response.
The only protection from this is to make the code that does this as small as possible so that us human beings can convince ourselves that it is correct and that the risk of a bug that someone can control is zero (or as close to zero as to make no odds).
When Jim Reid wants to pat himself on the back because "at least they didn't get root on my nameserver box", he misses the point: gethostbyname()'s spec doesn't say "it may or may not return. if it returns it could return anything. don't trust it, don't even use it!" They say gethostbyname() return a structure describing the address of the named Internet host, so people expect that and depend on that. Something that "suddenly" violates that gets in the news[1]. Fortunately, nobody remembers what Jim said so the BBC doesn't ask him for a comment.
Anyway.
"Minimizing privilege" doesn't solve that problem because the DNS server needs the privilege to respond to DNS requests.
It might be easier to think about a better example. Let's talk about zlib.
A program that needs to decompress some text is not concerned with the contents of the compressed text, only the uncompressed text. Resource limits on our program exist to keep some things from getting out of control[2], but what about bugs?
If we could run zlib's decompress() with the permission only to decompress text, then the worst-case impact would either spin the cpu or be equivalent to "getting out of control". What do we need to do that?
• No creating file descriptors can be done with setrlimit() except for the dynamic linker is going to open a shittonne of files. We need to know what the minimum number of files are, and decompress can't ever change that without changing our program anyway.
• No accessing files or the network could be done with a setuid wrapper and iptables. At least on Linux. Most programmers don't do this, and most sysadmins only do what they're told, so in practice this doesn't happen.
• Sandboxing! Google published some clever user-level sandboxing that works on Linux to whitelist each syscall. This "verifier" could do it as long as it's smaller than decompress()!
That sandboxing one is tricky: A tiny inflate routine takes around 500 lines of C done the normal way, but how big is our sandbox? Probably a lot bigger.
• Ask the operating system for help! This is what DJB suggests. Ask for a disablefiles and a disablenetwork system call. OpenBSD is implementing this with their pledge[3] system call.
There's not a portable and satisfying solution here yet, but you can see they all cluster around reducing the privileges of the untrusted program.
Now, what's to prevent decompress from lying? What if someone can produce a content stream that causes a future decompress run from producing invalid results. Maybe something really sneaky[4]. What possible protection could we have?
As you can see, in this case so long as decompress is supposed to produce "text", there's nothing we can do to make sure it produces the "correct text".
That's why DJB doesn't want to focus on the "untrusted" aspect, and instead on trying to solve the problem that we have to solve anyway: How do we write software that is correct?
[1]: http://news.bbc.co.uk/2/hi/technology/7496735.stm http://news.bbc.co.uk/2/hi/technology/7496735.stm
[2]: https://swtch.com/r.gz https://swtch.com/r.gz
[3]: https://man.openbsd.org/pledge.2 https://man.openbsd.org/pledge.2
[4]: https://cmaurice.fr/pdf/ndss17_maurice.pdf https://cmaurice.fr/pdf/ndss17_maurice.pdf
- viraptor 9y agoRight. I think I see the difference he intends. I see this more of a practice -vs- theory issue. (Or in isolation/in deployment) In theory he can work on designing the correct version of gzip and there's a chance he'll succeed. But in practice, I'm still putting a seccomp/pledge-equivalent on it, because if he fails, I'm stopping local root escalation and potential lateral movement, which he doesn't seem to think are interesting consequences.
- geocar 9y agoThere's a point of subtlety remaining: DJB isn't advocating against using seccomp or a pledge-equivalent. DJB is advocating against stopping there.
- viraptor 9y agoThat's definitely not how I understand this DJB quote: > I have become convinced that this “principle of least privilege” is fundamentally wrong. Minimizing privilege might reduce the damage done by some security holes but almost never fixes the holes. Minimizing privilege is not the same as minimizing the amount of trusted code, does not have the same benefits as minimizing the amount of trusted code, and does not move us any closer to a secure computer system. By "does not move us any closer" I don't believe he wants us to do it at all.
- geocar 9y ago> By "does not move us any closer" I don't believe he wants us to do it at all. Then take a look at § 5.1 of the paper which gives a clearer example with which to draw the distinction. Eliminating trusted code is what you're doing by decorating uncompress with pledge() with any capability to acquire resources; anything beyond stdio (or seccomp) Minimizing privilege means focusing on finding some other argument for pledge().
- irundebian 9y agoThat's a great explanation, but I still don't understand why he says that the principle of least privilege is _fundamentally_ wrong. I fully agree that POLP could lead to an illusion of security or doesn't ensure user's security requirements, but that doesn't make it fundamentally wrong. The correct point is, that you shouldn't over prioritize POLP over code correctness. Maybe he is just arguing against the very strict implementation of POLP I could also agree, but in general, I would argue that POLP is fundamentally true and necessary, but that doesn't mean you should implement complex fine-grained solution with a lot of administrative overhead. As soon as you build non-trivial systems, you have to contain error propagation with POLP, although you are striving to build simple and secure systems.