Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bind ptrace #178

Open
daurnimator opened this issue Apr 28, 2015 · 17 comments
Open

Bind ptrace #178

daurnimator opened this issue Apr 28, 2015 · 17 comments

Comments

@daurnimator
Copy link
Contributor

Please bind ptrace :)

@justincormack
Copy link
Owner

Ok, there is an awful lot of ptrace interface, which bits of it do you want? How were you intending to use it?

@daurnimator
Copy link
Contributor Author

I'd like to lock down an untrusted script.

This requires

  • ptrace("TRACEME") in the forked off process
  • ptrace("O_EXITKILL", pid, true) to prevent runaway
  • ptrace("SYSCALL", pid) to run until the next syscall
  • iov = ptrace("PTRACE_GETREGSET", pid, "NT_PRSTATUS") to get the registers

@justincormack
Copy link
Owner

You know that ptrace sandboxing does not work? eg see http://techandsp.blogspot.co.uk/2012/02/ptrace-based-security-just-does-not.html

The only working sandboxing at present in Linux is seccomp type 2 + cgroups for memory usage, or NaCl.

@daurnimator
Copy link
Contributor Author

You know that ptrace sandboxing does not work? eg see http://techandsp.blogspot.co.uk/2012/02/ptrace-based-security-just-does-not.html

Hmm, I didn't know that. I know lots of software out there that relies on it >.<

The only working sandboxing at present in Linux is seccomp type 2 + cgroups for memory usage, or NaCl.

for seccomp type 2 you need to do it from the forked off process.
AFAIK, this means you need to write it for every interpreter you support.
I take this approach in https://gist.github.com/daurnimator/7de5764fc5ddc5f469ad
But it's not extensible to every language.

P.S. you don't need cgroups for memory usage, setrlimit("AS", { max = n }) should be enough?

@justincormack
Copy link
Owner

For seccomp I use a helper that sets it up then execs the application, so you can do it however you want - as I dont trust the application I dont trust it to secure itself...

I think the issue with rlimit is that it is per process, so if you allow fork the total memory is max processes allowed * memory rlimit, which is less manageable, while cgroups is total for all processes. If you disallow fork it should be fine. You can also control swap, other anon pages, and how the oom killer works when more memory is used.

@daurnimator
Copy link
Contributor Author

For seccomp I use a helper that sets it up then execs the application, so you can do it however you want - as I dont trust the application I dont trust it to secure itself...

I'm imagining something where I trust an interpreter, but not the code I give it.

e.g. so you start python (which should be able to do everything it normally does; I trust the python interpreter), then pass an untrusted script to stdin.

I'm not sure how to accomplish this with seccomp filtering?

@justincormack
Copy link
Owner

It is easier just to leave the interpreter unmodified, you can just exec the script/interpreter after seccomp setup.

@daurnimator
Copy link
Contributor Author

It is easier just to leave the interpreter unmodified, you can just exec the script/interpreter after seccomp setup.

huh? even just opening the interpreter will do all sorts of things that the untrusted script shouldn't be able to do.

@justincormack
Copy link
Owner

No I meant execve("interpreter", ["script"], [env]).

@daurnimator
Copy link
Contributor Author

No I meant execve("interpreter", ["script"], [env]).

I know :P I'm considering that the interpreter needs to do privileged operations; that the script shouldn't be able to do.
e.g. if you consider access to /usr privileged.

@justincormack
Copy link
Owner

The standard way to do that is to have a helper application that performs the privileged operations; you provide a (Unix) socket to the application to talk to it on, and obviously you parse the operations correctly without buffer overflows (ie a simple protocol!). eg see the delegated capabilities part of the Capsicum paper https://www.usenix.org/legacy/event/sec10/tech/full_papers/Watson.pdf - Capsicum is well designed (and indeed it could well be worth switching to FreeBSD to use it as the Linux port seems to be taking a long time...). (I think I put all the capsicum support in ljsyscall).

@daurnimator
Copy link
Contributor Author

Then people aren't going to be able to use standard scripts; again it requires the use of programming language level customisations.

@justincormack
Copy link
Owner

In the sandbox, put stubs for each script which just call the helper, so you can exec as normal, and the stub calls the helper which runs the real script and outputs the results back to stdout/err. Thats deals with exec stuff.

For stuff you are allowed, bind bount it into the script sandbox (read only if necessary).

Hard to know without knowing what kinds of operations you want to allow...

@daurnimator
Copy link
Contributor Author

In the sandbox, put stubs for each script which just call the helper,

huh? I don't know what you mean

Hard to know without knowing what kinds of operations you want to allow...

Lets start with the most minimal: the untrusted script should only be able to read from stdin and write to stdout (+exit I guess).

@justincormack
Copy link
Owner

The first bit was if scripts need to call other scripts to do privileged operations, without modifiying interpreter.

If you just want to read stdin, write stdout, exit,( well also mmap, munmap, sbrk, and a few other housekeeping operations) thats pretty easy to set up in seccomp (or capsicum). posix_spawn the helper, that sets them up, then it execs the interpreter and you are done.

@daurnimator
Copy link
Contributor Author

If you just want to read stdin, write stdout, exit,( well also mmap, munmap, sbrk, and a few other housekeeping operations) thats pretty easy to set up in seccomp (or capsicum). posix_spawn the helper, that sets them up, then it execs the interpreter and you are done.

The issue is that the interpreter (e.g. python), need to be able to set itself up: it needs to open various libs, config files, etc. These are privileges I do not want to give the untrusted script.

Is there a way to start an intepreter, wait for it to do something (e.g. maybe it sends a signal to itself; or writes a single byte to stdout?); and only at that point, lock it down to only be able to use write/read/exit?

@justincormack
Copy link
Owner

You could get the interpreter to call seccomp itself; so as not to have to write this for every language it might be easiest to bind libseccomp for each language (or embed luajit); it has to be the same process you cannot set seccomp on a remote process.

But the things the interpreter does are probably ok, the files should be read only; you could unlink them (assume they are copies in a container) as well...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants