justincormack / ljsyscall

LuaJIT Unix syscall FFI
http://www.myriabit.com/ljsyscall/
Other
440 stars 53 forks source link

Bind ptrace #178

Open daurnimator opened 9 years ago

daurnimator commented 9 years ago

Please bind ptrace :)

justincormack commented 9 years ago

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

daurnimator commented 9 years ago

I'd like to lock down an untrusted script.

This requires

justincormack commented 9 years ago

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 commented 9 years ago

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 commented 9 years ago

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 commented 9 years ago

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 commented 9 years ago

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

daurnimator commented 9 years ago

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 commented 9 years ago

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

daurnimator commented 9 years ago

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 commented 9 years ago

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 commented 9 years ago

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

justincormack commented 9 years ago

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 commented 9 years ago

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 commented 9 years ago

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 commented 9 years ago

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 commented 9 years ago

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