최근 프로젝트 중 인프라 회사와 함께 협업하는 프로젝트가 있었다. 이전까지 사용하던 방식과는 다르게 상당히 세세한 퍼미션 설정으로 환경을 잡길래 다시 공부하는 겸 정리하게 되었다.

리눅스(또는 Unix-like) 시스템에서는 파일의 접근 권한과 파일의 종류를 16비트에 할당해서 관리하고 있다. 이 퍼미션은 심볼릭 표기법과 8진수 표기법으로 나타낼 수 있다. 흔히 심볼릭 표기법 즉, -rwxr-xr-x와 같은 형태로 접할 수 있다.

파일의 퍼미션은 파일의 상태를 확인하는 명령 stat로 확인할 수 있다.

$ stat hello
  File: 'hello'
  Size: 8760        Blocks: 24         IO Block: 4096   regular file
Device: 2dh/45d Inode: 15170       Links: 1
Access: (0755/-rwxr-xr-x)  Uid: (    0/    root)   Gid: (    0/    root)
Access: 2016-08-11 06:56:19.100326163 +0000
Modify: 2016-08-11 06:55:22.698669517 +0000
Change: 2016-08-11 07:23:31.122522096 +0000
 Birth: -

-c, 또는 --format 플래그를 사용해서 원하는 정보만 출력하는 것도 가능하다. 다음처럼 심볼릭 표기법과 8진수 표기법, 소유자, 그룹, 파일명을 확인한다.

$ stat -c "%a %A %U:%G %n" hello
755 -rwxr-xr-x root:root hello

파일 타입

심볼릭 표기법에서 첫 번째 기호는 파일 타입을 의미한다. 이 정보는 16비트 중 4비트에 해당한다.

  • -: 일반 파일
  • d: 디렉토리
  • l: 심볼릭 링크
  • p: Named pipe
  • s: 소켓
  • b, c: 디바이스 파일

그 외에도 Door 등이 존재한다.

접근 권한

접근 권한은 소유자 접근 권한(owner, u), 그룹 접근 권한(group, g), 기타 사용자 접근 권한(others, o)으로 구분된다. 각각의 권한은 읽기(r, 4), 쓰기(w, 2), 실행하기(x, 1)로 구성되어 있다.

각각 3비트로 구성된 3가지 접근 권한으로 총 16비트 중 9비트를 차지한다.

$ chmod 000 hello # 8진수 표기법으로 권한 없음 지정
$ chmod a= hello # 심볼릭 표기법으로 권한 없음 지정
$ chmod 755 hello # 소유자 rwx, 그룹 rx, 기타 rx
$ chmod u=rwx,g=rx,o=rx hello
$ chmod 644 hello # 소유자 rw, 그룹 r, 기타 r
$ chmod u=rw,g=r,o=r hello

특수 권한

특수 권한은 setuid, setgid, 스티키(sticky) 비트가 있다. 16비트 중 앞에서 사용한 파일 타입과 접근 권한을 제외한 나머지, 3비트는 특수 권한을 저장하는 비트로 사용한다.

물론 기본적으로 접근하는 사용자의 권한은 앞에서 설정한 접근 권한을 따르게 된다. 접근 권한에서 접근을 허용하지 않은 상태에서는 아래 특수 권한도 동작하지 않게 된다. 접근 권한과 특수 권한을 조합하면 많은 경우의 수가 나오지만 실행 권한이 없으면 의미가 없는 경우도 있어서 실제로 사용하는 방식은 다소 제한적인 편이다.

특수 권한이 있기 때문에 root 사용자가 아닌 사용자도 ping과 같은 명령을 사용할 수 있게 된다. /tmp와 같은 공유 디렉토리도 특수 권한 중 하나를 사용한다.

Set-user Identification (SUID, setuid, 4)와 Set-group Identification (SGID, setgid, 2)

setuid가 지정되어 있는 파일을 실행하면 해당 파일은 파일 소유자의 권한으로 실행하게 된다. setgid가 지정되어 있는 파일을 실행하면 해당 파일에 지정되어 있는 그룹의 권한으로 실행하게 된다. 물론 애초에 파일에 접근하는 사용자에게 실행하는 권한이 있어야 실행 가능한 것은 마찬가지다. root 권한으로 지정된 프로그램에 이 비트가 적용되어 있다면 실행할 때 root 권한으로 실행 된다는 뜻이다.

이 기능은 보안상 shell script에서는 동작하지 않는다. 실제로 동작을 확인하고 싶다면 작은 C 프로그램을 만들어서 테스트 해볼 수 있다.

#include <stdio.h>

int main () {
  printf("EUID: %d\nUID: %d\nEGID: %d\nGID: %d\n", geteuid(), getuid(), getegid(), getgid());
  return 0;
}

다음은 setuid를 사용한 예다. 같은 그룹 사용자는 해당 파일을 실행할 수 있고 실행할 때 소유자 권한으로 실행하게 된다.

$ chmod 4750 helloworld # 8진수 표기법
$ chmod u=rwxs,g=rx,o= helloworld # 심볼릭 표기법

다음은 setgid를 설정했다. 이 설정은 누구나 파일을 열 수 있으며 helloworld에 지정된 그룹 권한으로 실행한다.

$ chmod 2755 helloworld
$ chmod u=rwx,g=rxs,o=rx helloworld

Sticky 비트 (1)

스티키 비트는 일종의 공유 디렉토리와 같은 권한을 제공한다. 이 비트가 설정되어 있는 상황에서는 접근 권한이 있는 상황에서도 자신의 소유가 아닌 파일을 삭제할 수 없게 된다. 일반적으로 /tmp와 같은 임시 디렉토리에서 사용한다.

다음은 root 계정에서 haruair의 접근 권한이 있는 파일을 생성했지만 스티키 비트가 지정된 폴더 내에 있어서 삭제할 수 없는 예시다.

# mkdir tmp
# chmod 1777 tmp
# chmod a=rwx,=t tmp
# cd tmp ; touch hello
# chmod 777 hello
# sudo -u haruair -i
$ cd tmp ; rm hello
rm: cannot remove 'hello': Operation not permitted

특수 권한 적용하기

chmod를 8진수 표기법과 함께 사용하는 경우에는 주로 3자리로 많이 사용하지만 4자리로 사용하면 첫 번째 숫자가 특수 권한에 해당한다. 즉, chmod 700chmod 0700과 동일하다. 만약 특수 권한이 지정되어 있는 디렉토리에 chmod 700 식으로 지정하면 기존의 특수 권한이 모두 사라지기 때문에 주의해야 한다.

특수 권한으로 인한 보안 문제

특수 권한은 일반적인 파일 접근 방식과 다르기 때문에 사용에 주의해야 한다. 특히 root 권한으로 실행되도록 setuid가 지정된 프로그램에 보안 취약점이 있다면 공격 대상이 될 수 있다.


퍼미션은 가장 기초적인 수준이다. 좀 더 편리하게 사용할 수 있는 ACL도 있고 SELinux를 사용해서 더 보안성 높은 환경을 구축할 수도 있다. 최근에는 서버 가상화로 아키텍처 수준에서의 권한 분리가 이뤄진다. 상황에 맞는 기능을 선택해서 사용하도록 하자.

색상을 바꿔요

눈에 편한 색상을 골라보세요 :)

Darkreader 플러그인으로 선택한 색상이 제대로 표시되지 않을 수 있습니다.