17. Protection

이 장에서는 보호, 즉 프로세스의 접근에 대한 제어와 컴퓨터 시스템에 정의된 자원의 사용자에 대한 제어를 다룬다.

17.1. Goals of Protection

컴퓨터 시스템이 더 복잡해지고 널리 쓰임에 따라, 그들의 온전성을 보호할 필요도 늘어났다. 보호를 제공해야 할 필요는 여러 가지가 있다. 보호는 컴포넌트 부분 시스템간 인터페이스에 잠재하는 에러를 감지함으로써 가용성을 높일 수 있다. 컴퓨터 시스템에서 보호의 역할은 자원 사용을 관리하는 정책을 강제하는 메커니즘을 제공하는 것이다. 자원에 대한 정책은 애플리케이션마다 다르고 시간에 따라 변할 수 있으므로 보호는 운영 체제뿐만 아니라 애플리케이션 제작자에게도 사용되어야 한다. 메커니즘과 정책은 다르다. 메커니즘은 무엇이 어떻게 되어야 할지를 나타내고 정책은 무엇이 되어야 할지를 나타낸다.

17.2. Principles of Protection

오랜 시간 동안 유용함이 증명된 보호의 핵심 지도 원리는 최소 권한 원리이다. 최소 권한 원리의 실례들에서는 적절하게 정의된 허가가 있으면 공격을 완화시킬 수 있다. 다른 중요한 원리는 각 시스템 컴포넌트를 특정한 허가의 사용과 접근 제한을 통해 보호하는 칸막음이다. 접근 권한의 주의깊은 사용은 시스템을 보다 보호하고 허가된 접근의 분류를 추적하는 감사 추적을 제공하는 데 있어서도 이득이 된다. 아마도 가장 중요한 것은, 만능으로 동작하는 단일 원리는 없으니 여러 보호의 층을 혼합하는 심층 방어가 중요하다는 것이다.

17.3. Protection Rings

현대 운영 체제의 핵심 컴포넌트는 시스템 자원과 하드웨어에 대한 접근을 관리하는 커널이며, 이는 사용자 프로세스보다 높은 권한을 가져야 한다. 이러한 권한 분리를 위해서는 하드웨어 지원이 필요하다. 권리 분한의 유명한 모델은 보호 고리가 있으며, 여기서는 명령어들의 집합이 여러 고리를 이루며 이 고리들은 더 권한이 많은 쪽이 더 권한이 적은 쪽에 포함되는 동심원을 이룬다. 더 권한이 많은 쪽의 고리로 반환하기 위해서는 코드는 특별한 명령어를 포함하거나 프로세스 트랩, 인터럽트 등을 쓴다. 인텔 아키텍쳐는 사용자 모드 코드를 링 3, 커널 모드 코드를 링 0에 놓는다. 하이퍼바이저를 링 -1에 놓기도 한다. ARM 프로세서도 사용자 링과 커널 링에 추가로 트러스트존(TZ)을 배치한다. 이는 칩 위의 키를 담고 있으며 커널조차도 키를 직접적으로 호출하지는 못하고 안전 모니터 호출(SMC)를 통해 트러스트존에서 암호화/복호화 서비스만을 요청할 수 있다. 신뢰할 수 있는 실행 환경을 올바르게 갖춘다면 커널이 구성되었을 때 공격자가 커널 메모리로부터 키를 단순이 가져올 수가 없다. 64비트 ARMv8 아키텍쳐에서는 ARM이 이 모델을 확장해 4개의 레벨을 지원한다. 안전 모니터는 범용 커널보다 높은 실행 레벨에서 실행되므로 커널의 온전성을 체크하는 코드를 배치하기 좋다.

17.4. Domain of Protection

