4

ユーザーに制限付きのファイル アクセスを許可する Linux C++ プログラムを変更します。したがって、プログラムは、ユーザーがアクセスできるファイルを含むサンドボックスに自分自身をchrootします。すべてうまくいきました。

ただし、現在、プログラムは独自のニーズ (ユーザーのニーズではない) のためにいくつかのファイルにアクセスする必要がありますが、それらはサンドボックスの外にあります。chroot は、chroot の前に開かれたファイルにアクセスできることを知っていますが、この場合、必要なファイルは何百ものファイルのうちの数個になる可能性があるため、必要になる可能性のあるカップルのためだけにそれらすべてを開くことは明らかに非現実的です。

ファイルにアクセスする方法はありますか?

4

4 に答える 4

8

それらをサンドボックスにコピーするか、すべて開いてからchrooting してください。真剣に。これを行う方法があれば、それをサブボーンして他のアクセスを許可し、保護を無効にする方法があります。

サンドボックスの要点は、達成しようとしていることを正確に防ぐことです。

于 2010-03-14T02:36:52.453 に答える
3

ファイルがすべて 1 つのディレクトリにある場合は、mount を使用してサンドボックス内のディレクトリにバインドできます。

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

からファイルにアクセスできます/sandbox/files/。ユーザーに見られたくない場合はmount --bind /path/to/files /sandbox/.files.filesディレクトリを非表示にしてください。

于 2010-03-14T02:51:13.377 に答える
2

プログラムをchrootされた部分とそうでない部分の2つの部分に分割し、chrootされた部分がchrootされていない部分からファイルの内容を要求できるようにする必要があると思います選択した IPC メカニズム。

これはハックであり、chroot の利点を無効にして、間違いを犯しやすいかもしれません。paxdiablo が言うように、chroot サンドボックスの目的全体を回避しようとしているため、選択肢は非常に限られています。

達成しようとしていることをもう少し説明していただければ、他のアイデアを提供できるかもしれません。たとえば、SELinux と AppArmor は chroot よりも柔軟性が高く、求めるセキュリティを提供できる可能性があります。

于 2010-03-14T02:51:33.370 に答える
2

アクセスする必要があるファイルがいくつかのディレクトリ内にある場合は、chroot してファイル記述子を保存する前に、それらのディレクトリを開くことができます。その後、いわゆる *at 関数 (例: openat()renameat()など) を使用して、個々のファイルを取得できます。基本的に、chrootされたディレクトリではなく、すでに開いているディレクトリファイル記述子に 関連するファイルを開いています。

これが安全なことかどうかは疑問の余地がありますが、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

于 2010-03-14T02:54:56.280 に答える