루트 권한을 가진 파일에 프로그래밍 방식으로 쓰는 가장 안전한 방법은 무엇입니까? bash 스크립트에 대해 비활성화 되어

특정 시간에 대규모 응용 프로그램은 루트 권한이 필요한 파일에 적은 수의 쓰기 작업을 수행해야합니다. 실제로 파일이 아니라 Linux에 파일로 노출되는 하드웨어 인터페이스입니다.

전체 응용 프로그램에 루트 권한을 부여하지 않기 위해 중요한 작업을 수행하는 bash 스크립트를 작성했습니다. 예를 들어 다음 스크립트는 하드웨어 인터페이스의 포트 17을 출력으로 활성화합니다.

echo "17" > /sys/class/gpio/export
echo "out" > /sys/class/gpio/gpio17/direction

그러나 suid내 시스템에서 bash 스크립트에 대해 비활성화 되어 있으므로 이것을 달성하는 가장 좋은 방법이 무엇인지 궁금합니다.

  1. 여기에 제시된 해결 방법을 사용 하십시오.

  2. 스크립트를 sudo호출 할 때 비밀번호가 필요하지 않도록 기본 애플리케이션에서 스크립트를 호출하고 sudoers 목록을 편집하십시오. 에 sudo 권한을 부여하는 것이 약간 불편합니다 echo.

  3. 로 C 프로그램을 작성하고 fprintfsuid root로 설정하십시오. 문자열과 파일 이름을 하드 코딩하고 루트 만 편집 할 수 있는지 확인하십시오. 또는 텍스트 파일에서 문자열을 읽고 아무도 파일을 편집 할 수 없도록합니다.

  4. 나에게 발생하지 않았으며 위에서 제시 한 것보다 안전하거나 간단한 다른 솔루션?



답변

sudo액세스 권한을 부여 할 필요가 없습니다 echo. 실제로, 예를 들어로 sudo echo foo > bar리디렉션이 루트가 아닌 원래 사용자로 수행되므로 의미가 없습니다.

함께 작은 스크립트를 호출 sudoNOPASSWD:에 대한 액세스를 해당 스크립트 (및 다른 유사한 스크립트) 사용자가 그것을 액세스해야 (들).

이것은 항상 가장 안전하고 안전한 방법 sudo입니다. 루트 권한이 필요한 적은 수의 명령을 별도의 스크립트로 분리하고 신뢰할 수 없거나 부분적으로 신뢰할 수없는 사용자는 해당 스크립트를 루트로만 실행할 수 있습니다.

작은 sudo스크립트는 사용자로부터 인수 (또는 입력)를 취하지 말아야합니다 (즉, 호출하는 다른 프로그램은 하드 코딩 된 옵션과 인수를 가져야합니다). 사용자로부터 동의합니다.

검증에서 편집증을 가지십시오-제외 할 ‘알려진 나쁜 것’을 찾거나 ‘알려진 좋은 것’만 허용하고 불일치 나 오류 또는 원격으로 의심되는 것을 중단하십시오.

검증 가능한 스크립트 (가 않습니다 바람직 전에 일찍 발생한다 어떤 루트로 다른 사람을).


나는 정말 내가 처음이 답을 쓸 때이 문제를 언급 할 뻔했지만 스크립트가 쉘 스크립트 인 경우는 반드시 제대로 인용 모든 변수를. 어떤 식 으로든 사용자가 제공 한 입력을 포함하는 변수를 인용 할 때는 특히주의해야 하지만 일부 변수가 안전하다고 가정하지 마십시오 . QUOTE THEM ALL .

즉, 잠재적으로 (예를 들면 사용자가 제어 환경 변수를 포함한다 "$PATH", "$HOME", "$USER"등을 명확히 포함 "$QUERY_STRING"하고 "HTTP_USER_AGENT"등등 CGI 스크립트하여). 사실, 그것들을 모두 인용하십시오. 인수가 여러 개인 명령 행을 구성해야하는 경우 배열을 사용하여 인수 목록을 작성하고-를 인용하십시오 "${myarray[@]}".

내가 아직 충분히 “그들 모두를 인용”한다고 말했습니까? 기억해. 해.


답변

gpio 파일에서 소유자를 확인하십시오.

ls -l /sys/class/gpio/

대부분 그룹이 소유하고 있음을 알게 될 것입니다 gpio.

-rwxrwx--- 1 root     gpio     4096 Mar  8 10:50 export
...

이 경우 gpiosudo없이 액세스 권한을 부여 하기 위해 사용자를 그룹에 간단히 추가 할 수 있습니다 .

sudo usermod -aG gpio myusername

변경 사항을 적용하려면 로그 아웃 한 후 다시 로그인해야합니다.


답변

