[Linux] 특수 권한 설정 - SetUID, SetGID

Woody의 기록·2023년 7월 25일
2

Linux

목록 보기
4/4
post-thumbnail
post-custom-banner

✓ SetUID와 SetGID

  • 프로세스가 실행되는 동안 해당 파일의 소유자(Owner) 권한 또는 소유 그룹(Group)의 권한을 임시로 가져오는 기능이다.
  • 소유자의 권한을 가져오는 기능을 SetUID, 소유 그룹의 기능을 가져오는 기능을 SetGID라고 한다.
  • SetUID 권한이 명시된 디렉터리에 생성되는 모든 하위 디렉터리나 파일도 SetUID 권한을 가진다.

✓ SetUID와 SetGID는 왜 필요한가?

프로세스가 사용자보다 높은 수준의 접근을 요구할 경우, 파일 접근 제한으로 인해서 원할 기능을 수행할 수 없는데 이러한 문제를 해결하기 위한 방법으로 setUID와 setGID가 등장하였다.

그러면 애초에 다른 사용자에게도 Read, Write, Excute 중에서 필요한 권한을 chmod로 아예 허용해주면 되지 않는가 하는 생각이 들었다.

SetUID와 SetGID를 통해 실행중에 권한 상승을 이용하면 다음과 같은 이점을 가질 수 있다.

  1. 특정 작업에 대한 권한 제어:

    • 모든 파일에 대해 높은 권한을 부여하는 대신, 특정 작업을 수행하는데 필요한 최소한의 권한만 부여할 수 있다. SetUID와 SetGID를 사용하면 그러한 프로그램만 해당 작업을 위해 높은 권한으로 실행될 수 있다는 장점이 있다.
  2. 보안과 권한 관리:

    • 모든 프로그램에 높은 권한을 주는 것은 보안상 위험하다. SetUID와 SetGID를 사용하여 권한 상승을 필요로 하는 프로그램만 해당 권한을 얻도록 설정함으로써 보안 취약점을 최소화하고 시스템의 안정성을 유지할 수 있다.
  3. 사용자 편의성:

    • 일반 사용자가 특정 작업을 수행하려면 매번 루트 권한으로 전환해야 하는 번거로움을 피할 수 있다. SetUID와 SetGID를 사용하면 해당 작업을 위한 프로그램을 실행하는 것만으로도 높은 권한으로 작업을 수행할 수 있다.

실제로 passwd 명령어도 SetUID를 사용하는 예시중에 하나이다.

리눅스에서 사용자의 패스워드는 /etc/shadow 에 기록되는데 shadow 파일은 보안의 이유로 다른 사용자들이 수정할 수 없다.

/etc/shadow 파일의 권한

root@824f84264a66:/etc# ls -l | grep shadow
-rw-r----- 1 root shadow   390 Jul 24 06:47 gshadow
-rw-r----- 1 root shadow   384 Jul 24 05:43 gshadow-
-rw-r----- 1 root shadow   767 Jul 24 06:47 shadow
-rw-r----- 1 root shadow   672 Jul 24 06:19 shadow-

/usr/bin/passwd의 권한

root@824f84264a66:/usr/bin# ls -l | grep passwd
-rwsr-xr-x 1 root root      63528 Nov 24  2022 gpasswd
-rwsr-xr-x 1 root root      55544 Nov 24  2022 passwd

비밀번호를 설정하는데 사용되는 passwd 명령어는 내부적으로 shadow 파일을 수정하여 비밀번호를 변경하게 된다. passwd는 일반사용자도 사용(실행)할 수 있는 권한을 가진 명령어이다.

패스워드를 초기화하거나 변경할 때 사용하는 passwd 명령어는 /usr/bin에 위치하는데 해당 파일의 권한을 살펴보면 rwsr-xr-x로 SetUID가 적용되어 있는 것을 볼 수 있다.

따라서 passwd 실행 중에 사용자는 passwd의 소유자인 root 권한을 가지고 수행하기 때문에 내부적으로 shadow 파일을 변경하는 로직을 root가 아닌 다른 사용자들도 passwd 명령어를 통해서 수행할 수 있게 되는 것이다.

