jinb-park blog

Security, Network, OS, Linux, Kernel

[*] Linux Security 기능 총정리

댓글 0

Linux/Linux Kernel Security

2016. 9. 24.



작성자 : 박진범

메일 : jinb.park7@gmail.com



:) Linux Security

 "리눅스 커널이 제공하는 보안 기능" 을 말한다.


:) Goal

- 리눅스 커널이 제공하는 보안 기능들을 조사한다.


:) Discretionary Access Control (Unix DAC)

- uid, gid, permission 등을 이용한 접근제어 기능을 의미한다. 리눅스 역시 UNIX 의 이 모델을 그대로 사용한다.


:) POSIX ACLs (Extended DAC)

- Unix DAC 를 개선한 표준을 만들기 위한 여러 노력이 있었는데, 그 중 하나가 POSIX ACLs 이며, 리눅스에 적용되어 있다.
- Unix DAC 와 같은 컨셉이지만, 더 디테일한 설정이 가능하다.
 예를 들면, test.txt 파일에 대해, 소유자 이외의 사용자(other) 에게 아무런 권한이 없다고 하자.
 POSIX ACL 을 이용하면,, 다른 사용자 중 JB에게만 읽기 권한을 주는 것이 가능하다.


:) POSIX Capabilities

- http://egloos.zum.com/studyfoss/v/5338802
- 전통적인 super user (root) 기반의 시스템 관리 권한을 좀 더 세분화하는 것이다.
 즉, 특정 실행 파일에 대해 root 가 가질 수 있는 능력을 제한할 수 있는 것이다.
- 예를 들면, a.out 파일은 root 권한으로 실행되더라도 ==> "UID, GID 변경 불가", "kill 시그널 전송 불가" 등의 제한을 둘 수 있는 것이다.
 이 때, "UID, GID 변경 불가" ==> 이러한 각 항목을 "capability" 로 명칭한다.


:) Namespaces

- http://lwn.net/Articles/531114/
- 프로세스로써 볼수 있는 것들을 제한. partitioning 혹은 isolation 을 가능하게 해주는 기능.
- 보안을 위해 나온 기능은 아니지만, 보안을 위해 사용될 수 있다.
- 네임스페이스는 여러 개를 만들어 낼 수 있으며,, 프로세스 하나가 네임스페이스 하나에 포함되는 형태이다.
- 네임스페이스는 리눅스 컨테이너의 기반이 된다.

- 현재 리눅스에서 하나의 프로세스에 할당된 네임스페이스는 다음과 같은 여러 타입의 네임스페이스를 포함한다.
 . UTS : uname 명령어(system call) 를 통해 얻어지는 nodename, domainname 을 네임스페이스 별로 가질 수 있게 해준다.
 . IPC : SystemV IPC, Posix Message Queue 에 대해,, 같은 이름의 IPC object 를 서로 다른 네임스페이스에서 가질 수 있게 해준다.
 . VFS : 프로세스마다 root path 를 다르게 인식 가능한 것. chroot() 활용.
 . PID : 다른 namespace 의 프로세스는 서로 같은 PID 를 가질수 있다.
 . NETWORK : 서로 다른 네트워킹 리소스를 가질 수 있다. 즉, network device, IP 주소, IP 라우팅 테이블 등의 정보를 네임스페이스 별로 다르게 할당할 수 있다.
     컨테이너 구성 시 유용한데, 컨테이너 마다 각기 다른 network device, IP 주소, 라우팅 테이블을 가져서, 다른 컨테이너와 통신 시 네트워킹 활용할 수 있다.
 . USER : uid, gid 스페이스를 격리시킨다. 프로세스의 uid, gid 가 네임스페이스 안, 밖에서 달라질 수 있다.
          이렇게 되면, uid=user 인 프로세스가, 자신의 네임스페이스에선 uid=root 로 인식되고, 밖에선 uid=user 로 인식됨. sandboxing 구성이 가능해진다.


:) Network Security 

- Netfilter
: 패킷 필터링 기능 제공하는 프레임워크.

- Labeled Networking
: NetLabel, CIPSO, Labeled IPSec and SECMARK.
: network access control 을 label 기반으로 하는 것. (smack 의 label 처럼) 
 기존에 network access control 하려면, iptables 과 같은 별도의 솔루션 이용해야 했지만, label 기반으로 하면 LSM 에서 통합관리 가능.
 SELinux, Smack 에서 이 기능 지원. 
: 넷필터 룰에 따라 packet 에 라벨링 하거나, 소켓에 라벨링을 한다.

- NuFW
: https://lwn.net/Articles/146120/
: 리눅스 커널에 공식 포함된 기능은 아님.
: 넷필터를 활용한 방화벽 기능 제공. 인증 기능을 추가하여 좀 더 나은 방화벽 기능 제공한다. (기존에는 IP, Port 기반으로만 했기 때문에, user 에 대한 고려가 없었다)
: ip, port 뿐만 아닌, user 에 대한 accee control 이 가능하다. performance 를 떨어뜨리지 않기 위해서, TCP 의 경우, 초기 handshake 과정 (SYN 패킷) 만 인증한다.


:) FileSystem

- eCryptfs
: http://ecryptfs.org/
: http://www.fsl.cs.sunysb.edu/docs/cryptfs/cryptfs.html

: Enterprise Cryptographic Filesystem. POSIX 의 file system 레벨 암호화 레이어에 맞게 구현되었다.
: block device level 암호화와 file system level 암호화 (ecryptfs) 의 차이
==> block device level 암호화 :  FileSystem <-> Storage 로 read/write 과정에서 암복호화 된다. 즉, Storage 의 File Data 가 커널 메모리에 올라왔을 땐 복호화 된 상태인 것이다.
==> file system level 암호화 :  FileSystem 자체에서 file, directory 각각을 암호화 하는 것이다. 이 방법의 장점은, file 이나 directory 별로 다른 key 로 암호화가 가능하다는 것이다.

: stackable file system 이다. lower (encrypted directory), upper (unencrypted directory). 이렇게 2개 Layer 로 나뉜다. 
 lower 는 main file system 을 말한다. 예를 들어 lower directory 가 ext4 마운트된 디렉토리 아래라면, ext4 파일 시스템인 것. 
 upper 가 실제 ecryptfs 파일 시스템이며, ecryptfs 파일시스템 코드에서 lower 와 암복호화를 통해 연결된다.
 

:) Storage

- block device level 에 대한 보안 기능을 의미한다.

- dm-verity
: http://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/Documentation/device-mapper/verity.txt
: block device 의 integrity checking 을 담당한다. 검사하는 block device 는 read-only 여야만 한다.
: Hash Tree (== group hash) 형태로 hash 를 한다.
: VFS --> File System Driver --> Device Mapper --> dm-verity --> block devie --> physical disk
 Storage 까지 저장되는 순서가 위와 같을 때, 리눅스 커널에선 Device Mapper 라는 Layer 가 있는데, 이 device mapper target 으로 dm-verity 가 구현된다.
 (device mapper 에 대해선 잘 모름)

- dm-crypt
: block device 에 대한 encryption 기능을 제공한다.


:) Linux Security Module 

- AppArmor, TOMOYO, Smack, SELinux, Yama :  리눅스 커널에 공식적으로 포함되어 있는 LSM 이다. (아래 나온 것들 중 다른 것들은 공식 포함되어 있지는 않음)

- FBAC-LSM
: http://schreuders.org/FBAC-LSM/
: functionality-based application restrictions. 즉, application 이 할 수 있는 기능을 제한하는 것이다.
: 리눅스 커널에 공식 포함되어 있진 않다.

- Yama
: http://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/Documentation/security/Yama.txt?id=HEAD
: 리눅스 커널에 공식 포함되어 있는 LSM.
: adds restrictions to ptrace, providing a programmatic way to declare relationships between processes
: ptrace 사용에 대한 접근제어를 가능하게 해준다. 즉, 악의적인 프로세스가 ptrace 를 통해 다른 process 에 개입하지 못하도록 하는 것이 목적이다. 
: /proc/sys/kernel/yama/ptrace_scope ==> 이 값에 따라 ptrace attach 관련 정책이 변경된다.

- gresecurity
: https://grsecurity.net/features.php
: https://en.wikibooks.org/wiki/Grsecurity
: extensive security enhancement patch for the Linux kernel (RBAC, chroot hardening, auditing, stack/heap protection randomization and more...)
: 리눅스 커널에 공식 포함되어 있지 않다.
: 단순 LSM 이라고 보긴 어려움. 단순 access contol 이 아니라, Linux Kernel Security 전반을 향상시키기 위한 솔루션임.
: 엄청나게 많은 보안 feature 를 제공함. LSM 과도 함께 사용 가능.
: 커널 패치가 필요하다. gcc plugin 을 통한 기능도 제공.
: 제공하는 기능을 크게 나누면,, 
  Memory Corruption Defenses (ROP defense, ASLR, stack overflow 등), FileSystem Hardening, Miscellaneous Protections, RBAC (=MAC), GCC Plugins 