보호 고리는 함수들을 도메인별로 분리해 이들을 계층화한다. 컴퓨터 시스템은 프로세스와 오브젝트의 모임이라 할 수 있다. 오브젝트는 하드웨어 오브젝트(CPU, 메모리 세그먼트, 프린터, 디스크, 테이프 드라이브 등)와 소프트웨어 오브젝트(파일, 프로그램, 세마포어 등)을 모두 가리킨다. 가능한 동작은 오브젝트에 의존한다. 프로세스는 그것이 접근 권한을 가진 오브젝트에 대해서만 접근할 수 있어야 한다. 또한, 언제나 프로세스는 그것이 작업을 완료하는 데 현재 필요로 하는 오브젝트들에만 접근할 수 있어야 한다 (알 필요 있음의 원리). 알 필요 있음의 원리와 최소 권리의 원리를 비교할 때는 알 필요 있음의 원리는 정책이고 최소 권리 원리는 이 정책을 완수하기 위한 메커니즘으로 보면 된다.

17.4.1. Domain Structure

언급된 방법들을 가능케 하기 위해서는 프로세스가 프로세스가 접근해야 하는 자원들을 특정하는 보호 도메인 내에서 동작해야 한다. 오브젝트에 대한 동작을 실행할 수 있는 능력을 접근 권한이라 한다. 도메인은 접근 권한을 공유할 수도 있다. 프로세스와 도메인 간의 연관 관계는 정적(프로세스에 가능한 자원의 집합이 프로세스의 생애 주기 동안 고정됨), 일 수도 있고 동적일 수도 있다. 프로세스와 도메인 사이의 연관 관계가 고정되어 있는 상태에서 알 필요 있음의 원리를 고수하기 위해서는 도메인의 내용을 변경할 수 있는 메커니즘이 필요하다. 연관 관계가 동적이라면 프로세스가 하나의 도메인으로부터 다른 도메인으로부터 전환할 수 있게 하는 도메인 전환 메커니즘이 필요하다.

도메인은 여러 방식으로 인식될 수 있다. 각 사용자가 도메인일 수도 있고, 각 프로세스가 도메인일 수도 있고, 각 프로시져가 도메인일 수도 있다. 멀티프로그래밍 운영 체제에서는 2개의 보호 도메인으로는 불충분하다.

17.4.2. Exmaple: UNIX

UNIXㅔ서는 루트 사용자만 특권 명령어를 쓸 수 있고 다른 사용자는 쓸 수 있는데, 이는 다른 사용자의 일상적 동작을 해친다. UNIX는 이 문제를 setuid 비트를 둬서 해결한다. 이는 굉장히 제한되어 있고 밀폐되어 있어야 하지만, setuid 바이너리들 중 이 두 조건을 만족하는 것들은 많지 않다.

17.4.3. Example: Android Application IDs

Android에서는 애플리케이션 별로 서로 다른 사용자 ID가 제공된다.

17.5. Access Matrix

일반적인 보호 모델은 접근 행렬이라는 행렬로 추상적으로 볼 수 있다. 행은 도메인을, 열은 오브젝트를 나타낸다. 각 엔트리는 접근 권한의 집합이다. 이는 다양한 정책들을 특정하는 메커니즘을 제공해 준다. 접근 행렬은 보호를 고려하는 정책 결정을 구현할 수 있다. 접근 행렬의 엔트리는 대개 사용자에 의해 결정된다. 접근 행렬은 프로세스와 도메인간 정적/동적 연관 관계 모두에 대해 엄격한 제어를 정의하고 구현하는 적절한 메커니즘을 제공한다. 이 때 프로세스는 한 도메인으로부터 다른 도메인으로 전환할 수 있어야 한다. 접근 행렬의 엔트리 내용에 대한 변경은 copy, owner, control의 세 동작을 통해 이루어진다. 하지만 이는 정보의 전파를 막기 위한 적절한 도구를 제공하지는 못한다. 오브젝트가 처음에 담고 있던 정보가 그 실행 환경 밖으로 나가지 못하게 보장해야 하는 문제를 유폐 문제라 한다. 이 문제는 일반적으론 해결이 불가능하다. 접근 행렬과 도메인에 대한 이러한 동작들은 그 자체로는 중요하지 않지만 접근 행렬 모델을 통해 동적 보호 요구 사항을 구현하고 제어할 수 있는 능력을 나타내 준다.

17.6. Implementation of the Access Matrix

접근 행렬을 효율적으로 구현하려면 어떻게 할까?

17.6.1. Global Table

