簡體   English   中英

如何(合法地)將自己放入chroot沙箱后訪問文件?

[英]How to (legitimately) access files after putting self into chrooted sandbox?

更改Linux C ++程序,為用戶提供有限的文件訪問權限。 因此,程序自己chroot到一個沙箱,其中包含用戶可以獲得的文件。 一切順利。

但是,現在,程序需要根據自己的需要訪問某些文件( 而不是用戶),但它們位於沙箱之外。 我知道chroot允許訪問在chroot 之前打開的文件,但在這種情況下,所需的文件可能會有數百個,所以打開它們對於可能需要的那對夫婦來說顯然是不切實際的。

有辦法獲取文件嗎?

將它們復制到沙箱中或在chroot之前打開它們。 認真。 如果有辦法做到這一點,那么就有辦法讓它變得允許其他訪問並使你的保護無用。

沙箱的重點是要完全避免你想要實現的目標。

如果文件都在1目錄中,則可以使用mount將它們綁定到沙箱中的目錄。

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

您可以通過/sandbox/files/訪問這些文件。 如果您不希望用戶看到它們,請將mount --bind /path/to/files /sandbox/.files以便隱藏.files目錄

我想你應該能夠把你的程序分成兩部分,一部分是chroot'ed而另一部分是chroot'ed,並且chroot'ed部分請求文件的內容來自非chroot'ed部分,通過您選擇的IPC機制。

這是一個黑客,它可能很容易出錯,否定chroot的任何好處。 就像paxdiablo說的那樣,你試圖繞過chroot沙箱的整個目的,所以你的選擇非常非常有限。

也許如果你再解釋一下你想要完成的事情,我們或許可以提供一些其他的想法。 例如,SELinux和AppArmor比chroot更靈活,並且可以為您提供所需的安全性。

如果您需要訪問的文件位於幾個目錄中,則可以 chroot並保存文件描述符之前打開這些目錄。 然后,您可以使用所謂的* at函數(例如openat()renameat()等)來獲取單個文件。 基本上,您打開的文件對於已打開的目錄文件描述符而不是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”> /tmp/mystuff.dat

mkdir / tmp / jail

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM