Egloos | Log-in
F/OSS study
F/OSS study
[Linux] POSIX capability
Linux: 2.6.34


capability는 (현재는 제외되었지만) POSIX 1003.1e 초안에서 제안한 것으로
전통적인 super user (root) 기반의 시스템 관리 권한을 좀 더 세분화하여
보안 위협에 대처하고자 만들어진 보안 모델이다.
다시 말하면, 특정한 관리 작업을 수행할 때 root가 가지고 있는 모든 권한을 부여하는 것이 아니라
해당 작업에 필요한 권한 만을 부여하면, 프로그램의 버그 등으로 인해 해당 프로그램이 악의적인
사용자에게 제어 권한을 넘겨주었다 하더라도, 다른 권한이 주어지지 않았으므로 시스템의 피해를
최소화시킬 수 있게 되는 것이다.

시스템 내의 모든 프로세스는 자신의 보안 정보를 관리하는 cred 구조체를 가지고 있으며
여기에 해당 프로세스의 capability 정보도 물론 포함되어 있다.
각각의 capability는 32비트 정수형 데이터 내의 비트로 표현되며
/usr/include/linux/capabiliy.h 파일에서 자세한 내용을 찾아볼 수 있다.

하지만 capability는 단순히 권한 별로 1개의 비트 만으로 관리되는 것은 아니라
inheritable, permitted, effective라는 3개의 집합으로 나누어지며
추가적으로 bounding set을 가진다. 이는 다음과 같이 확인해 볼 수 있다.

$ cat /proc/self/status | grep Cap
CapInh:    0000000000000000
CapPrm:    0000000000000000
CapEff:    0000000000000000
CapBnd:    ffffffffffffffff

inheritable capability는 말 그대로 상속이 가능한 권한들을 의미하는 것이지만
여기서 말하는 상속은 fork()를 통한 parent/child 관계가 아니라
exec 계열의 시스템 콜을 이용하여 다른 프로세스를 실행하는 경우에 해당한다.
(이는 이 후 file capability를 살펴볼 때 다시 논의하기로 하자.)
fork()의 경우에는 단순히 parent의 capability 값이 그대로 복사된다.

permitted capability는 해당 프로세스에게 허용된 권한들의 의미한다.
하지만 프로세스에게 어떠한 권한이 허용되었다고 하더라도 이것을 바로 사용한다는 것은 아니며
effective capability가 프로세스가 현재 실제로 사용하고 있는 권한들을 나타낸다.

프로세스는 capget() 시스템 콜을 이용하여 (임의의) 프로세스의 capability를 살펴보거나
capset() 시스템 콜을 이용하여 자신의 capability를 조정할 수 있다. (CAP_SETPCAP 필요)
참고로 (file capability 기능이 구현되지 않았던) 2.6.24 이전의 커널에서는
CAP_SETPCAP capability를 가진 프로세스의 경우 다른 프로세의 capability를 조정할 수 있었지만
지금은 불가능하다.

inheritable과 effective capability는 permitted capability에 속한 것들에 한해
조정할 수 있으며, permitted capability는 줄이는 것만 가능하다.

기본적으로 root 사용자로 실행되는 프로세스는 모든 권한을 가지고 있으며
그 외의 사용자는 아무런 권한을 가지지 않도록 되어 있다.
(나중에 보겠지만 이러한 설정들은 변경될 수 있다.)

다음과 같은 예제 프로그램을 root와 일반 사용자로 실행해보면 그 효과를 볼 수 있다.

cap.c:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <linux/capability.h>

#define BUFSIZE  4096

extern int capset(cap_user_header_t header, cap_user_data_t data);

int main(void)
{
  FILE *fp;
  char buf[BUFSIZE];

  cap_user_header_t head;
  cap_user_data_t data;

  head = malloc(sizeof(*head));
  head->version = _LINUX_CAPABILITY_VERSION;
  head->pid = 0;

  data = calloc(sizeof(*data), _LINUX_CAPABILITY_U32S);
  data[CAP_TO_INDEX(CAP_SYS_BOOT)].inheritable = CAP_TO_MASK(CAP_SYS_BOOT);
  data[CAP_TO_INDEX(CAP_SYS_BOOT)].permitted   = CAP_TO_MASK(CAP_SYS_BOOT);
  data[CAP_TO_INDEX(CAP_SYS_NICE)].permitted  |= CAP_TO_MASK(CAP_SYS_NICE);
  data[CAP_TO_INDEX(CAP_SYS_TIME)].permitted  |= CAP_TO_MASK(CAP_SYS_TIME);
  data[CAP_TO_INDEX(CAP_SYS_TIME)].effective   = CAP_TO_MASK(CAP_SYS_TIME);

  if (capset(head, data) < 0)
    perror("capset");
 
  fp = fopen("/proc/self/status", "r");
  while (fgets(buf, BUFSIZE, fp) != NULL) {
    if (strncmp("Cap", buf, 3) == 0)
      printf("%s", buf);
  }
  fclose(fp);

  free(head);
  free(data);
  return 0;
}

linux/capability.h 파일에서 볼 수 있듯이 capability API에는 3개의 버전이 있다.
커널 내부적으로는 v3를 사용하지만 사용자 프로그램에는 호환성을 이유로 v1을 기본값으로 한다.
버전에 따라 조정할 수 있는 capability의 범위가 달라지므로
최근에 추가된 CAP_MAC_OVERRIDE 혹은 CAP_MAC_ADMIN capability를 사용하려면
명시적으로 v3를 사용하도록 위의 코드를 약간 수정해야 한다.

위의 코드를 컴파일하여 실행해보면 다음과 같다.

$ gcc cap.c
$ ./a.out
capset: Operation not permitted
CapInh:    0000000000000000
CapPrm:    0000000000000000
CapEff:    0000000000000000
CapBnd:    ffffffffffffffff
$
$ sudo ./a.out
CapInh:    0000000000400000
CapPrm:    0000000002c00000
CapEff:    0000000002000000
CapBnd:    ffffffffffffffff

위에서 설정한 inheritable과 effective capability는 반드시
설정된 permitted capability 내에 속한 것이어야 한다.
만약 (예를 들어) 위에서 effective capability에 CAP_SYS_ADMIN을 설정했다면
root 사용자로 실행했다 하더라도 일반 사용자와 동일하게 capset()에서 오류가 발생할 것이다.

또한 head->pid 값도 반드시 자신의 pid 혹은 0을 지정해야만 하며
다른 프로세스의 pid를 넣으면 역시 오류가 발생한다.

file capability는 setuid 프로그램과 동일하게 실행 파일에 권한을 부여한 것으로
이를 사용하려면 해당 파일 시스템에서 extended attribute (xattr)을 지원해야 한다.
보다 구체적으로는 "security.capability"라는 이름의 속성을 이용하며
위와 비슷하게 inheritable, permitted, effective capability를 각각 저장한다.
이를 설정하기 위해서는 CAP_SETFCAP capability를 가지고 있어야 한다.

exec()를 통해 새로 실행되는 프로세스의 capability는 다음과 같이 계산된다.
(여기서 p는 프로세스, f는 파일, I/P/E/B는 각각 해당 capability를 나타낸다.)

pI' = pI
pP' = (pB & fP) | (pI & fI)
pE' = fE ? pP' : 0
pB' = pB

여기서 먼저 살펴볼 것은 pB, 즉, 프로세스의 capability bounding set (CapBnd)이다.
이는 파일에 지정된 permitted capability를 제한하는 용도로 사용할 수 있으며
초기값은 제한 없이 모든 권한을 허용하도록 되어 있다.
이후 시스템 관리자가 원한다면 prctl() 시스템 콜의 PR_CAPBSET_DROP 명령을 이용하여
특정한 기능을 제한할 수 있다. (이것도 마찬가지로 값을 증가시킬 수는 없다.)

또한 pE', 즉 새로 실행된 프로세스의 effective capability는 파일에 저장된 값에 따라
permitted와 같아지거나 모두 사라지게 된다. 즉, effective 값은 개별적인 capability 마다
따로 적용되는 것이 아니라 전체 권한에 동일하게 적용되기 때문에 디스크 상에 오직 1비트 만이 저장된다.
따라서 file capability를 이용하기 위해서는 effective 비트는 항상 설정되어야 한다.

그렇다면 file capability에는 2가지 선택이 남아있다.
P & E로 지정한 capability들은 프로세스에 관계없이 (bounding set에서만 제한하지 않으면) 무조건 적용된다.
I & E로 지정한 capability들은 이를 실행하는 프로세스가 해당하는 inheritable capability를
가지는 경우에만 적용된다.

libcap2 라이브러리를 사용하면 프로세스 및 파일에 대한 capability 관리 작업을 좀 더 손쉽게 처리할 수 있다.
libcap2 라이브러리는 이에 대한 API 및 여러 도구들을 제공하므로 명령행에서도 간단히 확인해 볼 수 있다.
또한 pam_cap.so 모듈도 제공하여 로그인 시 /etc/security/capability.conf을 읽어
특정 사용자에게 지정된 (inheritable) capability를 부여하도록 설정할 수도 있다.

마지막으로 capability와 관련된 securebits에 대해서 간략히 살펴보자.
이것도 마찬가지로 프로세스의 cred 구조체에 저장되는 정보이며 다음과 같은 3가지 값을 가진다.
(또한 각각에 대응하는 lock 비트가 존재하여 해당 비트를 더 이상 수정하지 못하도록 한다.)
  • SECURE_NOROOT : setuid 비트가 설정된 root 소유 프로그램 실행 시 capability를 높이지 않는다.
  • SECURE_NO_SETUID_FIXUP : setuid()를 통해 root <-> non-root 간 전환 시 capability를 조정하지 않는다.
  • SECURE_KEEP_CAPS : 위의 설정을 무시하고 root -> not-root 간 전환 시 capability를 유지한다.
