본문 바로가기
운영체제 (LNX,WIN)

리눅스 procfs 시스템 콜 기반 통제: seccomp, AppArmor, SELinux 활용

by 날으는물고기 2025. 4. 12.

리눅스 procfs 시스템 콜 기반 통제: seccomp, AppArmor, SELinux 활용

728x90

Linux Kernel Security (SELinux vs AppArmor vs Grsecurity)

seccomp는 시스템 콜 수준에서 필터링을 수행하는 보안 메커니즘이므로, 특정 시스템 콜을 차단하거나 허용할 수는 있지만, /proc 경로에 대한 직접적인 접근을 제어하지는 않습니다. 하지만 proc 파일 시스템에 대한 접근을 간접적으로 제한할 수 있는 방법은 있습니다.

seccomp로 /proc 접근 제한 가능할까?

/proc은 커널이 프로세스 정보를 제공하는 가상 파일 시스템이므로, 파일 시스템 관련 시스템 콜 (open, openat, read, write, stat, fstat 등)을 필터링하면 접근을 제한할 수 있습니다.

 

예를 들어, /proc의 특정 파일에 접근하려면 일반적으로 다음과 같은 시스템 콜이 필요합니다.

  • openat
  • open
  • read
  • write
  • stat
  • fstat

 

이러한 시스템 콜을 seccomp를 통해 차단하면 /proc 경로에 대한 접근을 제어할 수 있습니다.

seccomp 적용 예제 (BPF 필터 사용)

/proc 경로 접근 차단

seccomp를 사용하여 /proc 내의 파일을 열지 못하도록 설정하려면, openat 시스템 콜을 필터링할 수 있습니다.

 

seccomp를 이용한 /proc 접근 차단 코드 (C 예제)

#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <linux/seccomp.h>
#include <linux/filter.h>
#include <linux/unistd.h>
#include <sys/prctl.h>
#include <sys/syscall.h>

void install_seccomp() {
    struct sock_filter filter[] = {
        /* Load system call number */
        BPF_STMT(BPF_LD | BPF_W | BPF_ABS, offsetof(struct seccomp_data, nr)),

        /* Block openat syscall */
        BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, __NR_openat, 0, 1),
        BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_KILL),

        /* Allow everything else */
        BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_ALLOW)
    };

    struct sock_fprog prog = {
        .len = sizeof(filter) / sizeof(filter[0]),
        .filter = filter,
    };

    if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0)) {
        perror("prctl(NO_NEW_PRIVS)");
        exit(1);
    }

    if (prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog)) {
        perror("prctl(SECCOMP)");
        exit(1);
    }
}

int main() {
    install_seccomp();
    printf("Seccomp 적용 완료: openat 차단됨\n");

    int fd = open("/proc/cpuinfo", O_RDONLY);
    if (fd == -1) {
        perror("open");
    } else {
        printf("파일 열림: /proc/cpuinfo\n");
        close(fd);
    }

    return 0;
}

실행 결과

Seccomp 적용 완료: openat 차단됨
open: Operation not permitted

이 코드는 openat 시스템 콜을 차단하여 /proc/cpuinfo 파일을 열지 못하도록 합니다.

특정 proc 파일만 차단하는 방식

만약 /proc/cpuinfo와 같은 특정 파일만 차단하고 싶다면, openat 시스템 콜의 경로 문자열을 검사해야 하지만, seccomp는 시스템 콜의 인자값을 직접 분석하지 않기 때문에 이를 직접 필터링할 수 없습니다.

 

대신, AppArmorSELinux와 같은 보안 모듈을 활용하여 /proc 내 특정 파일에 대한 접근을 제한하는 것이 더 적절합니다.

seccomp가 아닌 다른 방법으로 /proc 접근 차단

만약 seccomp만으로 /proc을 완전히 차단하는 것이 어렵다면, 다음과 같은 대체 방법을 고려할 수 있습니다.

mount 옵션 사용 (hidepid 설정)

Linux에서는 /proc 파일 시스템을 마운트할 때 hidepid 옵션을 사용하여 다른 프로세스의 정보를 감출 수 있습니다.

mount -o remount,hidepid=2 /proc
  • hidepid=1: 자신이 소유한 프로세스만 볼 수 있음.
  • hidepid=2: 자신의 프로세스 정보만 볼 수 있으며, 다른 사용자의 /proc 접근 차단.
  • hidepid=3: /proc 자체 접근 불가.

 

이를 /etc/fstab에 추가하면 부팅 시 자동 적용할 수 있습니다.

proc /proc proc defaults,hidepid=2 0 0

AppArmor 또는 SELinux를 이용한 /proc 접근 제한

seccomp가 파일 경로 기반의 접근 제어를 수행하지 않기 때문에, /proc 접근을 제한하려면 AppArmor 또는 SELinux를 활용하는 것이 좋습니다.

 

예를 들어, AppArmor에서 /proc 경로를 차단하는 정책을 만들 수 있습니다.

echo "
profile restrict_proc {
  /proc/** rw,
  deny /proc/[0-9]*/** rw,
}
" > /etc/apparmor.d/restrict_proc

