2010-03-14 3 views
4

사용자에게 제한된 파일 액세스 권한을 부여하는 Linux C++ 프로그램 변경. 따라서 사용자가 얻을 수있는 파일이있는 샌드 박스에 프로그램 chroots 자체가 있습니다. 모두 잘 작동했습니다. 자기를 chrooted 샌드 박스에 넣은 후 파일에 액세스하는 방법 (합법적으로)?

지금, 그러나, 프로그램은 자신의 필요하지만 샌드 박스 외부에있는 (사용자가 하지)에 대한 일부 파일에 액세스 할 필요가있다. 나는 chroot가 전에 chroot 전에 열리는 파일에 대한 액세스를 허용한다는 것을 알고 있지만이 경우에는 필요한 파일이 수백 개에서 수백 개가 될 수 있으므로 필수 일 수있는 커플을 위해 모두 열 수는 분명히 비실용적입니다.

파일을 가져 오는 방법이 있습니까?

+0

당신이 chroot 환경에서뿐만 아니라 파일을 복사 할 수 없습니다 mystuff.dat? – fabrizioM

+0

아니요, 너무 많아서 사용자가 보지 않아야하며 다른 프로그램에서 업데이트합니다. – ValenceElectron

답변

2

액세스해야하는 파일이 몇 디렉토리에있는 경우 디렉토리를 열고 전에 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; 
} 

:

에코에 "Hello World">/tmp를/mystuff에.DAT

에서 mkdir/tmp를/감옥

sudo는 ./myprog/tmp를/감옥/tmp 디렉토리는

+0

파일은 3 개의 디렉토리에 있습니다. – ValenceElectron

+0

이것은 원칙적으로 작동하는 것 같습니다. 나는 그것을 더 많이 테스트하고 일부 사람들에 의해 실행 하겠지만 이것은 우리에게 좋은 단기 해결책 일 수 있습니다. 감사! – ValenceElectron

+1

openat()이 "../"을 포함하는 상대 경로 이름을 허용하지 않는 한, 내 man 페이지에서 그 영향을 볼 수 없으면 감옥이 완전히 깨집니다. – pra

8

chroot ing 전에 샌드 박스에 복사하거나 모두 엽니 다. 진지하게. 이렇게 할 수있는 방법이 있다면 다른 접근을 허용하고 보호를 쓸모 없게 만들 수있는 방법이 있습니다.

샌드 박스의 모든 부분은 달성하려는 것을 정확히 방지하기위한 것입니다.

2

파일이 모두 하나의 디렉토리에 있으면 mount를 사용하여 파일을 샌드 박스 내부의 디렉토리에 바인드 할 수 있습니다.

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

당신은 /sandbox/files/을 통해 파일에 액세스 할 수 있습니다. 사용자가 볼 수 없도록하려면 mount --bind /path/to/files /sandbox/.files을 입력하여 .files 디렉토리를 숨기십시오.

+1

사용자가/sandbox/files에 액세스 할 수 없습니까? – ValenceElectron

+1

해당 프로그램이 샌드 박스와 상호 작용하는 유일한 방법이면 프로그램 인터페이스를 통한 액세스를 금지 할 수 있습니다. – m42a

2

프로그램을 두 부분으로 나눌 수 있어야합니다. 하나는 chroot이고 다른 하나는 isn입니다. 'chroot'된 부분 요청 파일의 내용을 chroot되지 않은 부분에서 원하는 IPC 메커니즘을 통해 가져옵니다.

이것은 해킹이며 잘못 될 수 있으며 chroot의 이점을 무효화 할 수 있습니다. paxdiablo와 마찬가지로 chroot 샌드 박스의 모든 목적을 달성하려고 노력하고 있으므로 옵션이 매우 제한적입니다.

아마도 여러분이 달성하려는 것을 조금 더 설명하면 다른 아이디어를 제시 할 수있을 것입니다. 예를 들어, SELinux와 AppArmor는 chroot보다 유연성이 뛰어나며 보안을 제공 할 수 있습니다.

+0

그것들은 모두 유효한 옵션이며, 상황이 계속되는 곳이라면 나는 그것을 사용할 것이다. 그러나 수술을 덜 필요로하는 것을 기대하고있다. 하나는 희망 이겠지? – ValenceElectron