이들은 root 사용자를 이용한 전통적인 UNIX 보안 모델에서
capability 기반의 보안 모델로의 매끄러운 전환을 위해 도입된 것이다.
이 값을 수정하기 위해서는 prctl() 시스템 콜의 PR_SET_SECUREBITS 혹은 PR_SET_KEEPCAPS 명령을 이용할 수 있다.

libcap2 라이브러리에 포함된 capsh 도구를 이용하면
현재 프로세스의 capability 및 secure bits 정보를 한 눈에 볼 수 있다.


$ capsh --print
Current: =
Bounding set =cap_chown,cap_dac_override,cap_dac_read_search,cap_fowner,cap_fsetid,cap_kill,cap_setgid,cap_setuid,cap_setpcap,cap_linux_immutable,cap_net_bind_service,cap_net_broadcast,cap_net_admin,cap_net_raw,cap_ipc_lock,cap_ipc_owner,cap_sys_module,cap_sys_rawio,cap_sys_chroot,cap_sys_ptrace,cap_sys_pacct,cap_sys_admin,cap_sys_boot,cap_sys_nice,cap_sys_resource,cap_sys_time,cap_sys_tty_config,cap_mknod,cap_lease,cap_audit_write,cap_audit_control,cap_setfcap,cap_mac_override,cap_mac_admin
Securebits: 00/0x0
 secure-noroot: no (unlocked)
 secure-no-suid-fixup: no (unlocked)
 secure-keep-caps: no (unlocked)
uid=1000

capability는 커널에 별도의 보안 모듈이 설정되지 않은 경우 기본적으로 사용되며
selinux, tomoyo, apparmor 등의 보안 모듈에서도 내부적으로 이 기능을 이용하고 있다.
capability는 보안성을 더욱 향상시키기 위해 도입된 것이기는 하지만
그 자체로도 새로운 문제를 낳을 수 있기 때문에 시스템에 도입하기 위해서는
면밀한 검토 및 운영 정책이 필요할 것이다.


=== 참조 문서 ===

by namhyung | 2010/06/16 13:27 | Kernel | 트랙백 | 핑백(4) | 덧글(0)
트랙백 주소 : http://studyfoss.egloos.com/tb/5338802
☞ 내 이글루에 이 글과 관련된 글 쓰기 (트랙백 보내기) [도움말]
Linked at echospread : 일반유.. at 2011/03/07 09:50

... 05/linux-security-capabilities.html* [Linux] POSIX capability (한글) http://studyfoss.egloos.com/5338802* Solaris 10 Non-Root User...Port 80 http://blogs.sun.com/tls/e ... more

Linked at 일반유저가 1024이하 포트를.. at 2011/10/15 21:24

... 05/linux-security-capabilities.html* [Linux] POSIX capability (한글) http://studyfoss.egloos.com/5338802 * Solaris 10 Non-Root User&#8230;Port 80 http://blogs.sun.com/ ... more

Linked at 일반유저가 1024이하 포트를.. at 2011/10/15 21:24

... 05/linux-security-capabilities.html* [Linux] POSIX capability (한글) http://studyfoss.egloos.com/5338802 * Solaris 10 Non-Root User&#8230;Port 80 http://blogs.sun.com/ ... more

Linked at LSM (Linux Secur.. at 2016/12/15 17:12

... /overcommit_ratio&#8221; 디폴트로 50% 코드 라인 13~15에서 계산된 허용 페이지 수에 전체 스왑 페이지 수를 더한다. 참고 [Linux] POSIX capability | F/OSS capabilities &#8211; overview of Linux capabilities | man7.org User virtual m ... more

:         :

:

비공개 덧글

◀ 이전 페이지 다음 페이지 ▶

카테고리
General
Application
System
Kernel
Book
Tips
태그
build emacs scm sed script perf CAaQA3 git bash gcc binutils glibc CARM vcs patch awk elf blktrace kernel C algorithm linux x86 documentation compiler block-layer SMP synchronization computer-architecture memory
전체보기
이글루 파인더

최근 등록된 덧글
http://serbaserbiinfoterkini56..
by cakra at 09/22
informsi yang bagus dan b..
by cakra at 09/16
informsi yang bagus dan be..
by pordanaia at 08/05
최근 등록된 트랙백
Tod's Ferrari Homme
by Tods Pas Cher,Kodak did ..
Mocassin Femme
by Mocassins Homme, I got so..
natural garcinia cambogia
by
rss

skin by jiinny


X