更改Linux C ++程序,为用户提供有限的文件访问权限。因此,程序chroots本身就可以使用用户可以获取的文件到沙箱。一切都运作良好。
但是,现在,程序需要根据自己的需要访问某些文件(不是用户的),但它们位于沙箱之外。我知道chroot允许访问在 chroot之前打开的文件,但在这种情况下,所需的文件可能会有数百个,所以打开它们对于可能需要的那对夫妇来说显然是不切实际的。 / p>
有没有办法获取文件?
答案 0 :(得分:8)
将它们复制到沙箱中或在chroot
之前打开它们。认真。如果有办法做到这一点,就会有办法让它变得允许其他访问,并使你的保护毫无用处。
沙箱的重点是要完全避免你想要实现的目标。
答案 1 :(得分:2)
如果文件都在1目录中,您可以使用mount将它们绑定到沙箱内的目录。
mount --bind /path/to/files /sandbox/files
您可以通过/sandbox/files/
访问这些文件。如果您不希望用户看到它们,请执行mount --bind /path/to/files /sandbox/.files
以隐藏.files
目录
答案 2 :(得分:2)
我想你应该能够把你的程序分成两部分,一部分是chroot'ed而另一部分是chroot'ed,并且chroot'ed部分请求文件的内容来自非chroot'ed部分通过您选择的IPC机制。
这是一个黑客,它可能很容易出错,否定chroot的任何好处。就像paxdiablo说的那样,你试图绕过chroot沙箱的整个目的,所以你的选择非常非常有限。
也许如果你再解释一下你想要完成的事情,我们或许可以提供一些其他的想法。例如,SELinux和AppArmor比chroot更灵活,并且可以为您提供所需的安全性。
答案 3 :(得分:2)
如果您需要访问的文件位于几个目录中,则可以在之前打开这些目录,然后chroot并保存文件描述符。然后,您可以使用所谓的* at函数(例如openat(),renameat()等)来获取各个文件。基本上,您将文件 relative 打开到已打开的目录文件描述符而不是chrooted目录。
这是否是一件安全的事情是值得商榷的,但它应该适用于Linux。
编辑:这是丑陋的一面,但似乎有效。你应该为我的漏洞找到更多的漏洞。我还没有测试权限下降等等会影响到什么。
#include <iostream>
#include <string>
using namespace std;
#include <cstdio>
#include <cstdlib>
#include <cerrno>
#include <cstring>
#include <unistd.h>
#include <fcntl.h>
#include <dirent.h>
#include <sys/types.h>
#include <sys/stat.h>
int main(int argc, char *argv[])
{
if (argc < 4)
{
cerr << "USAGE: " << argv[0] << " <jail directory> <freeworld directory> <filename>\n";
exit(EXIT_FAILURE);
}
const string JAILDIR(argv[1]);
const string FREEDIR(argv[2]);
string freefilename(argv[3]);
while (freefilename[0] == '/')
freefilename.erase(0, 1);
DIR *pDir;
if ((pDir = opendir(FREEDIR.c_str())) == NULL)
{
perror("Could not open outside dir");
exit(EXIT_FAILURE);
}
int freeFD = dirfd(pDir);
//cd to jail dir
if (chdir(JAILDIR.c_str()) == -1)
{
perror("cd before chroot");
exit(EXIT_FAILURE);
}
//lock in jail
if (chroot(JAILDIR.c_str()) < 0)
{
cerr << "Failed to chroot to " << JAILDIR << " - " << strerror(errno) << endl;
exit(EXIT_FAILURE);
}
//
//in jail, won't work
//
string JailFile(FREEDIR);
JailFile += "/";
JailFile += freefilename;
int jailFD;
if ((jailFD = open(JailFile.c_str(), O_RDONLY)) == -1)
{
cout << "as expected, could not open " << JailFile << endl;
perror("exected open fail");
}
else
{
cout << "defying all logic, opened " << JailFile << endl;
exit(EXIT_FAILURE);
}
//
//using this works
//
if ((jailFD = openat(freeFD, freefilename.c_str(), O_RDONLY)) == -1)
{
cout << "example did not work. Could not open " << freefilename << " Sorry!" << endl;
exit(EXIT_FAILURE);
}
else
cout << "opened " << freefilename << " from inside jail" << endl;
char buff[255];
ssize_t numread;
while (1)
{
if ((numread = read(jailFD, buff, sizeof(buff) - 1)) == -1)
{
perror("read");
exit(EXIT_FAILURE);
}
if (numread == 0)
break;
buff[numread] = '\0';
cout << buff << endl;
}
return 0;
}
测试:
echo“Hello World”&gt; /tmp/mystuff.dat
mkdir / tmp / jail
sudo ./myprog / tmp / jail / tmp mystuff.dat