Open kapf opened 9 years ago
Tentative solution to the first part (and #309): https://github.com/stefano-maggiolo/cms/commits/master (last 3 commits). I'd like to add your patch as well. My addition still lacks the whitelisting on compilation (haven't checked, but I'm pretty sure you can write to a file with C's preprocessor).
Let me know what you think, thanks!
I submitted the whitelisting of writable files. I'm not sure what could be a proper solution for the other two problems.
Is there any reason to allow executing and reading of writable files (0777)? If it would be changed to writing only (0722), it will solve part 2 of the second problem (creating and executing a file). I tried this with a simple C++ program and it worked.
As for the first part of the second problem (executing files from /usr), here are some possible solutions:
Thanks for the fix! A few comments:
The access should be either write-only (as artikz said) or read-and-execute-only. Assuming you consider compilation unsafe, you need to be careful with symlinks when overwriting permissions (since the symlink may point outside the sandbox). I'm not aware of a language where you can create files during compilation, though.
Change open(path, "w")
to open(path, "w").close()
so that you don't depend on a refcounting Python interpreter.
Some languages (C, C++, Pascal) can be statically linked, so there's no need for /usr
or any other system files to exist during runtime. Together with the more restrictive permissions, this solves problem 2 at least for those languages.
Other languages (Python, Java) may be restricted by white- and blacklisting files by hand. The execl-Trick works with Python too, so one might want prevent executing /usr/bin/perl
. Having no restriction by default should be fine, as long as you can manage such a whitelist in a config file.
close()
as well (not that I don't trust Python to close the file, but it is more readable).Not sure whether it will help, but seems that remounting /usr with noexec flag and making hard link to /usr/bin/python2.7 inside evaluation sandbox does what we want. Not checked with java though.
As for the first problem: I do not think it is a good idea to re-use the sandbox used in executing the solution for running the checker. Generally, it is not safe to recycle sandboxes without cleaning them up first. There might be symlinks, hardlinks, crazy permissions, dragons etc. in it.
Second, if you do not like Python to be executable inside the sandbox, just do not put it there. This is much easier than inventing complex access control schemes. It might be nice to let CMS configure the parameters of the sandbox (like what should be mounted where) in more pleasant way, though.
For analysis for these and other attacks, please see my paper from last year's IOI conference: https://mj.ucw.cz/papers/secgrad.pdf
I noticed the following sentence by OP:
_The sandbox does not restrict writing to local files and allows access to a large part of the directory tree, in particular everything in /usr/
. Access to all header files in /usr/include
. Is it allowed to #include <boost/graph/dijkstra_shortest_paths.hpp>
?_
I am curious, what if the host wishes to allow #include <boost/graph/dijkstra_shortest_paths.hpp>
as easy as #include <iostream>
, what should the host do?
The sandbox does not restrict writing to local files and allows access to a large part of the directory tree, in particular everything in
/usr/
. Here are some examples how this can be exploited:In the Batch task type (but not restricted to Batch), linking the solution file to the output file can trick the system.
When
res.txt
gets copied to the sandbox directory, it overwrites theoutput.txt
file. This can be fixed in Sandbox.py, see this patch for a possible fix. I have not checked if this fix breaks other task types, but those who are, are vulnerable to this attack anyway. Whitelisting files as proposed in #309 would also work.This is also a privilege escalation, because the path linked to does not need to exist. It is perfectly fine to link to
/tmp/i_was_here
(or any other path) and the EvaluationService process will happily write to that file.Execute installed binaries and load installed libraries. For example, running a Python interpreter from C, even if Python is not an allowed language:
This is possible because
execl
does not start a new process, it just replaces the old one.On a similar note, one could submit a source file that contains a Base64-encoding of a binary file that makes use of "unallowed features" such as being compiling with
-O3
or-pthread
, using a bigint library-lgmp
or similar. This data can be written to a file and executed like above./usr/include
. This is more of a gray zone. Is it allowed to#include <boost/graph/dijkstra_shortest_paths.hpp>
? While those files should not be available in the first place, it would be nice to be able to whitelist only the standard library headers and their dependencies for compiling.