Reputation: 8637
I realize this sounds a little crazy, but I'm working on a project for which I need a server to run user-provided Ruby code and return the result.
I'm looking to prevent something like this:
system("rm -rf /")
eval("something_evil")
# etc...
I'm sure there must be some reasonably safe way to do this, as it already exists at places like tryruby.org. Any help is greatly appreciated, thanks!
Upvotes: 8
Views: 930
Reputation:
I had the same problem but then came across eval.so and decided to write an API wrapper for it, called Sandie. It's as easy as:
sandie = Sandie.new(language: 'ruby')
# => #<Sandie:0x00000002e30650>
sandie.evaluate(code: 'puts "hello world"')
# => {"stdout"=>"hello world\n", "stderr"=>"", "wallTime"=>487, "exitCode"=>0}
It also supports a whole lot of other languages as well like C#, Perl, Lua, and Java.
Upvotes: 0
Reputation: 107979
A "blank slate" is an object stripped of (most of) its methods. A "clean room" is an object within which you evaluate potentially unsafe room. If you evaluate the code in a "clean room" which is also a "blank slate," cranking the safe level up as high as it will go, you will afford yourself a great deal of protection. Nothing in security is sure, so this should be considered a layer in your security, not necessarily the only layer.
This answer shows how to do it.
Upvotes: 2
Reputation: 41247
Three suggestions:
1) Take a look at Ruby taint levels. This provides some degree of protection against, eval('evil_code')
type things, etc.
2) Unless user's actually need access to the local file system, use something like fakefs
3) No matter what else you do follow Tronic's suggestion (can be a pain to setup, but limited chroot jails are about the only way to make absolutely sure that user's cannot access resources you don't explicitly want them to).
Upvotes: 6
Reputation: 10430
Run the program ptraced with a whitelist of allowed syscalls, as user/group nobody, with resource limits (memory usage etc), in a minimal chroot.
Upvotes: 3