Support of OpenBSD pledge(2) in programming languages
gist.github.com
gist.github.com
Perhaps the design of pledge will turn out to have advantages, but it's a pity the unix world fragments yet again on something that should be trivial. Either people will limit themselves to chroot as the only portable solution, or hairy libraries will be necessary (like libevent .. no, libev.. wait, libuv).
> [...] but it's a pity the unix world fragments yet again
> on something that should be trivial.
FWIW: Theo mentions in the talk that he's willing to change things if that makes it easier for other operating systems to adopt pledge(2).It probably isn't an issue with a project like Chrome or Firefox to find someone able to understand all the intricacies of seccomp-bpf and implement it properly. And I am sure seccomp is a much more powerful solution.
But for a sole programmer or small team writing some micro-services or similar it seems unlikely they are going to bother. By comparison sending a string with some well chosen categories looks so ridiculously easy it lowers the barriers a lot.
A gist someone posted that's fairly easy to follow: https://gist.github.com/ya790206/9579145
Theo de Raadt doesn't like it (http://www.openbsd.org/papers/hackfest2015-pledge/mgp00011.h...), but I don't see a huge difference between it and pledge.
The aliases that pledge offers (like stdio) that sum up logical groups would be nice, but that's a minor difference to me.
Pledge also gives you ability to block or allow on pathnames, which you cant do easily with seccomp, as you just get pointers. You are better off using one of the other security mechanisms to deal with paths, but it is not simple.
Can I start a process in some way that means "demand a pledge call, and only allow [x,y,z] / disallow [a,b,c]"?
I can't test that since I don't have openbsd installed, but I don't see why it wouldn't work.
A very important part of pledge's design is that a parent can be more restricted than its child. This isn't a sandboxing mechanism. It's intended to mitigate the dangers of some other vulnerability leading to remote code execution. With pledge, even if you get into the system you may not be able to make all the syscalls you need.
ISTM this will just slightly raise the bar so that attackers who get code execution have to force a call to execve.
On the other hand, it avoids needing to worry about all the setuid issues that Linux's seccomp avoids using PR_SET_NO_NEW_PRIVS.
If the program did not pledge 'exec', then calling execve() will cause the program to be killed. Lots of programs don't need exec, so don't pledge it.
In fact, most programs will not need the exec promise in which case any attempt to call execv(3)..
Abort trap (core dumped)
If you think about the semantics of execv(3), it needs a path to an existing executable. So an attacker will need to know of one in advance, or write one out to disk beforehand.. oh but--
Abort trap (core dumped)
The exploited process pledged "stdio rpath proc exec" and cannot write to arbitrary files. Hmm. Bummer.
/bin/sh, perhaps? It's harder to pass in machine code, but I bet there's a way. /bin/sh -c "echo -e shellcode_here >/tmp/foo; chmod 700 /tmp/foo; /tmp/foo" seems plausible to me.
In most cases your program doesn't need execve, so it can call pledge without "exec" promise.
Sometimes you will still be able to open some shell script and add your commands there or something like this, but without "wpath" promise it is impossible.
Source? I didn't see that in the man page.
> exec: Allows a process to call execve(2). Coupled with the proc promise, this allows a process to fork and execute another program. The new program starts running without pledge active and hopefully makes a new pledge().
$ cat testpledge.c
#include <unistd.h>
#include <stdio.h>
int main()
{
pledge("proc exec", NULL);
execl("/bin/echo", "echo", "asdf", NULL);
_exit(0);
}
$ cc testpledge.c
$ ./a.out
asdfWhen using a third party library, it should be possible to have more faith that it's not doing something unexpected. So not only can it protect you against ingress attacks, but also potentially against malicious code you might accidentally include in your software.
(I'm assuming of course that the third party library can't reset the pledge)
Not sure how some edge cases (?) are handled. For example if a database server goes down, my app that uses pledge needs to open another socket to another server. Reload of changed configurations?
"Unpledge" then pledge again? Whitepaths?
If you think of a shell as an example, it will need to exec programs that do privileged things before they can drop them, but the parent shell itself may never need to say.. create sockets.