그리고 AppArmor를 적용하면 특정 proc 파일에 대한 접근을 제한할 수 있습니다.

sudo apparmor_parser -r /etc/apparmor.d/restrict_proc
  • seccomp/proc 파일 시스템 자체를 제어하지 않지만, openat, read, write 등의 시스템 콜을 필터링하여 간접적으로 접근을 제한할 수 있습니다.
  • seccomp는 파일 경로를 검사하지 않기 때문에, 특정 /proc 파일만 차단하려면 AppArmorSELinux 같은 보안 모듈이 필요합니다.
  • 가장 효과적인 방법은 " mount -o hidepid=2 /proc" 설정 또는 AppArmor를 사용하는 것입니다.

 

seccomp 단독으로 /proc 접근을 제어하는 것은 한계가 있기 때문에, 목적에 따라 추가적인 보안 메커니즘과 병행해서 사용하는 것이 가장 좋은 방법입니다. seccomp는 기본적으로 시스템 콜을 제한하는 기술이므로, 특정 파일이나 디렉터리 자체를 직접 필터링할 수 없습니다. 하지만 특정 파일을 접근하는 데 필요한 시스템 콜을 차단하면 /proc뿐만 아니라 다른 파일 시스템의 접근도 제한할 수 있습니다.

특정 파일 시스템 접근을 제한하는 방법

파일을 읽거나 쓸 때 사용되는 시스템 콜을 seccomp에서 제한하면, 특정 파일을 간접적으로 접근 제한할 수 있습니다.

주요 파일 관련 시스템 콜

시스템 콜 설명
open / openat 파일 열기
read / write 파일 읽기 / 쓰기
stat / fstat 파일 정보 조회
unlink / unlinkat 파일 삭제
rename 파일 이름 변경
mkdir / rmdir 디렉터리 생성 / 삭제

이 중에서 특정 파일을 차단하려면 openat, read, write 등의 시스템 콜을 제한해야 합니다.

특정 디렉터리(예: /sys, /dev, /etc) 접근 차단

만약 /proc뿐만 아니라 /sys, /dev, /etc 같은 특정 시스템 파일이나 디렉터리에 대한 접근을 차단하고 싶다면, openat 시스템 콜을 막으면 효과적입니다.

 

seccomp를 사용한 /sys, /dev, /etc 차단 (C 코드 예제)

#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <linux/seccomp.h>
#include <linux/filter.h>
#include <linux/unistd.h>
#include <sys/prctl.h>
#include <sys/syscall.h>

void install_seccomp() {
    struct sock_filter filter[] = {
        /* 시스템 콜 번호 로드 */
        BPF_STMT(BPF_LD | BPF_W | BPF_ABS, offsetof(struct seccomp_data, nr)),

        /* openat 시스템 콜 차단 */
        BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, __NR_openat, 0, 1),
        BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_KILL),

        /* 기본적으로 모든 시스템 콜 허용 */
        BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_ALLOW)
    };

    struct sock_fprog prog = {
        .len = sizeof(filter) / sizeof(filter[0]),
        .filter = filter,
    };

    if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0)) {
        perror("prctl(NO_NEW_PRIVS)");
        exit(1);
    }

    if (prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog)) {
        perror("prctl(SECCOMP)");
        exit(1);
    }
}

int main() {
    install_seccomp();
    printf("Seccomp 적용 완료: openat 차단됨\n");

    /* /sys, /dev, /etc 파일 접근 테스트 */
    int fd = open("/sys/kernel/security", O_RDONLY);
    if (fd == -1) {
        perror("open(/sys/kernel/security)");
    } else {
        printf("파일 열림: /sys/kernel/security\n");
        close(fd);
    }

    fd = open("/etc/passwd", O_RDONLY);
    if (fd == -1) {
        perror("open(/etc/passwd)");
    } else {
        printf("파일 열림: /etc/passwd\n");
        close(fd);
    }

    return 0;
}

실행 결과

Seccomp 적용 완료: openat 차단됨
open(/sys/kernel/security): Operation not permitted
open(/etc/passwd): Operation not permitted

openat 시스템 콜을 차단하면 /sys, /etc 등의 경로를 열 수 없게 됩니다.

특정 파일 시스템 (proc, sys, dev)을 차단하는 추가 방법

seccomp 단독으로 특정 파일만 선택적으로 차단하는 것은 어렵기 때문에, 아래 방법들을 추가로 활용할 수 있습니다.

mount 옵션을 사용한 접근 차단

  • /proc, /sys, /dev와 같은 시스템 디렉터리는 mount 옵션을 통해 읽기 전용(ro)으로 설정하거나 nosuid, noexec 등의 제한을 걸 수 있습니다.
mount -o remount,ro /proc
mount -o remount,ro /sys
mount -o remount,ro /dev

또는 /etc/fstab에 다음과 같이 추가하면 부팅 시 적용됩니다.

proc /proc proc defaults,ro,nosuid,nodev,noexec 0 0
sysfs /sys sysfs defaults,ro,nosuid,nodev,noexec 0 0
devtmpfs /dev devtmpfs defaults,ro,nosuid,nodev,noexec 0 0