이를위한 한 가지 솔루션 (특히 Linux 데스크톱에서 사용되지만 다른 경우에도 적용 가능)은 D-Bus 를 사용 하여 권한 부여를 위해 루트 및 폴킷 으로 실행되는 소규모 서비스를 활성화하는 것 입니다. 이것은 기본적으로 폴킷을 위해 설계된 것 입니다. 입문서 에서 :

polkit은 권한이없는 프로그램 ( “CLIENTS”)에 서비스를 제공하는 권한있는 프로그램 ( “MECHANISMS”)이 사용할 수 있도록 인증 API를 제공합니다. 시스템 아키텍처 및 큰 그림은 polkit 매뉴얼 페이지를 참조하십시오.

권한이없는 큰 프로그램은 도우미 프로그램을 실행하는 대신 버스에서 요청을 보냅니다. 도우미는 시스템 부팅시 시작된 데몬으로 실행되거나 systemd에서 필요에 따라 활성화 될 수 있습니다 . 그런 다음 도우미는 polkit을 사용하여 요청이 승인 된 장소에서 오는지 확인합니다. (이 경우 과도한 것으로 느껴지면 다른 하드 코딩 된 인증 / 권한 부여 메커니즘을 사용할 수 있습니다.)

나는 D-Bus를 통한 통신에 대한 좋은 기본 기사를 찾았 으며 테스트하지는 않았지만 이것은 믹스에 polkit을 추가하는 기본 예제 인 것으로 보입니다 .

이 방법에서는 setuid로 표시 할 필요가 없습니다.


답변

이를 수행하는 한 가지 방법은 C로 작성된 setuid-root 프로그램을 만들어 필요한 것만 수행하는 것입니다. 귀하의 경우에는 사용자 입력을 전혀 볼 필요가 없습니다.

#include <unistd.h>
#include <string.h>
#include <stdio.h>  // for perror(3)
// #include ...  more stuff for open(2)

static void write_str_to_file(const char*fn, const char*str) {
    int fd = open(fn, O_WRONLY)
    if (-1 == fd) {
        perror("opening device file");  // make this a CPP macro instead of function so you can use string concat to get the filename into the error msg
        exit(1);
    }
    int err = write(fd, str, strlen(str));
    // ... error check
    err = close(fd);
    // ... error check
}

int main(int argc, char**argv) {
    write_string_to_file("/sys/class/gpio/export", "17");
    write_string_to_file("/sys/class/gpio/gpio17/direction", "out");
    return 0;
}

환경 변수 등을 통해 이것을 바꿀 수있는 방법은 없습니다. 왜냐하면 모두 시스템 호출을 수행하기 때문입니다.

단점 : 모든 시스템 호출의 반환 값을 확인해야합니다.

거꾸로 : 오류 검사가 정말 쉽습니다. 오류가 전혀 없다면 그냥 perror구제하십시오 : 0이 아닌 상태로 종료하십시오. 오류가 있으면으로 조사하십시오 strace. 정말 멋진 오류 메시지를 제공하기 위해이 프로그램 자체가 필요하지 않습니다.


답변

sudo를위한 echo 대신 echo tee는 루트 파마를 제한해야하는 상황에 접근하는 일반적인 방법 중 하나입니다. / dev / null 로의 리디렉션은 출력 유출을 막는 것입니다. 티는 원하는 것을합니다.

echo "17" | sudo tee /sys/class/gpio/export > /dev/null
echo "out" | sudo tee /sys/class/gpio/gpio17/direction > /dev/null


답변

원하는 작업을 수행하는 스크립트를 만들 수 있습니다. 그런 다음 OpenSSH에서 사용하는 키를 제공하여 로그인 만 가능한 새 사용자 계정을 작성하십시오.

참고 : 키 파일이 있으면 누구나 해당 스크립트를 실행할 수 있으므로 작업을 수행하지 못하게하려는 사람이 OpenSSH 키 파일을 읽을 수 없는지 확인하십시오.

authorized_keys 파일의 OpenSSH 구성에서 키를 지정하기 전에 다음 “예제”텍스트에 설명 된대로 공백 (공백)으로 명령을 지정하십시오.

command="myscript" keydata optionalComment

이 구성 옵션은 OpenSSH 키가 특정 명령 만 실행하도록 제한 할 수 있습니다. 이제 권한을 부여하는 sudo가 있지만 OpenSSH 구성은 실제로 사용자가 수행 할 수있는 작업을 제한 / 제한하는 데 사용되는 솔루션의 일부이므로 사용자가 다른 명령을 실행하지 않습니다. 이것은 “스도”구성 파일만큼 복잡하지 않기 때문에 OpenBSD를 사용하거나 OpenBSD의 새로운 “doas”( “do as”)가 더 널리 사용되기 시작하면 (사용하는 운영 체제의 향후 버전에서) sudo 구성의 복잡성으로 인해 어려움을 겪을 필요는 없습니다.


답변