✓ SetUID와 SetGID 권한 부여

리눅스에서 숫자로 권한을 표현하는 방식

일반적으로 리눅스에서 권한은 4자리 정수로 표현된다.

첫번째 정수는 특수권한인 SetUID, SetGID, Sticky bit을 표현하기 위한 자리이며 이후의 3자리는 순서대로 Owner, Group, Others에 대한 read, write, excute 권한에 대한 권한을 각각 하나의 8진 숫자로 표현한 것이다.

예를 들어 권한이 4자리 정수로 0644 경우 기호로 표기하면 rw-r- -r-- 가 되는데

첫번째 값이 0이므로 특수권한은 별도로 설정되지 않았음을 의미하고 Owner에 대해 부여된 정수값은 6이므로 read, write 권한이, Group에 대한 정수값은 4이므로 Read 권한이, Others에 대한 정수값은 4이므로 Read 권한이 부여된 상태로 해석 할 수 있다.

위와 같이 일반적으로 특수권한이 부여되지 않은 경우 권한에 대한 첫번째 숫자는 0으로 설정된다.
SetUID를 설정하려면 권한의 첫번째 정수값을 4로 지정하고 SetGID를 설정하고자 할 경우 첫번째 정수값을 2로 지정하면 된다.

SetUID와 SetGID 권한 표현

SetUID, SetGID 권한 설정 예시:

  1. SetUID 적용

    $ chmod 4666 hello

  2. SetGID 적용

    $ chmod 2755 hello

✓ SetUID 적용 실습

이해를 돕기 위해 간단한 실습을 준비해보았다. 아래의 실습을 통해 자세히 살펴보자.

RootOnly라는 이름의 디렉터리 생성후, 루트만 해당 디렉터리에 Read,Write 가 가능하고 그룹 및 이외의 사용자는 아무것도 할 수 없도록 권한 설정을 변경해주었다.

root@824f84264a66:/home/test# mkdir RootOnly
root@824f84264a66:/home/test# chmod 600 RootOnly
root@824f84264a66:/home/test# ls -l
total 4
drw------- 2 root root 4096 Jul 25 07:54 RootOnly

만약 woody가 RootOnly에 접근하려고 한다면 Permission Denied 문구가 출력되면서 제한될 것이다.

root@824f84264a66:/home/test# su woody
woody@824f84264a66:/home/test$ ls
RootOnly
woody@824f84264a66:/home/test$ cd RootOnly/
bash: cd: RootOnly/: Permission denied
woody@824f84264a66:/home/test$ touch ./RootOnly/ImWoody
touch: cannot touch './RootOnly/ImWoody': Permission denied

이번에는 SetUID를 본격적으로 사용해보기 위해서 해당 RootOnly 디렉터리에 “Hello I’m Woody”라는 내용을 가진 hello.txt 파일을 write하는 c코드(SetUID_Example.c)를 작성해볼 것이다.

작성한 SetUID_Example.c 코드

root@824f84264a66:/home/test# vim SetUID_Example.c

/* SetUID_Example.c */

#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>

int main() {
    char *file_path = "/home/test/RootOnly/hello.txt";
    char *content = "Hello, I'm Woody\n";

    int fd = open(file_path, O_WRONLY | O_CREAT, 0644);
    if (fd == -1) {
        perror("Failed to open the file");
        exit(EXIT_FAILURE);
    }

    if (write(fd, content, sizeof(content)) == -1) {
        perror("Failed to write to the file");
        close(fd);
        exit(EXIT_FAILURE);
    }

    printf("Successfully wrote to the file.\n");

    close(fd);

    return 0;
}

"SetUID_Example.c" 27L, 580B                                  12,2          Top

SetUID_Example.c를 gcc로 컴파일

root@824f84264a66:/home/test# gcc -o SetUID_Example SetUID_Example.c
root@824f84264a66:/home/test# ls
RootOnly  SetUID_Example  SetUID_Example.c

생성된 SetUID_Example의 권한 확인

root@824f84264a66:/home/test# ls -l
total 20
drw------- 2 root root 4096 Jul 25 07:54 RootOnly
-rwxr-xr-x 1 root root 9088 Jul 25 08:07 SetUID_Example
-rw-r--r-- 1 root root  580 Jul 25 08:06 SetUID_Example.c

ls -l 로 권한을 확인해보면 SetUID_Example는 root 소유 파일로 rwxr-xr-x 권한이 부여되어 있는 것을 볼 수 있다. 따라서 root 가 아닌 그룹이나 이외의 사용자들도 execute가 가능한 상태이다.

🤔 그렇다면, woody 계정에서 해당 SetUID_Example를 통해 RootOnly 디렉터리에 hello.txt를 작성하는 것은 가능할까?

→ 정답은 불가능하다이다. 왜냐하면 SetUID_Example 자체는 실행할 수 있다고 해도 woody의 권한으로는 SetUID_Example 내에서 일어나는 RootOnly 디렉터리내에 hello.txt를 Write 하는 행위를 할 수 없기 때문이다. 결국 SetUID_Example를 실행한다고해도 실행중에 Woody가 가지는 권한(EUID)는 Woody 인데 RootOnly 디렉터리에 부여된 권한 설정은 drw-------로 root 이외의 모든 사용자에 대해서 write가 제한되기 때문에 Permission Denied가 발생하게 된다.

직접 확인해보자

woody로 계정 변경 후 SetUID_Example 실행

root@824f84264a66:/home/test# su woody
woody@824f84264a66:/home/test$ ./SetUID_Example
Failed to open the file: Permission denied

예상 했던대로 Permission denied가 발생한다. open을 통해 fd에 할당하는 과정에서 denied 된 것인데,

RootOnly 디렉터리의 권한설정은 Read 또한 불가능하도록 되어있기 때문에 접근하지 못하여서 발생하는 것이다.

다시 root로 전환한 후 이번에는 SetUID_Example에 SetUID 권한을 설정해보자

root 계정으로 전환 후 SetUID 권한을 설정

root@824f84264a66:/home/test# chmod 4755 SetUID_Example
root@824f84264a66:/home/test# ls -l
total 20
drw------- 2 root root 4096 Jul 25 07:54 RootOnly
-rwsr-xr-x 1 root root 9088 Jul 25 08:07 SetUID_Example
-rw-r--r-- 1 root root  580 Jul 25 08:06 SetUID_Example.c

권한을 표현하는 4자리 숫자중 가장 첫번째 숫자를 4로 지정하면 SetUID가 설정된다.

ls -l로 확인해보면 -rwsr-xr-x 로 설정된 것을 볼 수 있다.

Owner의 execute 권한은 원래 기호로 x 가 입력되는데 s 로 되어있는 것을 의미한다. SetUID가 적용된 것을 의미하는데, 다른 사용자가 SetUID_Example를 실행하는 동안은 SetUID_Example의 소유자인 root와 동일한 권한을 가지게 된다는 것을 의미한다.

이제 다시 woody로 넘어가서 정말 동일한 권한을 가지는지 확인해보자.

woody로 전환 후 SetUID_Example 실행

root@824f84264a66:/home/test# su woody
woody@824f84264a66:/home/test$ ./SetUID_Example
Successfully wrote to the file.

성공적으로 파일을 생성했을 때 출력하도록 해두었던 “Successfully wrote to the file.” 라는 메시지가 출력되면서 정상적으로 실행된 것을 볼 수 있다.

root로 전환 후 생성된 파일 확인

woody@824f84264a66:/home/test$ su
woody@824f84264a66:/home/test# cd RootOnly
root@824f84264a66:/home/test/RootOnly# ls
hello.txt

root 계정으로 접속하여 직접 디렉터리 내에 생성된 파일도 확인해 볼 수 있다.

profile
Github - https://www.github.com/woody35545
post-custom-banner

0개의 댓글