AppArmor 또는 SELinux를 이용한 특정 파일 차단

  • /proc, /sys, /dev 등의 특정 파일에 대한 접근을 제한하려면 AppArmorSELinux 같은 보안 정책을 사용하는 것이 더 효과적입니다.

 

AppArmor 프로필 예제

echo "
profile restrict_sys {
  deny /sys/kernel/security/** rw,
  deny /dev/mem rw,
  deny /proc/[0-9]*/** rw,
  deny /etc/shadow rw,
}
" > /etc/apparmor.d/restrict_sys
sudo apparmor_parser -r /etc/apparmor.d/restrict_sys

SELinux를 활용한 접근 제한

만약 SELinux를 사용한다면 특정 파일에 대한 접근을 deny 규칙을 적용할 수 있습니다.

semanage fcontext -a -t sysfs_t "/sys/kernel/security(/.*)?"
restorecon -R /sys/kernel/security

또는 특정 프로세스가 /proc, /sys에 접근하는 것을 차단할 수도 있습니다.

seccomp를 보완할 수 있는 방법

방법 특징
seccomp 시스템 콜 차단 가능, 특정 파일은 직접 필터링 불가
mount -o remount,ro 파일 시스템을 읽기 전용으로 설정 가능
AppArmor 특정 파일 및 경로에 대한 접근 차단 가능
SELinux 파일 권한 및 프로세스 권한 제어 가능

seccomp 단독으로 /proc, /sys, /dev 같은 특정 디렉터리를 차단하는 것은 어렵지만, openat 등 파일 접근 관련 시스템 콜을 차단하면 간접적으로 제한 가능
✅ 파일 경로를 기준으로 접근을 차단하려면 AppArmorSELinux를 활용하는 것이 더 효과적
mount 옵션을 활용하면 특정 파일 시스템을 ro로 마운트하여 보호 가능
✅ 최상의 보안성을 위해 seccomp + AppArmor/SELinux + mount 옵션을 함께 사용 추천

seccomp는 시스템 콜 수준에서 필터링하기 때문에 특정 파일을 완전히 차단하려면 추가적인 접근 제어 메커니즘을 함께 활용하는 것이 가장 좋은 방법입니다.

AppArmor vs. SELinux: Comprehensive Comparison

auditctl에서 /proc/meminfo와 같은 가상 파일 시스템(procfs) 파일에 대한 읽기 이벤트 감시는 지원되지 않습니다. auditctl-w(watch) 옵션은 일반적인 파일 시스템에서의 파일 접근을 감시하는데 사용되며, procfs처럼 동적으로 생성되는 가상 파일 시스템에서는 동작하지 않습니다.

syscall 기반 감시 (syscall open / openat / read 감시)

auditctl-S 옵션을 사용하여 syscall을 감시하는 방법을 고려할 수 있습니다.

설정 방법

auditctl -a always,exit -F arch=b64 -S open,openat -F path=/proc/meminfo -F success=1 -k meminfo_read
auditctl -a always,exit -F arch=b64 -S read -F path=/proc/meminfo -F success=1 -k meminfo_read

위 설정은

  • open 또는 openat 시스템 호출을 감시합니다.
  • /proc/meminfo 파일이 실제로 열릴 때 (success=1) 로깅합니다.
  • read 시스템 호출이 /proc/meminfo에 대한 데이터를 읽을 때 감시합니다.
  • -k meminfo_read 태그를 추가하여 필터링을 쉽게 합니다.

로그 확인

ausearch -k meminfo_read --raw | aureport -f -i

또는 ausearch를 직접 사용하여 특정 이벤트를 조회할 수 있습니다.

ausearch -k meminfo_read -i

auditctl 없이 ebpf 사용

auditctl로 해결하기 어려운 경우, eBPF 기반의 도구(예: bpftrace)를 사용하면 보다 정확한 감시가 가능합니다.

bpftrace 스크립트 예제

다음과 같이 bpftrace를 사용하여 /proc/meminfo 파일이 열리는 이벤트를 감시할 수 있습니다.

bpftrace -e 'tracepoint:syscalls:sys_enter_openat /str(args->filename) == "/proc/meminfo"/ { printf("Process %d (%s) accessed /proc/meminfo\n", pid, comm); }'

위 스크립트는 /proc/meminfo가 열릴 때마다 프로세스 ID와 명령어를 출력합니다.

auditctl 외에 fanotify 또는 inotify 활용

auditd가 아닌 다른 방법으로 감시하고 싶다면 inotify 또는 fanotify를 사용할 수 있습니다.

inotifywait 예제

inotifywait -m -e access /proc/meminfo

하지만 inotifyprocfs 파일 감시에는 잘 동작하지 않을 수 있습니다.

  • /proc/meminfoauditctl -w로 감시할 수 없음.
  • syscall 감시 (open, read)를 활용하면 auditd에서 가능.
  • 보다 세밀한 감시는 bpftrace 같은 eBPF 도구 활용.
  • inotify는 일부 프로세스에서 동작할 수도 있으나 procfs에서는 제한적.
728x90

댓글