가장 간단한 구현은 순서 3원소의 집합으로 이루어진 전역 테이블을 통한 구현이다. 하지만 이 테이블은 매우 크므로 메인 메모리에 조재할 수 없어 추가의 입출력이 요구된다.

17.6.2. Access Lists for Objects

접근 행렬의 각 열은 오브젝트별 접근 리스트로 구현될 수 있다. 이러한 접근법을 확장해 리스트에 추가로 기본 접근 권한의 집합을 정의할 수 있다.

17.6.3. Capability Lists for Domains

접근 행렬의 열들을 접근 목록 오브젝트와 연관짓는 대신에, 접근 행렬의 행들을 그 도메인과 연관지을 수 있다. 도메인의 능력 목록은 오브젝트의 목록과 그 오브젝트에 허용된 동작들의 목록이다. 오브젝트는 종종 능력이라 불리는 그 물리적 이름이나 주소로 표현된다. 능력 목록은 도메인과 연관지어지지만 도메인 내에서 실행 중인 프로세스에 직접적으로 접근 가능하지는 않다. 능력은 본래는 일종의 안전한 포인터로 제안되었으며 멀티프로그래밍 컴퓨터 시스템이 발달하면서 자원 보호의 필요를 충족시키기 위할 것으로 예견되었다. 이런 내재적인 보호를 제공하기 위해서는 능력들과 다른 종류의 오브젝트들을 구분할 필요가 있으며 이는 고수준 프로그램이 동작하는 추상 기계를 통해 표현됭야 한다. 이러한 구분은 오브젝트에 달린 태그나 프로그램에 연관된 주소 공간의 분할로 이루어진다.

17.6.4. A Lock-Key Mechanism

잠금-키 방식은 접근 목록과 능력 목록 간의 절충이다. 각 오브젝트는 잠금이라 불리는 유일한 비트 패턴의 목록을 갖고 있다. 각 도메인은 라 불리는 유일한 비트 패턴을 갖고 있다. 도메인 내에서 실행 중인 프로세스는 그 도메인이 락들 중 하나에 매칭되는 키를 갖고 있는 오브젝트에만 접근할 수 있다.

17.6.5. Comparison

접근 행렬을 구현하는 방식을 택하는 것에는 여러 트레이드오프가 있다. 전역 테이블은 단순하지만 크고, 오브젝트나 도메인의 특별한 그룹핑으로부터 이득을 보지 못한다. 접근 목록은 사용자의 기대를 직접적으로 충족시키지만, 각 도메인의 접근 권한을 판별하는 것은 어렵다. 능력 목록은 사용자의 기대를 직접적으로 충족시켜 주지는 못하지만, 주어진 프로세스의 정보를 국소화하는 데 있어 유용하다. 잠금-키 메커니즘은 접근 목록과 능력 목록의 절충이다. 대다수의 시스템은 접근 목록과 능력 목록의 조합을 쓴다. 접근 권한은 각 접근마다 체크되어야 하고, 파일-테이블 엔트리는 허가된 동작에 대한 능력만 갖고 있어야 한다.

17.7. Revocation of Access Rights

동적 보호 시스템에서는 서로 다른 사용자들에게 공유되는 오브젝트에 대한 접근 권한을 회수해야 할 때가 있다. 이 때 여러 의문이 있을 수 있다: 즉각적으로 회수해야 하나 지연된 회수를 해야 하나? 선택적으로 회수해야 하나 일반적으로 회수해야 하나? 부분적으로 회수해야 하나 전부 회수해야 하나? 일시적으로 회수해야 하나 영구적으로 회수해야 하나? 접근 목록 방식에서는 회수는 쉽다. 능력 목록 방식에서는 더 어려운데, 다음의 방식을 쓴다: 환취식, 후방 포인터식, 간접식, 키 식. 키 식에서는 각 오브젝트에 마스터 키를 연관시켜 이를 이용한다. 이 방식은 선택적 회수를 허용하지는 않으며, 키를 정의하고 목록에 삽입하고 삭제하는 일들이 모든 사용자에게 허용되어서는 안 된다.

17.8. Role-Based Access Control

