Hacker Newsnew | past | comments | ask | show | jobs | submitlogin
Support of OpenBSD pledge(2) in programming languages (gist.github.com)
136 points by protomyth on April 9, 2016 | hide | past | favorite | 52 comments


Here's Theo de Raadt explaining how pledge(2) works: https://www.youtube.com/watch?v=F_7S1eqKsFk


This seems like such an elegant idea it is surprising that it hasn't been done before. I can imagine adding pledge calls to software I write myself. I can't say that for most other policy systems.


Hasn't it? It doesn't look very different from the many syscall filters out there, of which the seccomp family is most used. That's what Chrome and OpenSSH uses to sandbox.

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).


The simplicity of the interface is what feels novel to me.

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.


can anyone provide a textual description of what this is? so far all I've found is a broken manpage and a slideshow presentation without much explanation.



thanks ... that works. Also this register article is decent: http://www.theregister.co.uk/2015/11/10/untamed_pledge_hopes...


Thank you for the links. Reading the presentation, and ignoring the 'monkey' and 'loudmouth' comments, made me think this could be seen as an implementation of the 'intent security' capability that Android has through its Manifests. Although I assume (I did not go through all the slides) that implementing this is 'slightly' more complex due to the number of things you can pledge to use/non-use.


pledge allows a process to declares privileges it needs to function. If the process accesses something beyond those pledges then the Kernel kills the process. The idea is that this will help reduce the surface area that certain types of attacks like remote code execution can have.


Content starts at around 14:30 minutes if you want to jump over the bashing of others and self-adulation by Theo.


But you miss the wonderfully absurd gif at the ~02:00 mark.


I've created a full 'awesome' list of Pledge resources at https://github.com/PeterTonoli/awesome-pledge


What a great way to fix up the choices that were necessarily lazy (socket to syslogd) and are now attack vectors. I REALLY liked this talk and the concept. It's not perfect, but it leads to better software by thinking about existing programs in a new way (much like the priv-drop).


The popular equivalent on Linux is seccomp, and the most straightforward way to use it is libseccomp.[1]

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.

[1] https://github.com/seccomp/libseccomp


You really need to know your system calls back to front to work out how to apply seccomp usefully and effectively. There are several hundred of them, including historical versions which may or may not be used, depending on the libc version that runs.


Sure. But libseccomp does use the same "only explicitly allowed" path that pledge() does. It also uses "pseudo" names for the syscalls, so there's one place to look up the list: https://github.com/seccomp/libseccomp/blob/master/include/se...

The aliases that pledge offers (like stdio) that sum up logical groups would be nice, but that's a minor difference to me.


You can blacklist or whitelist with seccomp it is up to you. The pseudo names dont help significantly. It gives you a small amount of help with the socketcall issues on 32 bit linux, but you are largely on your own.

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.


OK, now someone put this in PDF readers, so that once they open the specified PDF file, but before they start reading and parsing it, they call "pledge" and lock out further file opens. (If this breaks Adobe WebBuy, so be it.)


The mupdf PDF reader has been patched to make use of pledge on OpenBSD.


An OpenBSD developer vouched for MuPDF's code quality on Schneier's blog. A combo of good code and use of OS mitigations is a good sign. Might try to switch to it soon.


The Enterprise world will continue to read their PDFs using Adobe remote management software independent of what OpenBSD does, the rest of the world is there already (browser PDF readers).


As if browsers aren't full of security holes... It would really be a good idea to split up the browser into separate executables that could each use pledge() (more or less like Chrome, but a bit more granular).


Chrome's model is based on OP, which is a high-assurance-style model. If interested in secure browsing, look up OP2 Web Browser and IBOS Illinois Browser OS. Gazelle from Microsoft is also interesting.


When I get time, Im going to straight up try and run one through the tools like Softbound or Code Pointer Integrity that CompSci is building. If performance hit isn't too high, then problem mostly solved.


Oh, and put this in Flash. All you get to talk to is the originating site. No local file access except Flash's local config and cache files, which can be opened before reading the .swf input.


Additional info in comments on lobste.rs: https://lobste.rs/s/dmhmdc/support_of_openbsd_pledge_2_in_pr...


I'm not familiar with OpenBSD and certainly not with pledge, so I'm having little luck finding the answer to:

Can I start a process in some way that means "demand a pledge call, and only allow [x,y,z] / disallow [a,b,c]"?


The same way you start any other process: fork/exec. But in between (i.e., after you fork but before you exec), call pledge.

I can't test that since I don't have openbsd installed, but I don't see why it wouldn't work.


That won't work because exec resets pledge.

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.


> 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.


> ISTM this will just slightly raise the bar so that attackers who get code execution have to force a call to execve.

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.


It is indeed another security mitigation, any potential attack payload will need to do more work and hence require more code.

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.


> 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--

/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.


Well, binary shellcode often has the sole purpose of providing shell access, so if you can just exec /bin/sh then that job is already done...


You're right, of course. If you promise exec, you should certainly expect someone will find a way to use it.


> this will just slightly raise the bar so that attackers who get code execution have to force a call to execve

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.


> exec resets pledge

Source? I didn't see that in the man page.


From the manpage:

> 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().


That's not clear, though. "The new program" it talks about is after running fork and exec, not just exec. It doesn't specify which call resets the pledge.


From the quoted text I'd understand it's the `exec` that resets the pledge.


I installed OpenBSD so I could check this out. tl;dr, you were right.

    $ 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
    asdf


After fork, the original program is still running. The text specifically refers to the proc promise, which allows fork. It may be tersely formulated, but I really don't see how you could interpret this text otherwise.


it seems to me that the Go package can easily slot in golang.org/x/unix, where all the extra syscalls not present in the fixed stdlib syscall package go. that's a minor point. if pledge becomes widespread in usage it will get its spot there.


pledge seems like it could also help in another scenario that the recent npm issues should make us worry about.

When 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)


Idea looks really really nice.

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?


I think being able to "unpledge" would defeat the purpose of pledge. Instead, I think the better way would be to have your app run by a parent, and when you lose connectivity to your db server, you crash your app on purpose and whenever your app crashes, parent restarts it. Problem solved, I think.


Thanks!


Anyone know what the major differences are between OpenBSD's pledge and OS X's libsandbox ?


OS X's libsandbox is much closer to SELinux. It's MAC-based (mandatory access control not Macintosh) and is actually TrustedBSD under the covers. Pledge simply disallows access to syscalls and paths outside a list. It's not very fine-grained. It also resets on exec, so it can't be used as a sandbox or container.


The entire point of pledge is self-sandboxing, in the case of an exec promise the expectation is the new process will also self-sandbox.

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.


Unless it's Bash, with its /dev/tcp interface.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: