출처 : http://croky.tistory.com/15
LIDS Internals
글쓴이 : 채효철
*INDEX*
1. 소개
2. 중요한 소스 분석
3. 예제
4. 결론
-----------------------------
1. 소개
LIDS 는 Linux Intrusion Detection System 의 약자로서 리눅스 기반의 IDS 이다.
중국의 해커 Huagang Xie 로 부터 시작되어
최고의 보안 도구로 각광 받고 있다. 아직 국내에는 까다라온 사용법 때문에 실제로
적용된 사례가 잘 없지만 외국에는 널리 쓰이고 있다고 한다.
하지만 이름과는 다르게 IDS 의 뜻과는 달리 리눅스의 보안 강화로 요즘 유행하는
Secure OS 을 지향하고 있다.
-현재 시스템의 문제는 무엇일까?
* 현재 파일 시스템은 보호되지 못한다
* 프로세스도 보호되지 못한다
* Access Control 모델이 부족하다
* root 권한이 너무 막강하다.
-모듈 방식 보다 좋은점은 무엇일까?
모듈 방식은 한계가 있는것으로 알려져 있다. 유지보수가 쉬운 이유로
모듈로 작성되고 있지만 모듈 만으로 커널의 모든 자료구조를 접근할수가
없다. 물론 커널을 컴파일 할 당시에 커널에서 쓰이는 자료구조나 변수들을
export 시킨다면 가능은 하겠지만 일반적으로 필요한 것만 export 시키기 때문에
그것은 논외로 하겠다.
- 중요한 기능들
LIDS 에 어떤 중요한 기능이 있는지 살펴보기 위해 커널에 패치된 파일과 새로
생성된 파일들을 살펴보겠다. 우리의 목적은 LIDS 의 내부를 살펴보는 것이기 때문에
사용하는 방법엔 관심이 별로 없다.(물론, 분석을 할려면 어느정도는 알아야 된다)
-패치된 파일
init/main.c /* 시작 루틴이 있음 */
kernel/fork.c /* 프로세스 생성하는 부분 */
kernel/ksym.c
kernel/signal.c /* 프로세스 보호 */
kernel/exit.c
fs/buffer.c
fs/dcache.c
fs/exec.c
fs/namei.c
fs/namespace.c
fs/readdir.c
fs/super.c
fs/open.c
fs/proc/base.c /* 프로세스 감추기 */
fs/proc/root.c
-추가된 파일
kernel/lids.c /* lids 의 핵심적 소스, 파일을 ACL 에 연결시키는등 */
kernel/klids.c /* lids thread 이다. 초기화시 kernel_thread() 를 통해서
실행됨 */
kernel/lids_mail_script.c /* 경고를 메일로 보낸다 */
kernel/lids_syslog_script.c
kernel/lids_net.c /* 네트워크 관련 보호루틴 */
kernel/lids_logs.c /* 로그 남기는 루틴 */
소스 파일명을 보면 알수있듯이
파일 시스템 보안과 프로세스 보안으로 나눌수 있다.
proc/ 파일 아래의 소스들은 프로세스를 보호하고
fs/ 디렉토리의 소스들은 파일 시스템이 ACL 에 의해 보호되는지
체크하고 실패하면 경고를 낸다. kernel/ 디렉토리에서 새로 생성된 파일들은 관리자에게
메일로 경고를 하거나 로그를 남긴다.
종합해 보자면 LIDS 의 특징은 다음과 같다.
보호(Protection). LIDS는 여러분의 하드 디스크에 있는 중요한 파일을 보호할 수 있다.
이때 파일시스템의 타입은 문제가 되지 않는다. 루트를 포함한 누구든지 지정된 파일을
변경할 수 없게 된다. LIDS는 또한 중요한 프로세스에 대해 kill 되어지는 것을 방지할 수
있다. LIDS는 인증되지 않은 프로그램으로부터의 RAW IO operation을 보호할 수 있다.
여러분의 하드디스크를 포함하여 MBR까지 보호할 수 있다.
탐지(Detection). 누군가 여러분의 호스트를 스캔했을 때 LIDS가 그것을 탐지하여 관리자
에게 알려줄 수 있다. LIDS는 또한 규정을 어긴 시스템상의 행동을 알아 챌 수도 있다.
응답(Response). LIDS에 의해 보호되고 있는 시스템 상에서 누군가 시스템상의 규정을
어겼을 때(주로 해킹을 위해) LIDS는 그 규정을 어긴 행동에 대해 자세한 메세지를 시스템
로그 파일로 기록한다. LIDS는 또한 여러분의 메일박스로 로그 메세지를 보낼 수도 있다.
이런 경우 LIDS는 즉시 유저 세션을 셧다운 시킬 수 있다.
2. 중요한 소스 분석
이번 절에서는 LIDS 소스에서 핵심적인 부분 몇가지를 분석하겠습니다.
- (1) 예) sys_ioperm
이 시스템콜은 I/O Port 를 접근하기 위해 커널에 허가를 요청 합니다.
커널 내부에서 이 요청이 허가된 사용자 - 루트인지 - 를 체크하기 위해
62 if (turn_on && !capable(CAP_SYS_RAWIO)) {
63 #ifdef CONFIG_LIDS
64 lids_security_alert("CAP_SYS_RAWIO violation: attempted to g
65 #endif
66 return -EPERM;
67 }
capable 함수는 인라인 함수로써 내부에 아래의 소스로 치환된다.
if(cap_raised(current->cap_effective,cap))
{
current->flags != PF_SUPERPRIV;
return 1;
}
이 함수는 current 즉 현재 프로세스의 cap_effective 라는 디스크립터를 검사해서
CAP_SYS_RAWIO - 로우레벨 I/O 작업의 권환이 있는지 - 를 검사해서
있다면 현재 프로세스의 PF_SUPERPRIV 플래그를 할당한다.
다시 돌아가서, 만약 허가되지 않은 사용자가 io_perm 을 호출했다면 lids_security_alert 가 실행된다.
이 함수는 lids_log 라는 함수를 호출해서 아래와 같은 동작을 한다.
1. 현재 프로세스의 매핑된 영역중 executable 한 영역을 찾아
매핑된 파일의 directory entry 를 얻는다.
2. 현재 프로세스의 tty 이름을 얻는다.
3. directory entry 와 tty 이름과 pid uid 등의 정보를 모아 프린트를 한다.
이 함수는 관리자에게 경고를 보내는 것이다.
LIDS 의 설계 목표중 하나가 Linux kernel 의 capability 지원을 강화하기 위한 것이다.
capability 에는 아래와 같은 속성이 있다.
CAP_CHOWN : 파일과 그룹의 허가권의 변경제한을 무시한다.
CAP_DAC_OVERRIDE : 파일 접속 퍼미션을 무시한다.
CAP_DAC_READ_SEARCH : 파일과 디렉토리의 읽기와 검색 허가를 무시한다.
CAP_FOWNER : 파일 허가권을 무시한다.
CAP_FSETID : setuid 와 setgid 플래그의 제한을 무시한다.
CAP_KILL : 시그널 보낼때의 제한을 무시한다.
CAP_SETGID : setgid 플래그 조작을 허용한다.
CAP_SETUID : setuid 플래그 조작을 허용한다.
CAP_SETPCAP : 다른 프로세스 에게 허가된 능력(capabilities) 의 부여한다.
CAP_LINUX_IMMUTABLE : 추가 전용파일이나 일정한 파일의 변경을 허용한다.
CAP_NET_BIND_SERVICE : TCP/IP socket 을 1024 번 이하로의 바인딩을 허용한다.
CAP_NET_BROADCAST : 네트워크 브로드캐스팅과 멀티캐스트를 듣는것을 허용한다.
CAP_NET_ADMIN : 일반적인 네트워킹 관리를 허용한다.
CAP_NET_RAW : RAW/PACKET socket 의 사용을 허용한다.
CAP_IPC_LOCK : 페이지나 메모리 세그먼트의 잠금을 허용한다.
CAP_IPC_OWNER : IPC 의 소유권 검사를 생략한다.
CAP_SYS_MODULE : 커널 모듈을 삽입/삭제 를 허용한다.
CAP_SYS_RAWIO : ioperm 과 iopl 을 이용해 I/O 포트에 접근을 허용한다.
CAP_SYS_CHROOT : chroot() 를 허용한다.
CAP_SYS_PTRACE : 어떤 프로세스에서나 ptrace() 를 허용한다.
CAP_SYS_PACCT : 프로세스 계정의 설정의 허용한다.
CAP_SYS_ADMIN : 일반적인 시스템 관리를 허용한다.
CAP_SYS_BOOT : reboot() 를 허용한다.
CAP_SYS_NICE : nice() 의 제한을 무시한다.
CAP_SYS_RESOURCE : 여러 자원 사용의 제한을 무시한다.
CAP_SYS_TIME : 시스템 시간과 실시간 시간의 조작을 허용한다.
CAP_SYS_TTY_CONFIG : tty 장치의 설정을 허용한다.
CAP_HIDDEN : 이 기능은 LIDS 에서 추가되는 것으로 프로세스를 숨기는 것이다.
CAP_KILL_PROTECTED : 이 함수 역시 LIDS 에서 추가되는 것으로 프로세스를 보호한다.
CAP_PROTECTED : 위와 유사
예를들어 nice 시스템 콜이 해당 프로세스가 요청을 할 권한이 있는지 검사하기 위해
capable(CAP_SYS_NICE) 로 검사하면 된다.
- (2) 프로세스 감추기
이 기능은 LIDS 패치에 의해 추가된 기능이다.
유닉스의 전형적인 명령어인 ps 를 실행하면 아래와 같이 프로세스가 출력된다.
root 1 0.0 0.1 1368 420 ? S Sep05 0:06 init
root 2 0.0 0.0 0 0 ? SW Sep05 0:00 [keventd]
root 3 0.0 0.0 0 0 ? SW Sep05 0:00 [kapmd]
root 4 0.0 0.0 0 0 ? SWN Sep05 0:00 [ksoftirqd_CPU0]
root 5 0.0 0.0 0 0 ? SW Sep05 0:00 [kswapd]
root 6 0.0 0.0 0 0 ? SW Sep05 0:00 [bdflush]
root 7 0.0 0.0 0 0 ? SW Sep05 0:00 [kupdated]
root 8 0.0 0.0 0 0 ? SW Sep05 0:00 [mdrecoveryd]
root 12 0.0 0.0 0 0 ? SW Sep05 0:00 [kjournald]
chc 1624 0.0 3.4 22844 8904 ? S Sep05 0:00 kdeinit: kwrited
chc 1632 0.0 3.5 21808 9044 ? S Sep05 0:00 korgac --miniicon
chc 1643 0.0 3.2 21776 8368 ? S Sep05 0:00 kalarmd --login
chc 1681 1.5 11.0 66376 28320 ? S Sep05 2:05 /usr/lib/mozilla/
잠깐 왜 우리가 프로세스를 잠궈야 할까? 그것은 해커가 루트를 획득한후 프로세스들을 제거하여
웹 서비스 같은것을 중단시킬수 있기 때문인데 예를들어 kill -9 4 를 하면
kswapd 가 죽지 않고 Zombie 상태가 될것이다. 그렇게 되면 우리가 예상한것 보다
큰 문제가 발생할 것이다.
ps 를 하게되면 내부적으로 아래와 같을 것이다.
1. execve("/bin/ps");
2. proc 라이브러리 열기
3. /proc 안에 있는 디렉토리들을 차례대로 열어서 프로세스들의 정보를 얻어낸다.
4. 만약 open("/proc/1624") 를 한다면, proc 가상 파일시스템을 거쳐서 proc_pid_lookup
함수까지 가게된다.
이 함수는 ls /proc 명령을 치게 되면 pid 가 디렉토리 목록으로 나올것이다.
아래 소스는 proc_pid_lookup 함수중 프로세스를 하이드 하는 부분이다.
1021 #ifdef CONFIG_LIDS
1022 if (cap_raised(task->lids_cap,CAP_HIDDEN) && lids_load && lids_local_load)
1023 inode=NULL;
1024 else
1025 #endif
자세한 설명을 하자면, task 프로세스의 lids_cap 에서 현재 capability 가 hidden 라면
얻어낸 inode 를 NULL 로 저장하여 보이지 않게 한다.
그런데 LIDS 가 패치된 커널 소스 안에는 프로세스를 숨기는 코드가 보이질 않는데
이것은 lids-adm 이라는 유저레벨 관리툴이 있어서 그 관리 프로그램으로
커널과 통신하여 관리할수 있다.
- (3) 파일 보호
보통 리눅스에서 파일에 접근 하려면 -rwxrwxrwx 이러한 권한만 가지고 접근여부를
결정한다. 하지만 이런것에 헛점이 있을수 있다. 그래서 LIDS 자체에서
강력한 파일시스템 보안을 제공한다.
커널 소스에서 파일에 접근하기 전에 반드시 lids_check_base 라는 함수를 호출한다.
이 함수는 dentry 와 플래그를 입력 받는다.
이 함수의 동작의 예를 들어보면
어떤 시스템콜을 통해서 /etc/apache 디렉토리에 접근하려고 한다.
그리고 현재 /etc 에는 ACL(Access Control List)에 기반하여 보호가 된다고 가정하자.
잠깐 우선 어떻게 관리할 파일(아이노드)이 기술되는지 살펴보겠다.
LIDS 에서 사용되는 자료구조는
struct lids_acl {
struct lids_acl *next;
unsigned long int ino;
kdev_t dev;
int type;
};
위와 같으며
next 는 다음 acl 을 가리키고
ino 는 관리될 파일(아이노드)를 가리키며
dev 는 디바이스 타입을 가리킨다.
type 는 읽기전용,쓰기전용,추가전용,접근불가 이렇게 나뉘며
특히 추가전용 같은 경우 로그파일 같은곳에 유용하다.
다시 돌아가서..
lids_check_base 의 동작 방법을 알아본다면,
while(dentry)
{
만약 현재 프로세스가 도메인을 체크한다면
lids_check_acl(base,flag);
dentry = dentry->d_parent;
}
이 소스는 parent dentry 로 가면서 dentry 가 LIDS 시스템에 의해 보호되고 있는지
체크를 하는 부분이다.
lids_check_acl 함수의 동작부분을 요약해보면 아래와 같다.
acl = current->lids_sys_acl->lids_domain;
while(acl != NULL)
{
if(acl->ino == inode->i_ino)
return 보호되고 있다;
}
그 다음부분은 lids_data 라는 자료구조에 들어가 있는 아이노드와 비교하여
리턴한다.
- (4) 그 외
지금까지 LIDS 에서 가장 많은 비중을 차지한 함수들을 분석하였다.
그 외에는 LIDS 관리 프로그램인 lids-adm 과 통신을 하기 위한 코드들이다.
3. 예제
이해를 돕기 위해 예제를 들어 보겠다.
유저모드에서 아래와 같은 문장을 실행하게 되면 lids.conf 에 2번과 같은 문장이
추가 될 것이다.
1) lidsadm -A -r /sbin/
2) 0:0::1:0:80483:770:/sbin:0-0
각 필드들은 타입,아이노드,디바이스번호,파일명 등이다.
그리고 리부팅을 해서 커널의 처음 시작 루틴에서 lids_load 를 1로 설정한다.
초기에 lids_init() 를 호출하면 아래와 같은 루틴이 작동한다.
filp = filp_open(LIDS_CONF_FILE,O_RDONLY,O_RDONLY);
즉 /etc/lids.conf 을 연다.
filp->f_op->read(filp,buffer,1024,&filp->f_pos);
설정 파일에서 1024 바이트만 읽는다. 물론 이 연산은 유저모드에서 커널모드로
복사해 오는것이기 때문에 더 복잡하다.
한줄씩 읽으면서 #으로 시작하면 넘어가고 아니면 lids_init_add_file 을 호출해서
한줄에 읽은 문자열을 넘겨줘서 분석을 하고 각 필드들을 메모리에 넣고
나머지 아이노드,타입,파일명 필드는 lids_get_info 함수에서 처리한다.
그런후에 얻어진 inode 번호등을 이용해 lids_add_acl 함수로 acl list 에 추가하게
되는 것이다. 그리고 앞에서 보았듯이 디렉토리에 접근 할때는 acl list 를
검사한다.
LIDS Internals
글쓴이 : 채효철
*INDEX*
1. 소개
2. 중요한 소스 분석
3. 예제
4. 결론
-----------------------------
1. 소개
LIDS 는 Linux Intrusion Detection System 의 약자로서 리눅스 기반의 IDS 이다.
중국의 해커 Huagang Xie 로 부터 시작되어
최고의 보안 도구로 각광 받고 있다. 아직 국내에는 까다라온 사용법 때문에 실제로
적용된 사례가 잘 없지만 외국에는 널리 쓰이고 있다고 한다.
하지만 이름과는 다르게 IDS 의 뜻과는 달리 리눅스의 보안 강화로 요즘 유행하는
Secure OS 을 지향하고 있다.
-현재 시스템의 문제는 무엇일까?
* 현재 파일 시스템은 보호되지 못한다
* 프로세스도 보호되지 못한다
* Access Control 모델이 부족하다
* root 권한이 너무 막강하다.
-모듈 방식 보다 좋은점은 무엇일까?
모듈 방식은 한계가 있는것으로 알려져 있다. 유지보수가 쉬운 이유로
모듈로 작성되고 있지만 모듈 만으로 커널의 모든 자료구조를 접근할수가
없다. 물론 커널을 컴파일 할 당시에 커널에서 쓰이는 자료구조나 변수들을
export 시킨다면 가능은 하겠지만 일반적으로 필요한 것만 export 시키기 때문에
그것은 논외로 하겠다.
- 중요한 기능들
LIDS 에 어떤 중요한 기능이 있는지 살펴보기 위해 커널에 패치된 파일과 새로
생성된 파일들을 살펴보겠다. 우리의 목적은 LIDS 의 내부를 살펴보는 것이기 때문에
사용하는 방법엔 관심이 별로 없다.(물론, 분석을 할려면 어느정도는 알아야 된다)
-패치된 파일
init/main.c /* 시작 루틴이 있음 */
kernel/fork.c /* 프로세스 생성하는 부분 */
kernel/ksym.c
kernel/signal.c /* 프로세스 보호 */
kernel/exit.c
fs/buffer.c
fs/dcache.c
fs/exec.c
fs/namei.c
fs/namespace.c
fs/readdir.c
fs/super.c
fs/open.c
fs/proc/base.c /* 프로세스 감추기 */
fs/proc/root.c
-추가된 파일
kernel/lids.c /* lids 의 핵심적 소스, 파일을 ACL 에 연결시키는등 */
kernel/klids.c /* lids thread 이다. 초기화시 kernel_thread() 를 통해서
실행됨 */
kernel/lids_mail_script.c /* 경고를 메일로 보낸다 */
kernel/lids_syslog_script.c
kernel/lids_net.c /* 네트워크 관련 보호루틴 */
kernel/lids_logs.c /* 로그 남기는 루틴 */
소스 파일명을 보면 알수있듯이
파일 시스템 보안과 프로세스 보안으로 나눌수 있다.
proc/ 파일 아래의 소스들은 프로세스를 보호하고
fs/ 디렉토리의 소스들은 파일 시스템이 ACL 에 의해 보호되는지
체크하고 실패하면 경고를 낸다. kernel/ 디렉토리에서 새로 생성된 파일들은 관리자에게
메일로 경고를 하거나 로그를 남긴다.
종합해 보자면 LIDS 의 특징은 다음과 같다.
보호(Protection). LIDS는 여러분의 하드 디스크에 있는 중요한 파일을 보호할 수 있다.
이때 파일시스템의 타입은 문제가 되지 않는다. 루트를 포함한 누구든지 지정된 파일을
변경할 수 없게 된다. LIDS는 또한 중요한 프로세스에 대해 kill 되어지는 것을 방지할 수
있다. LIDS는 인증되지 않은 프로그램으로부터의 RAW IO operation을 보호할 수 있다.
여러분의 하드디스크를 포함하여 MBR까지 보호할 수 있다.
탐지(Detection). 누군가 여러분의 호스트를 스캔했을 때 LIDS가 그것을 탐지하여 관리자
에게 알려줄 수 있다. LIDS는 또한 규정을 어긴 시스템상의 행동을 알아 챌 수도 있다.
응답(Response). LIDS에 의해 보호되고 있는 시스템 상에서 누군가 시스템상의 규정을
어겼을 때(주로 해킹을 위해) LIDS는 그 규정을 어긴 행동에 대해 자세한 메세지를 시스템
로그 파일로 기록한다. LIDS는 또한 여러분의 메일박스로 로그 메세지를 보낼 수도 있다.
이런 경우 LIDS는 즉시 유저 세션을 셧다운 시킬 수 있다.
2. 중요한 소스 분석
이번 절에서는 LIDS 소스에서 핵심적인 부분 몇가지를 분석하겠습니다.
- (1) 예) sys_ioperm
이 시스템콜은 I/O Port 를 접근하기 위해 커널에 허가를 요청 합니다.
커널 내부에서 이 요청이 허가된 사용자 - 루트인지 - 를 체크하기 위해
62 if (turn_on && !capable(CAP_SYS_RAWIO)) {
63 #ifdef CONFIG_LIDS
64 lids_security_alert("CAP_SYS_RAWIO violation: attempted to g
65 #endif
66 return -EPERM;
67 }
capable 함수는 인라인 함수로써 내부에 아래의 소스로 치환된다.
if(cap_raised(current->cap_effective,cap))
{
current->flags != PF_SUPERPRIV;
return 1;
}
이 함수는 current 즉 현재 프로세스의 cap_effective 라는 디스크립터를 검사해서
CAP_SYS_RAWIO - 로우레벨 I/O 작업의 권환이 있는지 - 를 검사해서
있다면 현재 프로세스의 PF_SUPERPRIV 플래그를 할당한다.
다시 돌아가서, 만약 허가되지 않은 사용자가 io_perm 을 호출했다면 lids_security_alert 가 실행된다.
이 함수는 lids_log 라는 함수를 호출해서 아래와 같은 동작을 한다.
1. 현재 프로세스의 매핑된 영역중 executable 한 영역을 찾아
매핑된 파일의 directory entry 를 얻는다.
2. 현재 프로세스의 tty 이름을 얻는다.
3. directory entry 와 tty 이름과 pid uid 등의 정보를 모아 프린트를 한다.
이 함수는 관리자에게 경고를 보내는 것이다.
LIDS 의 설계 목표중 하나가 Linux kernel 의 capability 지원을 강화하기 위한 것이다.
capability 에는 아래와 같은 속성이 있다.
CAP_CHOWN : 파일과 그룹의 허가권의 변경제한을 무시한다.
CAP_DAC_OVERRIDE : 파일 접속 퍼미션을 무시한다.
CAP_DAC_READ_SEARCH : 파일과 디렉토리의 읽기와 검색 허가를 무시한다.
CAP_FOWNER : 파일 허가권을 무시한다.
CAP_FSETID : setuid 와 setgid 플래그의 제한을 무시한다.
CAP_KILL : 시그널 보낼때의 제한을 무시한다.
CAP_SETGID : setgid 플래그 조작을 허용한다.
CAP_SETUID : setuid 플래그 조작을 허용한다.
CAP_SETPCAP : 다른 프로세스 에게 허가된 능력(capabilities) 의 부여한다.
CAP_LINUX_IMMUTABLE : 추가 전용파일이나 일정한 파일의 변경을 허용한다.
CAP_NET_BIND_SERVICE : TCP/IP socket 을 1024 번 이하로의 바인딩을 허용한다.
CAP_NET_BROADCAST : 네트워크 브로드캐스팅과 멀티캐스트를 듣는것을 허용한다.
CAP_NET_ADMIN : 일반적인 네트워킹 관리를 허용한다.
CAP_NET_RAW : RAW/PACKET socket 의 사용을 허용한다.
CAP_IPC_LOCK : 페이지나 메모리 세그먼트의 잠금을 허용한다.
CAP_IPC_OWNER : IPC 의 소유권 검사를 생략한다.
CAP_SYS_MODULE : 커널 모듈을 삽입/삭제 를 허용한다.
CAP_SYS_RAWIO : ioperm 과 iopl 을 이용해 I/O 포트에 접근을 허용한다.
CAP_SYS_CHROOT : chroot() 를 허용한다.
CAP_SYS_PTRACE : 어떤 프로세스에서나 ptrace() 를 허용한다.
CAP_SYS_PACCT : 프로세스 계정의 설정의 허용한다.
CAP_SYS_ADMIN : 일반적인 시스템 관리를 허용한다.
CAP_SYS_BOOT : reboot() 를 허용한다.
CAP_SYS_NICE : nice() 의 제한을 무시한다.
CAP_SYS_RESOURCE : 여러 자원 사용의 제한을 무시한다.
CAP_SYS_TIME : 시스템 시간과 실시간 시간의 조작을 허용한다.
CAP_SYS_TTY_CONFIG : tty 장치의 설정을 허용한다.
CAP_HIDDEN : 이 기능은 LIDS 에서 추가되는 것으로 프로세스를 숨기는 것이다.
CAP_KILL_PROTECTED : 이 함수 역시 LIDS 에서 추가되는 것으로 프로세스를 보호한다.
CAP_PROTECTED : 위와 유사
예를들어 nice 시스템 콜이 해당 프로세스가 요청을 할 권한이 있는지 검사하기 위해
capable(CAP_SYS_NICE) 로 검사하면 된다.
- (2) 프로세스 감추기
이 기능은 LIDS 패치에 의해 추가된 기능이다.
유닉스의 전형적인 명령어인 ps 를 실행하면 아래와 같이 프로세스가 출력된다.
root 1 0.0 0.1 1368 420 ? S Sep05 0:06 init
root 2 0.0 0.0 0 0 ? SW Sep05 0:00 [keventd]
root 3 0.0 0.0 0 0 ? SW Sep05 0:00 [kapmd]
root 4 0.0 0.0 0 0 ? SWN Sep05 0:00 [ksoftirqd_CPU0]
root 5 0.0 0.0 0 0 ? SW Sep05 0:00 [kswapd]
root 6 0.0 0.0 0 0 ? SW Sep05 0:00 [bdflush]
root 7 0.0 0.0 0 0 ? SW Sep05 0:00 [kupdated]
root 8 0.0 0.0 0 0 ? SW Sep05 0:00 [mdrecoveryd]
root 12 0.0 0.0 0 0 ? SW Sep05 0:00 [kjournald]
chc 1624 0.0 3.4 22844 8904 ? S Sep05 0:00 kdeinit: kwrited
chc 1632 0.0 3.5 21808 9044 ? S Sep05 0:00 korgac --miniicon
chc 1643 0.0 3.2 21776 8368 ? S Sep05 0:00 kalarmd --login
chc 1681 1.5 11.0 66376 28320 ? S Sep05 2:05 /usr/lib/mozilla/
잠깐 왜 우리가 프로세스를 잠궈야 할까? 그것은 해커가 루트를 획득한후 프로세스들을 제거하여
웹 서비스 같은것을 중단시킬수 있기 때문인데 예를들어 kill -9 4 를 하면
kswapd 가 죽지 않고 Zombie 상태가 될것이다. 그렇게 되면 우리가 예상한것 보다
큰 문제가 발생할 것이다.
ps 를 하게되면 내부적으로 아래와 같을 것이다.
1. execve("/bin/ps");
2. proc 라이브러리 열기
3. /proc 안에 있는 디렉토리들을 차례대로 열어서 프로세스들의 정보를 얻어낸다.
4. 만약 open("/proc/1624") 를 한다면, proc 가상 파일시스템을 거쳐서 proc_pid_lookup
함수까지 가게된다.
이 함수는 ls /proc 명령을 치게 되면 pid 가 디렉토리 목록으로 나올것이다.
아래 소스는 proc_pid_lookup 함수중 프로세스를 하이드 하는 부분이다.
1021 #ifdef CONFIG_LIDS
1022 if (cap_raised(task->lids_cap,CAP_HIDDEN) && lids_load && lids_local_load)
1023 inode=NULL;
1024 else
1025 #endif
자세한 설명을 하자면, task 프로세스의 lids_cap 에서 현재 capability 가 hidden 라면
얻어낸 inode 를 NULL 로 저장하여 보이지 않게 한다.
그런데 LIDS 가 패치된 커널 소스 안에는 프로세스를 숨기는 코드가 보이질 않는데
이것은 lids-adm 이라는 유저레벨 관리툴이 있어서 그 관리 프로그램으로
커널과 통신하여 관리할수 있다.
- (3) 파일 보호
보통 리눅스에서 파일에 접근 하려면 -rwxrwxrwx 이러한 권한만 가지고 접근여부를
결정한다. 하지만 이런것에 헛점이 있을수 있다. 그래서 LIDS 자체에서
강력한 파일시스템 보안을 제공한다.
커널 소스에서 파일에 접근하기 전에 반드시 lids_check_base 라는 함수를 호출한다.
이 함수는 dentry 와 플래그를 입력 받는다.
이 함수의 동작의 예를 들어보면
어떤 시스템콜을 통해서 /etc/apache 디렉토리에 접근하려고 한다.
그리고 현재 /etc 에는 ACL(Access Control List)에 기반하여 보호가 된다고 가정하자.
잠깐 우선 어떻게 관리할 파일(아이노드)이 기술되는지 살펴보겠다.
LIDS 에서 사용되는 자료구조는
struct lids_acl {
struct lids_acl *next;
unsigned long int ino;
kdev_t dev;
int type;
};
위와 같으며
next 는 다음 acl 을 가리키고
ino 는 관리될 파일(아이노드)를 가리키며
dev 는 디바이스 타입을 가리킨다.
type 는 읽기전용,쓰기전용,추가전용,접근불가 이렇게 나뉘며
특히 추가전용 같은 경우 로그파일 같은곳에 유용하다.
다시 돌아가서..
lids_check_base 의 동작 방법을 알아본다면,
while(dentry)
{
만약 현재 프로세스가 도메인을 체크한다면
lids_check_acl(base,flag);
dentry = dentry->d_parent;
}
이 소스는 parent dentry 로 가면서 dentry 가 LIDS 시스템에 의해 보호되고 있는지
체크를 하는 부분이다.
lids_check_acl 함수의 동작부분을 요약해보면 아래와 같다.
acl = current->lids_sys_acl->lids_domain;
while(acl != NULL)
{
if(acl->ino == inode->i_ino)
return 보호되고 있다;
}
그 다음부분은 lids_data 라는 자료구조에 들어가 있는 아이노드와 비교하여
리턴한다.
- (4) 그 외
지금까지 LIDS 에서 가장 많은 비중을 차지한 함수들을 분석하였다.
그 외에는 LIDS 관리 프로그램인 lids-adm 과 통신을 하기 위한 코드들이다.
3. 예제
이해를 돕기 위해 예제를 들어 보겠다.
유저모드에서 아래와 같은 문장을 실행하게 되면 lids.conf 에 2번과 같은 문장이
추가 될 것이다.
1) lidsadm -A -r /sbin/
2) 0:0::1:0:80483:770:/sbin:0-0
각 필드들은 타입,아이노드,디바이스번호,파일명 등이다.
그리고 리부팅을 해서 커널의 처음 시작 루틴에서 lids_load 를 1로 설정한다.
초기에 lids_init() 를 호출하면 아래와 같은 루틴이 작동한다.
filp = filp_open(LIDS_CONF_FILE,O_RDONLY,O_RDONLY);
즉 /etc/lids.conf 을 연다.
filp->f_op->read(filp,buffer,1024,&filp->f_pos);
설정 파일에서 1024 바이트만 읽는다. 물론 이 연산은 유저모드에서 커널모드로
복사해 오는것이기 때문에 더 복잡하다.
한줄씩 읽으면서 #으로 시작하면 넘어가고 아니면 lids_init_add_file 을 호출해서
한줄에 읽은 문자열을 넘겨줘서 분석을 하고 각 필드들을 메모리에 넣고
나머지 아이노드,타입,파일명 필드는 lids_get_info 함수에서 처리한다.
그런후에 얻어진 inode 번호등을 이용해 lids_add_acl 함수로 acl list 에 추가하게
되는 것이다. 그리고 앞에서 보았듯이 디렉토리에 접근 할때는 acl list 를
검사한다.
'Linux' 카테고리의 다른 글
우분투 종료방법 (ubuntu shutdown) (1) | 2011.03.04 |
---|---|
리눅스에서 CD 굽기기 (0) | 2011.03.04 |
__attribute__ __context__ sparse (0) | 2011.02.15 |
#define 활용, macro, preprocess (DEBUG, printf) (0) | 2010.12.07 |
linux directory dirent.h (0) | 2010.12.05 |
WRITTEN BY
- RootFriend
개인적으로... 나쁜 기억력에 도움되라고 만들게되었습니다.
,