Как (законно) получить доступ к файлам после помещения себя в изолированную программную среду chroot? - PullRequest
4 голосов
/ 14 марта 2010

Изменение программы на Linux C ++, которая дает пользователю ограниченный доступ к файлам. Таким образом, программа сама загружает в песочницу с файлами, которые пользователь может получить. Все работало хорошо.

Теперь, однако, программе необходимо получить доступ к некоторым файлам для своих собственных нужд ( не пользователя), но они находятся вне песочницы. Я знаю, что chroot разрешает доступ к файлам, открытым до chroot, но в этом случае необходимые файлы могут быть немногими из многих сотен, поэтому, очевидно, нецелесообразно открывать их все только для пары, которая может потребоваться.

Есть ли способ получить файлы?

Ответы [ 4 ]

8 голосов
/ 14 марта 2010

Скопируйте их в песочницу или откройте все до chroot ing. Шутки в сторону. Если бы был способ сделать это, был бы способ подчинить его, чтобы предоставить другой доступ и сделать вашу защиту бесполезной.

Весь смысл песочницы - предотвратить то, чего вы пытаетесь достичь.

2 голосов
/ 14 марта 2010

Если файлы, к которым вам нужно получить доступ, находятся в нескольких каталогах, вы можете открыть эти каталоги до , выполнить chroot и сохранить дескрипторы файлов. Затем вы можете использовать так называемые * at функции (например, openat () , renameat () и т. Д.), Чтобы получить отдельные файлы. По сути, вы открываете файлы относительно для уже открытых файловых дескрипторов каталога, а не для корневого каталога.

Является ли это безопасным делом, остается открытым, но оно должно работать в 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"> /tmp/mystuff.dat

мкдир / тмп / джейл

sudo ./myprog / tmp / jail / tmp mystuff.dat

2 голосов
/ 14 марта 2010

Я полагаю, что вы должны иметь возможность разбить вашу программу на две части, одну с chroot'ом, а другую - нет, и получить часть файлов chroot с запросом содержимого файлов из не-chroot порция через механизм IPC по вашему выбору.

Это взлом, и может быть легко ошибиться, сводя на нет любые преимущества chroot. Как говорит Паксдиабло, вы пытаетесь обойти все цели песочницы chroot, поэтому ваши возможности очень и очень ограничены.

Возможно, если бы вы немного подробнее объяснили, чего вы пытаетесь достичь, мы могли бы предложить другие идеи. Например, SELinux и AppArmor более гибки, чем chroot, и могут обеспечить вам необходимую безопасность.

2 голосов
/ 14 марта 2010

Если все файлы находятся в 1 каталоге, вы можете использовать mount, чтобы связать их с каталогом внутри песочницы.

mount --bind /path/to/files /sandbox/files

Вы можете получить доступ к файлам через /sandbox/files/. Если вы не хотите, чтобы пользователь их видел, выполните mount --bind /path/to/files /sandbox/.files, чтобы каталог .files был скрыт

...