- RSBAC (Rule Set Based Access Control)
: https://en.wikipedia.org/wiki/RSBAC
: https://www.acsa-admin.org/secshelf/book001/09.pdf
: 리눅스 커널에 공식 포함되어 있지 않다.
: RSBAC == RBAC (Role Based Access Control). 2개는 같은 뜻으로 사용한다.
: LSM 을 활용하지 않고, 자체 후킹 코드를 이용하여 General Framework 를 구현하고 있다.
: 기능은 SELinux 와 흡사함.



:) Integrity

- 승인된 (변조되지 않은) 프로그램만 실행해주는 것. TPM chip 을 이용하여 인증되지 않은 프로그램 실행되지 않게 해주고, good code 만 실행시켜줌.
: http://events.linuxfoundation.org/sites/events/files/slides/Integrity_Protection_LinuxCon_Europe_2013_0.pdf

- EVM (Extended Verification Module) 
: 특정 파일 데이터와 metadata 에 대하여 hash, 이 hash 값을 TPM 으로 서명하는 작업을 담당.
: 즉, 실행 파일 변조를 보호하는 것이 EVM 의 역할이다.

- IMA (Integrity Measurement Architecture) 
: mmap() 사용 추적한다. 실행코드로서 매핑된 파일의 memory 영역을 hash 한다. 그리고 이 영역을 계속 tracking 한다. (이 영역을 TPM 으로 서명??)
: 즉, 현재 실행중인 실행파일의 실행코드를 인증하는 것이 IMA 의 역할이다.

==> EVM, IMA 를 함께 생각해보면,, offline file 변조는 EVM 이 막고,, running file 의 메모리 변조는 IMA 가 막는다.

- LIM (Linux Integrity Module)
: https://lwn.net/Articles/287790/
: 초기 EVM, IMA 는 LSM 을 사용하였다. 하지만 LSM Stacking 이 안되는 것과, side effect 의 존재로, LIM 의 하나로 들어간다.
 이를 통해 LSM 과 함께 동작 가능하다.
: LSM 이 access control 을 위한 주요 위치에 hook 을 설치한 것처럼, LIM 도 integrity 체크를 위한 주요 위치에 hook 을 설치.
 ==> 근데 코드 상에는 LIM 이라는 명시가 없음. hook 설치했다는 개념만 남아있고, IMA 에 그냥 합쳐진 듯.


:) Audit

: Audit 은 커널의 주요 이벤트나 주요 상황을 기록하기 위해서 사용된다. 즉, Audit 에서 여러 이벤트 타입을 제공 (uapi/linux/audit.h). 커널의 여러 코드에서 상황에 맞는 이벤트 타입으로 Audit API 호출하여, 이벤트 기록하는 것이다.
: LSM 과 다른 보안 기능들에서 Audit API 를 많이 사용한다. (audit_log() 가 주요 public api)
: auditd 라는 유저데몬이 있다. 이 데몬은 Audit record 들을 파일에 기록하는 역할을 한다. /etc/audit/auditd.conf 가 configure 파일이다.


:) Seccomp

: secure computing mode 의 약자. 프로세스가 호출할 수 있는 system call 을 제한하는 것이다. 
  seccomp() system call 을 통해 기능을 활성화시키면, 이를 호출한 프로세스에 있는 모든 fd 들에 대해서, read(), write(), exit(), sigreturn() 을 제외한 모든 system call 호출이 불가능해진다. (호출할 경우 SIGKILL 됨)
: seccomp 에 filtering 기능이 더해진 것이, seccomp-bfp 이다. 이는, 차단할 시스템 콜과, 시스템 콜 인자에 대한 필터링을 추가할 수 있는 기능이다. 이 역시 seccomp() 시스템 콜을 통해 필터링 룰 설정 가능하다.
 필터링 룰은 BPF (berkely packet filter) 의 포맷을 따른다.
: 리눅스 커널 문서에서는, 샌드박싱 기능을 위해 seccomp 를 활용할 수 있다고 되어있다.


:) Hardening

- hardening 이란, 공격자가 리눅스 커널을 해킹하기 더 어렵게 만드는 것을 의미한다. 이 기능은 다양한 레벨에서 적용 가능하다.

- ASLR (Address Space Layout Randomization)
: user level 실행파일의 로딩되는 메모리를 랜덤화하는 것이다. 최근에는 Linux Kernel 의 메모리 로딩도 랜덤화하는 기능이 포함되었다.


:) Platform Security( = Hardware Security)

- 리눅스 커널은 여러 Hardware Security Feature 들을 Support 한다.