접근 제어는 파일시스템 내 파일들에 적용할 수도 있지만 컴퓨터 시스템의 다른 부분에도 적용할 수 있다. 이는 역할 기반 접근 제어(RBAC)를 통해 최소 권리의 원리를 추가해 이루어진다. 이는 권한과 프로그램에 역할을 부여함을 통해 이루어진다.

17.9. Mandatory Access Control (MAC)

운영 체제는 전통적으로 파일이나 다른 시스템 오브젝트에 대한 접근을 제안할 때 자유 재량 접근 제어(DAC)를 사용해 왔다. 하지만 이는 시간에 따라 불충분함이 입증되었다. 그래서 더 강한 형태의 보호인 의무적 접근 제어(MAC)가 필요해졌다. 이는 루트 사용자조차 수정할 수 없는 시스템 정책으로 강제된다. 현대적 운영 체제들은 의무적 접근 제어와 자유 재량 접근 제어를 함께 제공하지만, 구현은 다를 수 있다. 의무적 접근 제어의 핵심 개념은 라벨로, 이는 오브젝트에 할당된 문자열이다.

17.10. Capability-Based Systems

능력 기반 시스템은 1970년대 초에 소개되었다.

17.10.1. Linux Capabilities

Linux는 UNIX 모델의 한계점을 다루기 위해 능력 기반 시스템을 사용한다. 실제로는 permitted, effective, inheritable의 세 비트마스크를 사용해 루트의 권한을 독립된 영역으로 쪼갠다. 이는 전통적 UNIX 모델에 비해서는 큰 발전이지만 여전히 유연하지 못하다.

17.10.2. Darwin Entitlements

Apple의 시스템 보호는 선언적 허가인 자격의 형태로 이루어진다. 이는 코드 서명에 삽입되어 구현된다.

17.11. Other Protection Improvement Methods

보호를 개선하는 다른 방법들을 알아보자.

17.11.1. System Integrity Protection

Apple은 macOS 10.11에서 시스템 온전성 보호 (SIP)라는 새 보호 메커니즘을 도입하였다. Darwin 기반 운영 체제는 시스템 온전성 보호를 통해 시스템 파일과 자원에 대한 접근을 제한해 루트 사용자도 그들을 함부로 변경할 수 없게끔 한다. 루트는 시스템 내에서 가장 강력한 사용자이긴 하지만 훨씬 권한이 제한된다.

17.11.2. System-Call Filtering

시스템의 온전성을 절충하기 위한 시도는 시스템 호출을 통해 사용자 모드에서부터 이루어진다. 그러므로 어떤 형태의 시스템 호출 필터링을 구현하는 것이 필수적이다. 이를 위해서는 커널에 코드를 추가해 시스템 호출 게이트에 조사를 수행해 호출자가 호출할 수 있는 시스템 호출을 안전한 것들이나 그 기능에 필요한 것들만으로 제한한다. 시스템 호출 필터링의 또 다른 형태는 더 복잡하지만, 각 시스템 호출을 조사하는 것은 같다. 두 접근법에 있어서 공통된 난점은 이들을 가능한 한 유용하게 하면서 새 필터나 기존 필터에 대한 변경이 필요해질 때 커널을 재빌딩할 필요성을 피하는 것이다. 이를 충족시키기 위한 하나의 접근법은 필터 구현과 커널을 분리하는 방법이 있다.

17.11.3. Sandboxing

샌드박싱에는 프로세스를 그것이 할 수 있는 것을 제한하는 환경에서 실행하는 것이 있다. 샌드박싱이란 단어는 프로세스에 엄격한 제한을 강제하는 관례에 적용된다. 이네는 여러 접근법이 있으며, 복수의 메커니즘의 조합으로도 구현할 수 있다. Apple은 샌드박싱을 최초로 구현했으며 구현이 최초에 비해 크게 발전하였다.

17.11.4. Code Signing

근본적인 단계에서 시스템이 프로그램이나 스크립트를 어떻게 신뢰할 수 있는가? 현재로서는 프로그램이나 실행 파일이 제작자가 만든 뒤 변경되지 않았음을 보증하는 디지털 서명인 코드 서명을 통해 이것이 이루어진다.

17.12. Language-Based Protection

대개 보호는 컴퓨터 시스템에서는 운영 체제 커널을 통한 정도까지 제공된다. 운영 체제 커널은 보호되는 자원에 대한 접근에 대한 시도를 조사하고 검증하는 보안책의 역할을 한다. 운영 체제들이 더 복잡해지고 고수준의 사용자 인터페이스를 제공하려고 하게 됨에 따라, 보호의 목적은 훨씬 더 정제되었다. 시스템 보호 설계자들은 프로그래밍 언어와 추상적 자료형과 오브젝트로부터 파생된 아이디어에 크게 의지하게 되었다. 자원에 대한 정책 또한 애플리케이션에 따라 다양할 수 있고, 시간에 따라 변화할 수 있다.

17.12.1. Compiler-Based Enforcement

이 지점에서는 프로그래밍 언어가 관련이 된다. 보호를 강제하기 위해 프로그래밍 언어 구현에 의해 여러 방식들이 제공되지만, 이들은 기반한 기계와 운영 체제의 지원에 의존한다. 시스템이 강력한 보호 커널을 제공하지 않더라도, 프로그래밍 언어에 주어진 보호 명세를 구현하는 메커니즘은 여전히 가능하다. 컴파일러에 의해 제공되는 강제와 반대로 커널만을 기반으로 하는 강제에는 보안상의 이점, 유연성, 효율성 등에서 몇 가지 이점이 있다. 요약하면, 프로그래밍 언어 내에서의 보호에 대한 명세는 자원 사용과 할당에 대한 정책의 고수준 기술을 가능케 한다. 애플리케이션 프로그램에서 보호를 가능케 하는 하나의 방법은 연산의 대상으로 쓰일 수 있는 소프트웨어 능력을 통한 것이다. 이를 위해서는 사용자 프로세스들간 시스템 자원에 능력을 분배할 수 있는 안전한 동적 접근 제어 메커니즘이 필요하다. 이런 구성은 세 가지 기능에 대한 메커니즘을 제공한다: 소비자 프로세스에 능력들을 안전하고 효율적으로 분배하는 것, 특정 프로세스가 할당된 자원을 작동시키는 동작의 유형을 특정하는 것, 특정 프로세스가 자원에 대한 여러 동작들을 작동시킬 순서를 특정하는 것. 시스템 설계의 실용적 도구로서 프로그래밍 언어에 이런 보호 개념들을 주입시키는 것은 아직 초창기 단계에 있다.

17.12.2. Run-Time-Based Enforcement-Protection in Java

Java는 분산 환경에서 가동되도록 설계되었으므로 Java 가상 머신은 많은 내장 보호 메커니즘을 갖고 있다. Java 프로그램은 클래스로 구성되어 있으며 클래스는 데이터 필드와 그에 동작하는 함수(메소드)로 구성된다. Java는 네트워크에서 신뢰할 수 없는 클래스를 동적으로 불러와 상호 불신 클래스를 같은 JVM 내에서 실행할 수 있기 때문에 보호는 매우 중요한 고려 사항이다. 같은 JVM에서 가동되는 클래스는 신뢰도가 다를 수 있기 때문에 보호 결정 사항은 JVM 내에서 다뤄져야 한다. 그러나 어떤 클래스가 보호되는 자원에 접근하기 위한 요청에 대해 책임이 있는지를 판별하기는 어려운 일이다. 이를 위한 Java의 철학은 라이브러리 클래스가 네트워크 연결을 명시적으로 허가하도록 요구하는 것이다. 이에 대한 구현 상의 접근법은 스택 조사이다. JVM 내 모든 스레드는 메소드 실행에 대해 연관된 스택이 있는데 이를 조사하는 것이다. 물론 이것이 수행되려면 프로그램은 스택 조사를 조작하거나 스택 프레임에 대한 주석을 수정할 수 없어야 한다. 즉 메모리를 직접적으로 조작할 수 없어야 하며 이것이 C++ 등과 다른 점이다. Java의 로드 시간/수행 시간 체크는 Java 클래스의 타입 안정성을 체크한다. 이것은 같은 JVM 내에 로딩된 다른 클래스로부터 데이터와 메소드를 보호할 수 있도록 캡슐화하는 Java 보호의 기본이다.

17.13. Summary

  • 시스템 보호 특성은 알 필요 있음 원리에 의해 이끌어지며, 최소 권리의 원리를 강제하는 메커니즘을 구현한다.
  • 컴퓨터 시스템은 오용으로부터 반드시 보호되어야 하는 오브젝트를 담는다. 오브젝트들은 하드웨어 (메모리, CPU 타임, 입출력 기기) 일수도 있고 소프트웨어 (파일, 프로그램, 세마포어) 등일 수도 있다.
  • 접근 권한은 오브젝트에 대한 동작을 수행하기 위한 허가이다. 도메인은 접근 권한의 집합이다. 프로세스는 도메인 내에서 실행되어 도메인 내의 접근 권한 중 하나를 사용해 오브젝트를 접근하고 조작할 수 있다. 생애 주기 동안, 프로세스는 보호 도메인에 묶이거나 한 도메인에서 다른 도메인으로 전환될 수 있다.
  • 오브젝트를 보호하는 흔한 방법은 권한의 순서대로 나열된 일련의 보호 고리를 제공하는 것이다. ARM은 4개의 보호 레벨을 제공한다. 가장 권한이 높은 TrustZone은 커널 모드에서만 호출 가능하다.
  • 접근 행렬은 보호 메커니즘을 제공하는 일반적인 보호 모델로서 특정한 보호 정책을 시스템이나 그 사용자에게 강제하지 않는다. 정책과 메커니즘의 분리는 중요한 설계 특성이다.
  • 접근 행렬은 희박한 행렬이다. 이는 각 오브젝트에 연관된 접근 목록이나 각 도메인에 연관된 능력 목록으로 구현된다. 도메인과 접근 행렬 자체를 오브젝트로 생각함으로써 접근 행렬 모델에 동적 보호를 포함시킬 수 있다. 동적 보호 모델에서 접근 권한을 회수하는 것을 구현할 때는 접근 목록 방식이 능력 목록 방식보다 쉽다.
  • 실제 시스템은 일반 모델보다 훨씬 제한되어 있다. 오래된 UNIX 배포판은 그 대표로서, 읽기, 쓰기, 실행 보호에 대한 자유 재량 접근 제어를 각 파일에 대해 사용자, 그룹, 일반에 대해 독립적으로 제공한다. 현대 시스템은 일반적 모델에 보다 가깝거나, 최소한 시스템과 그 사용자를 보호하기 위해 다양한 보호 특성을 둔다.
  • Solaris 10 이상과 다른 시스템은 최소 권한 원리를 역할 기반 접근 제어를 통해 구현하며 이는 접근 행렬의 형태를 가진다. 다른 보호 확장은 의무적 접근 제어로 시스템 정책 강제의 형태를 띈다.
  • 능력 기반 시스템은 구형 모델에 비해 세밀하게 구분된 보호를 제공한다는데, 루트의 권한을 구분된 영역으로 쪼개 프로세스에 특정한 권한을 제공한다. 보호를 개선하는 다른 방법들은 시스템 온전성 보호, 시스템 호출 필터링, 샌드박싱, 코드 서명 등이 있다.
  • 언어 기반 보호는 요청이나 권한을 운영 체제가 제공할 수 있는 방법에 비해 세밀하게 구분해 중재한다. 예를 들어, 단일 Java JVM은 복수의 스레드를 각각 서로 다른 보호 클래스 내에서 구동할 수 있다. 이는 언어의 타입 안정성과 복잡한 스택 조사를 통해 자원 요청을 강제한다.

답글 남기기

아래 항목을 채우거나 오른쪽 아이콘 중 하나를 클릭하여 로그 인 하세요:

WordPress.com 로고

WordPress.com의 계정을 사용하여 댓글을 남깁니다. 로그아웃 /  변경 )

Google photo

Google의 계정을 사용하여 댓글을 남깁니다. 로그아웃 /  변경 )

Twitter 사진

Twitter의 계정을 사용하여 댓글을 남깁니다. 로그아웃 /  변경 )

Facebook 사진

Facebook의 계정을 사용하여 댓글을 남깁니다. 로그아웃 /  변경 )

%s에 연결하는 중