- SMAP (supervisor mode access prevention)
: intel cpu 의 security feature 이다. 리눅스 커널에서 이를 지원하기 위해 2012년에 추가되었다.
: user --> kernel 접근 시 page fault 가 발생한다. 하지만 그 반대의 경우 kernel --> user. 이 시나리오에 대해선 접근 제어를 하지 않는다. 하지만 kernel 은 user 의 모든 부분을 접근 가능하기 때문에, 이는 위험할 수 있다.
 따라서, kernel privilege 에서 user memory 접근을 막는 것. 이것이 SMAP 의 역할이다.
: CR4 레지스터에 SMAP 을 위한 특정 비트를 추가. SMAP enable 이면, kernel 에서 user memory 접근 시 page fault 가 발생한다.
STAC, CLAC 이라는 명령어도 새로 추가되어, 이게 SMAP enable/disable 해준다. (copy_to_user 등의 접근은 allow 되어야 한다)
: SMAP 의 장점은 다음과 같다.
  ==> kernel 이 잘못된 user memory 를 읽거나 씀으로써 생기는 expolit 을 예방한다.
  ==> kernel 개발자의 실수 (user memory 접근에 관한) 를 쉽게 발견할 수 있다.

- TPM (Trusted Platform Module)
: 암호화 키 저장, 암호화 연산이 가능한 Hardware Chip 규격을 의미한다.
2006년 이후의 많은 PC, 노트북들은 TPM 이 포함되어 출시되었다.

- IOMMU (Input Output Memory Management Unit)
: IOMMU 란 CPU<->MMU<->Physical Memory 의 컨셉을 DMA 가능한 버스에 적용한 것이다. 즉, 주변 기기<->IOMMU<->Physical Memory 형태가 된다.
 즉, DMA 를 할 때, 물리 메모리에 직접 접근하지 않고, 디바이스는 가상 메모리로 접근 -> IOMMU 에서 물리주소로 재매핑 하는 것이다.
 이를 통해 IOMMU 에서 memory protection 이 가능하다.
: Intel ==> VT-d  /  ARM ==> SMMU 라는 이름으로 이 기능을 지원한다.

- NX (Never Execute)
: 코드와 데이터 영역을 구분하여, 데이터 영역이 실행되지 않도록 하는 기술이다. 페이지 테이블의 특정 비트를 이용해서, 실행영역 메모리만 실행 가능하도록 해준다.
: ARM 에서는 xn bit 로 사용된다.


:) Key (Key Retention Service)

- key, 인증 토큰, cross-domain user mapping(??) 등을 커널에 보관하고, 요청 시 이를 제공해주는 서비스이다.
- 크게 아래와 같은 3가지 type 의 key 존재.
  1. keyring :  key 들의 집합.
  2. user :  user 에서도 access 가능한 키.
  3. logon :  kernel 에서만 access 가능한 키. (생성은 user 에서. access 는 kernel 에서만)
              즉, user space 사용자가 자신의 데이터를 kernel 에 숨기고 싶을 때. 이럴 때 주로 사용한다.
  4. Trusted Keys :  TPM 에서 생성되고, TPM 에서 보관되는 키.
  5. Encrypted Keys :  커널에서 생성되는 AES 키.  master key 를 이용하여 보호된다. (master key == Trusted Key or user)
(user, logon 의 경우 모두, user-space 에서 key 를 kernel 에 전달하고, kernel 이 이를 보관하는 방식이다)

- /proc/keys, /proc/key-users 를 통해 현재 커널에서 관리 중인 key 를 확인할 수 있다.


:) Kernel Self Protection

- 잘못된 커널 코드로 인해서 발생하는 버그들은 계속해서 생기고 있다. kernel self protection 이란, 이러한 결함을 해결하는 것을 말한다.
- static checker (smatch, coverity, ..), dynamic checker (kernel configs, trinity, KASAN, ...), 


:) Appendix-1. Linux Containers

- Linux Kernel 이 제공하는 기능을 이용하여 OS-Level 가상화 방법. (namespace, cgroup 등의 커널 기능을 이용하여 container 기능 제공)
- LXC, LXD, (LXCFS) ==> canonical 에서 만든 컨테이너. LXC 는 2008년에 만들어진 컨테이너이며, LXD 는 2014년에 발표되어 현재 개발중인 발전된 컨테이너이다.
- Docker ==> 현재 가장 Hot 한 컨테이너(?) 를 활용한 기술. LXC 가 컨테이너라고 한다면, Docker 는 컨테이너 기반의 App 을 배포하는 것에 초점이 맞춰진 오픈소스 프로젝트.
    Docker 는 libcontainer (자체 컨테이너 기술), libvirt, LXC, systemd-nspawn 등을 이용하여 컨테이너 동작 수행 가능하다.


:) References

- https://www.linux.com/learn/overview-linux-kernel-security-features
- http://kernsec.org/wiki/index.php/Projects