메뉴 바로가기 검색 및 카테고리 바로가기 본문 바로가기

한빛출판네트워크

한빛랩스 - 지식에 가능성을 머지하다 / 강의 콘텐츠 무료로 수강하시고 피드백을 남겨주세요. ▶︎

IT/모바일

루트킷 조사하기

한빛미디어

|

2002-04-16

|

by HANBIT

11,995

저자: Oktay Altunergil, 역 서성용

이전에 작성했던 기사인 루트킷 이해하기에서 우리는 어떻게 시스템 침입과 루트킷을 감시해야 할지에 대해 이야기했다. 누구도 침입할수 없는 서버를 갖는 것이 가장 좋지만, 현실적으로 네트워크에 연결된 모든 서버는 잠재적인 침입의 표적이 된다고 할 수 있다.

만일 서버가 침입당할 경우, 이것을 너무 늦지 않게 발견하는 것과 그 공격에 대항해 살아남는 수단을 취하는 것은 똑같이 중요하다.

나의 서버가 침입당했나?

대개 서버가 침입당한 것으로 의심할 수 있는 첫 번째 징후는 서버의 동작중 발생하는 단순한 이상동작이다. 이때 발생하는 많은 공통적인 이상 동작중 하나는 한 개 또는 그 이상의 핵심 시스템 유틸리티에서의 변화이다. 예를 들어 매일 아무 문제없이 사용하던 "netstat" 이나 "ps" 에 대한 명령행 스위??에러 메시지를 반환하기 시작할 수도 있다. 왜냐하면 침입자가 이러한 유틸리티를 자신의 이상 행동을 숨기기 위해 설계된 버전으로 갈아치웠을 수도 있기 때문이다. 이들이 갈아치운 유틸리티는 원래의 것과 다른 버전일수도 있고, 다른 옵션으로 컴파일되었을 수도 있기 때문에 그 결과 우리가 사용하던 것과 같은 옵션을 갖지 않는다.

또다른 큰 적신호를 일으키는 이상은 대역폭 사용량 패턴의 변화이다. 만약 호스팅 회사가 주기적으로 대역폭 사용량을 모니터한다면, 서버가 내뱉고 있는 트래픽의 양이 정상적인 트래픽 패턴과 비교하여 증가했음을 발견할 것이다. 이것은 대개 저작권이 있는 소프트웨어를 배포하기 위해 침입자가 서버를 사용함으로써 발생하는데 흔히 "warez" 라고 알려져 있다. 서버에서의 그러한 행위의 결과로 법적인 조치의 상대가 여러분 자신이 될 수도 있음을 기억하라.

이상적으로 서버 관리자는 서버가 침입의 징후를 검사하기 전, 모든 알람이 울릴 때까지 기다려서는 안된다. 왜냐하면 침입자가 서버에서 보내는 시간이 적으면 적을수록 손상의 정도도 작아질 것이기 때문이다. (매우 악의적인 침입자는 잠재적인 루트 수준의 접근을 얻은 후 전체의 시스템을 지워버릴 수도 있다.) 이러한 이유에서, 서버 보안 검사를 주기적으로 수행하는 것이 중요하며, 서버가 침입 당했을 경우 가능한 한 빨리 아는 것도 중요하다.

포트 스캐닝

침입자는 차후 서버에 쉽게 접근하기 위해 거의 항상 서버에 백도어를 설치하려는 노력을 한다. 로컬 시스템 유틸리티들도 아마 침입으로 인해 감염될 것이므로 침임자를 탐지하는데 신뢰할 수 없다. 그렇지만 외부 머신에서 수행된 포트 스캐닝은 보통 때는 닫혀있어야 할 열린 포트를 드러낼지도 모른다. 유닉스 세계에서 사실상의 표준 포트 스캐너는 nmap 이다. GUI 버전뿐 아니라 명령 라인으로도 이용할 수 있다. 여기서는 도구 자체의 세부사항을 다루지는 않고 리스닝하고 있는 서비스를 찾아서 한 서버에 있는 포트를 검색하는 방법을 살펴보자.
[root@leeloo root]# nmap -p 1-65535 192.168.0.1

Starting nmap V. 2.54BETA22 ( www.insecure.org/nmap/ )
Interesting ports on  (192.168.0.1):
(The 65531 ports scanned but not shown below are in 
  state: closed)
Port       State       Service
21/tcp     open        ftp
22/tcp     open        ssh
80/tcp     open        http
111/tcp    open        sunrpc


Nmap run completed -- 1 IP address (1 host up) scanned 
  in 169 seconds
[root@leeloo root]#
이와 같은 특별한 명령 변형은 이용할 수 있는 모든 포트들 (1에서 65535를 포함한)을 192.168.0.1에서 검색한다. 위에서의 열린 포트가 ftp, ssh, http의 트로얀으로 오염된 버전일수도 있으나, 진짜 문제는 보통 극소수의 합법적인 서비스들만이 들어오는 접속에 대해 리슨하는 수천번대 이상의 포트 번호가 있을 경우다. 주기적으로 전체 네트워크를 스캐닝해서 다른 시간 주기에 대한 출력간의 차이점을 확인하는 것은 현명한 일이다.

보안 도구로서의 RPM

RPM (Red Hat Package Manager)는 레드햇, 맨드레이크, 수세를 포함한 주요 리눅스 배포판에서 사용되는 인기있는 패키징 시스템이다. 하나의 RPM 패키지가 설치될 때마다 패키지 관리자는 패키지와 패키지가 포함한 개별적인 파일에 대한 정보를 하나의 중앙 RPM 데이터베이스에 집어넣는다. 아주 간단하지는 않지만 이 정보는 빠르고 쉬운 시스템 검사를 수행하는데 사용될 수 있다. 시스템에 이상이 없다고 RPM이 보고할 때 이것을 100% 신용하는 것은 위험한 일일 수 있지만 시스템 바이너리들이 수정되었다고 보고할 때 이를 의심할 필요는 거의 없다.

RPM은 패키지 안에 있는 모든 파일의 체크섬을 기록하고 검사한다, 이 파일중에는 시간이 지남에 따라 변경될 것으로 예상되는, 다양한 설정파일 같은 것들을 비롯해 passwd, shadow, group 파일들과 같은 다른 파일들도 포함되어 있다. 이것은 전체 검사를 어렵게 할뿐만 아니라 결과를 이해하기도 어렵다. 여러분은 소수의 중요한 핵심 패키지들에 대해서만 검사를 수행함으로써 이 작업을 쉽게 할 수 있다. 이러한 패키지들은 다른 것들 가운데서도 net-tools, fileutils,

이것은 RPM 패키지에 대한 서명을 검사하는 법이다.
rpm -V procps
만약 패키지 파일들에 대해 변화가 없다면 명령행으로 되돌아올 것이고 변화가 있다면 다음과 같이 출력될 것이다.
S.5....T c /root/.bash_profile
첫 번째 항목은 패키지가 처음 인스톨된 이후로 마지막 항목에 출력된 특정 파일에 어떤 변화가 일어났는지를 보여준다.

아래 기호의 의미는 다음과 같다(맨페이지에서 인용):
M   모드가 다름 (퍼미션과 파일 타임을 포함하여)
5   MD5 sum이 다름
D   장치 주/부 번호가 부적절
L   readLink(2) 경로가 부적절
U   사용자 소유권이 다름
G   그룹 소유권이 다름
T   mTime이 다름
이 외에도 모든 것을 테스트하기 쉬운 방법이 있다. 위에서 출력된 기본 패키지의 일부분이 아니라 파일에서의 변화도 탐지하는데 사용될 수 있다. rpm -Va >filename.txt 명령을 이용해 전체 보고를 파일로 리다이렉트하여 어떠한 중요한 변화라도 확인할 수 있다.

RPM 유틸리티를 이용해 특정 파일이 어떤 패키지에 속하는지를 알아볼 수도 있다. 이것은 흔하지 않은 장소에 있는 잘 알려진 바이너리를 찾을 때 유용하게 이용할 수 있다.

rpm -qf /path/to/file은 그 파일이 어떠한 패키지의 일부분 인지 아닌지를 알려준다. 그 이후엔 특정 패키지에 대하여 -V를 실행하여 변화를 탐지할 수 있다.

부정적인 결과를 얻을 때만 RPM을 신뢰할 수 있음을 명심하라. RPM 바이너리, 운영 체제, RPM 데이터베이스를 수정해서 변경사항들이 탐지되지 않도록 할 수 있다. 이러한 이유에서, ‘chkrootkit’와 RPM 방법을 함께 이용하는 것은 좋은 생각이다.

chkrootkit 루트킷 스캐너

chkrootkit은 시스템과 관련된 잘 알려진 루트킷의 존재를 탐지하는데 사용되는 작은 유틸리티 모음이다. 거의 모든 스크립트를 찾는 독립적인 탐지 스크립트도 있지만, chkrootkit은 단일 애플리케이션을 이용해 서로 다른 수많은 루트킷을 탐지할 수 있는 능력 때문에 다른 것들과 차별된다. 알려진 루트킷 서명 탐지 외에도 그 애플리케이션에 의해 실제로 지원되지 않는 루트킷을 발견하는데 도움을 줄 수 있는 몇몇 일반적인 시험도 수행한다.

chkrootkit 패키지는 일곱 개의 작은 애플리케이션을 포함한다. 주요 프로그램인 chkrootkit은 알려진 루트킷서명을 탐지하는데 사용한다. 루트킷의 기본 파일을 검색할 뿐 아니라 의심스러운 내용에 대해 핵심 시스템 바이너리를 검사한다. 패키지에서 남아있는 애플리케이션들은 네트워크 인터페이스가 무차별(promiscuous) 모드(netstat를 신뢰하지 말라고 했던 것을 기억하라)인지를 발견하는데 도움을 주는 ifpromisc와 다양한 로그 파일에서 삭제를 탐지하는 chklastlog, chkwtmp, check_wtmpx, 적재가능한 커널 모듈(LKM: Loadable Kernel Module) 트로얀과 감추어진 프로세스를 탐지하는 chkproc, 마지막으로 유닉스 문자열 유틸리티의 간단한 구현인 문자열이 있다.

chkrootkit 사용법을 알아보기 전, 이것을 얻는 방법과 설치하는 방법부터 살펴보자. 공식 chkrootkit 사이트는 http://www.chkrootkit.org이다. 가장 최근에 작성된 .tar.gz 파일을 이 웹 사이트에서 다운는다. 파일을 받은 후 임시 디렉토리에 넣어 압축을 풀고(tar xfvz chkrootkit.tar.gz) cd로 새롭게 생성된 디렉토리로 들어간다(cd chkrootkit-0.35). 마지막으로 make sense를 입력해 그것을 컴파일한다. 애플리케이션은 언제나 대부분 문제없이 컴파일 되겠지만, 만약에라도 에러 메시지를 만난다면 다른 유사한 머신에서 빌드를 시도해서 스캐닝 하고자 하는 서버로 바이너리들을 이동시키자. 새롭게 생성된 바이너리를 설치하기 위해서 한 곳에 놓아두고 복사해서 사용할 수도 있다. 그러나 소프트웨어는 새로운 기능이 추가되어 자주 업데이트되므로 이와 같은 방법보다는 매번 새로운 사본을 얻어 사용할 것을 추천하는 바이다.

바이너리 생성 후, 필자 개인적인 취향으로는 당장 ./ifpromisc를 실행해 인터페이스 중의 어떤 것이라도 무차별 모드에 있는지를 확인한다. 왜냐하면 그 서버를 즉시 네트워크에서 뽑아버리고 싶을 경우를 대비해서이다. 또한 ifpromisc 바로 다음에 ./chkproc를 실행해서 그 시스템에 어떠한 숨겨진 프로세스나 LKM 트로얀이 있는지를 확인하는 것도 좋다. 이 두 개의 독립적인 유틸리티 실행후, 매개변수 없이 메인 프로그램인 ./chkrootkit를 실행할 수 있다. 이것은 이전에 우리가 실행했던 ifpromisc와 chkproc를 포함한 패키지에 있는 나머지 유틸리티들이 제공하는 테스트뿐 아니라 루트킷 검사도 수행한다.

이것은 chkrootkit에서 출력한 샘플의 일부분이다.
[root chkrootkit-0.34]# ./ifpromisc
eth0 is not promisc
eth0:0 is not promisc
eth0:1 is not promisc
eth0:2 is not promisc
eth0:3 is not promisc
eth0:4 is not promisc
eth0:5 is not promisc
eth0:6 is not promisc
eth0:7 is not promisc
eth0:8 is not promisc
[root chkrootkit-0.34]#


[root chkrootkit-0.34]# ./chkrootkit
ROOTDIR is `/"
Checking `amd"... not found
Checking `basename"... not infected
Checking `biff"... not found
Checking `chfn"... not infected
Checking `chsh"... not infected
Checking `cron"... not infected
Checking `date"... not infected
Checking `du"... not infected
Checking `dirname"... not infected
Checking `echo"... not infected
Checking `egrep"... not infected
Checking `env"... not infected
Checking `find"... not infected
Checking `fingerd"... not found
Checking `gpm"... not infected
Checking `grep"... not infected
Checking `hdparm"... not infected
Checking `su"... not infected
Checking `ifconfig"... not infected
Checking `inetd"... not infected
Checking `inetdconf"... INFECTED
Checking `identd"... not found
Checking `killall"... not infected
Checking `login"... not infected
Checking `ls"... not infected
Checking `mail"... not infected
Checking `mingetty"... not infected
Checking `netstat"... not infected
Checking `named"... not infected
Checking `passwd"... not infected
Checking `pidof"... not infected
Checking `pop2"... not found
Checking `pop3"... not found
Checking `ps"... not infected
Checking `pstree"... not infected
Checking `rpcinfo"... not infected
Checking `rlogind"... not infected
Checking `rshd"... not infected
Checking `slogin"... not infected
Checking `sendmail"... not infected
Checking `sshd"... not infected
Checking `syslogd"... not infected
Checking `tar"... not infected
Checking `tcpd"... not infected
Checking `top"... not infected
Checking `telnetd"... not infected
Checking `timed"... not found
Checking `traceroute"... not infected
Checking `write"... not infected
Checking `aliens"... no suspect files
Searching for sniffer"s logs, it may take a while... nothing found
Searching for t0rn"s default files and dirs... nothing found
Searching for t0rn"s v8 defaults... nothing found
Searching for Lion Worm default files and dirs... nothing found
Searching for RSHA"s default files and dir... nothing found
Searching for RH-Sharpe"s default files... nothing found
Searching for Ambient"s rootkit (ark) default files and dirs... nothing found
Searching for suspicious files and dirs, it may take a while...
/usr/lib/perl5/site_perl/5.005/i386-linux/auto/mod_perl/.packlist /usr/lib/perl5/site_perl/5.005/i386-
linux/auto/MD5/.packlist /usr/lib/perl5/site_perl/5.005/i386-linux/auto/Quota/.packlist
/usr/lib/perl5/site_perl/5.005/i386-linux/auto/XML/Parser/.packlist /usr/lib/perl5/site_perl/5.005/i386-
linux/auto/Devel/Symdump/.packlist /usr/lib/perl5/site_perl/5.005/i386-linux/auto/Image/Magick/.packlist
/usr/lib/perl5/5.00503/i386-linux/.packlist /lib/... /lib/.../BitchX/.config.h
/lib/...
Searching for LPD Worm files and dirs... nothing found
Searching for Ramen Worm files and dirs... nothing found
Searching for Maniac files and dirs... nothing found
Searching for RK17 files and dirs... nothing found
Searching for Ducoci rootkit... nothing found
Searching for Adore Worm... nothing found
Searching for ShitC Worm... nothing found
Searching for Omega Worm... nothing found
Searching for anomalies in shell history files... nothing found
Checking `asp"... not infected
Checking `bindshell"... not infected
Checking `lkm"... ./chkrootkit: [: integer expression expected before -gt
not tested
Checking `rexedcs"... not found
Checking `sniffer"...
eth0 is not promisc
eth0:0 is not promisc
eth0:1 is not promisc
eth0:2 is not promisc
eth0:3 is not promisc
eth0:4 is not promisc
eth0:5 is not promisc
eth0:6 is not promisc
eth0:7 is not promisc
eth0:8 is not promisc
Checking `wted"... nothing deleted
Checking `z2"... user ap deleted or never loged from lastlog!
위에서 보듯이 이 시스템에 있는 인터페이스들은 무차별 상태는 아니지만 감염된 파일이 하나있다. chkrootkit은 "..." 디렉토리에 있는 의심스러운 파일(/lib/.../BitchX/.config.h)을 삭제했다. 침입자들은 주로 소수점 문자로 시작하는 이름을 갖는 디렉토리를 생성한다. 왜냐하면 발견되기 어렵거나 찾기 어렵기 때문이다. 이 외에도 ‘ .’(공백 점) 파일을 찾아야 하는데, 터미널 화면에서는 "." (현재 디렉토리)와 구별하기 어렵다. "Checking lkm" 행에서의 에러는 걱정할 만한 것이 아니다. 이는 커널이 적재가능한 커널 모듈을 지원하지 않을 때 나타나는 에러 메시지이고 그것과 관련해서 잘못된 점이 없기 때문이다(서버에 대해 가장 바람직한 설정). 마지막 행은 사용자 "ap"가 로그인하지 않았거나 나중에 로그파일에서 삭제된 것을 보여준다. 보다 자세한 정보를 원한다면 chkrootkit 웹사이트에 있는 FAQ를 읽어볼 것을 강력히 추천한다.

루트킷이 삭제되었다. 이제는 뭘 해야할까?

루트킷 감염 이후에도 시스템이 깨끗하다고 완전히 확신할 수 있는 유일한 방법은 드라이브를 포맷하고 원본 매체로부터 운영체제를 다시 설치하는 경우뿐이다. 그러나 실제 상황에서는 최소한 잠시동안만이라도 감염된 시스템을 사용해야 할 수밖에 없다. 이러한 경우에는 적어도 서버만이라도 깨끗이 하고 루트킷과 트로얀을 제거해야 한다.

chkrootkit 출력이 깔끔하고 핵심적이기는 하지만, 그것이 한 번 발견한 어떤 주어진 루트킷이나 트로얀을 제거하는 것에 대한 조언을 주지는 않는다. 루트킷이 작동하는 방식에 정통하고 싶다면 cert.org와 같은 보안관련 웹사이트나 특정 루트킷이 동작하는 법에 대해 설명하는 사이트를 자주 방문함으로써 그렇게 될 수 있다. Teep의 웹사이트에 있는 기사는 특정 루트킷 분석을 상세하게 보고하고 있을 뿐만 아니라 다른 루트킷에 적용할 수 있는 가치있는 정보도 많이 제공하고 있다. 루트킷에 정통하기 위한 또다른 방법은 시험 환경에서 그것을 인스톨하고 찾음으로써 시스템의 전후의 스냅샷을 사용해 결과를 비교하는 것이다. 만약 루트킷이 무엇을 하고, 어떤 디렉토리와 파일을 생성하고, 그리고 어떤 바이너리를 감염시키는지 알고 있다면 감염된 서버에서 트로얀된 파일을 삭제하고 감염된 바이너리를 깨끗한 것으로 대체할 수 있다.

RPM 기반의 시스템에서는 감염된 패키지를 이전 기사에서 설명한대로 확인할 수 있다. 감염된 RPM 패키지 목록을 얻으면 원본 소스를 사용해 다시 설치할 수 있다.

다음의 문법으로 RPM 패키지를 강제로 재설치할 것이다. 이 과정에서 이전 파일들은 덮어쓰여진다.
rpm -U --force  rpm_package_name.rpm
모든 감염된 RPM 패키지들을 재설치한 후, RPM 과 chkrootkit 검사를 다시 실행시켜서 여전히 해결되지 않은 문제들이 있는지 확인해야 한다. 만약 시스템이 RPM을 사용하지 않는다면 사용중인 운영 체제에 적용되는 유사한 과정을 따를 수 있다. 만약 어떠한 패키징 시스템도 사용하고 있지 않다면 이와 관련된 애플리케이션을 소스에서 다시 컴파일하여 이전 것들을 덮어써야 한다.

시스템에 있어야 할 패키지들을 다시 설치한 후, 침입자가 끌고 들어온 외부 파일들도 청소해야 한다. chkrootkit 출력은 이러한 파일의 위치를 확인할 수 있도록 도와줄 것이다. 또한 ifconfig, netstat, find, ls, top, ps 같은 핵심 시스템 유틸리티들을 청소한 후에는 보다 많은 외부 파일들과 프로세스들을 나타낼 수도 있는 정확한 정보를 보다 많이 얻을 수 있다. 루트킷에 포함되어 있을 수도 있는 설정 파일 읽기에 약간의 시간을 들이면 그 서버에 다른 트로얀 파일들과 프로세스가 있는지 그 단서를 찾을 수 있을 수도 있다.

확인한 모든 외부 파일들을 지운 후 "top"과 "ps"를 다시 실행해서 아직도 실행중인 원하지 않는 프로세스들을 확인하고 죽여라. 대부분의 시스템에서는 ‘netstat -nap"를 사용해서 데몬을 시작시킨 프로세스 이름과 ID를 볼 수 있다. 또한 초기화 스크립트를 검사해서 외부 프로세스가 그러한 스크립트를 이용해 시작되지 않도록 확실히 해두기를 원할 수도 있다. 침입자들은 대개 시작 행을 이러한 스크립트의 끝에 두기도 하지만 그것들을 파일의 중간에 숨겨서 확인하기 어렵도록 할 수도 있다. 침입자들이 시작 호출을 두는 흔히 사용되는 몇몇 위치로는 inetd.conf 파일, rc.local 파일, 서버를 구동시키는 run-level에 해당하는 초기화 디렉토리에 있는 다른 파일들이다. 또한 다른 초기화 스크립트들이 포용하는 /etc/rc.d/init.d/functions과 같은 도움 함수 파일들에 대해 특별한 주의를 기울여야 하고, 그 때문에 그 파일들 안에 있는 유효한 명령은 시스템이 재부팅될 때 간접적으로 실행되는 것을 허용하는 것이다.

더 이상 남아서 실행중인 스니퍼나 트로얀이 없는 것을 확신하고 나서야 서버의 패스워드를 모두 변경해라. 이것이 불가능하다면 적어도 루트나 서버에 그와 동등한 접근를 가진 사용자들의 패스워드라도 변경해라. 또한 패스워드 파일을 잘 살펴본 후 거기에 있으면 안된다고 생각하는 사용자들, 특히 루트와 동등한 권한을 가진 사용자들을 삭제해야 한다. 필요하다면 서버를 재부팅해 다른 보안 검색을 수행하여 모든 시동 스크립트와 감염된 바이너리를 청소할 수 있었는지를 확인해 볼 수도 있다.

결론

이론상으로는 루트킷이나 트로얀에 감염된 머신에서 루트킷이나 트로얀이 미치는 모든 영향을 탐지하여 제거할 수 있다. 그렇지만 시스템을 안전하게 하여 루트킷이나 트로얀이 시스템에 첫 번째 위치에서 들어오지 못하도록 하는 것이 더 중요하다. 인터넷에서 발생하는 침임 활동의 대부분은 특정 운영체제나 소프트웨어의 취약점을 조사하는 네트워크 스캔에 긍정적으로 반응하는 서버들을 대상으로 삼아 발생한다. 만약 소프트웨어 패치나 업데이트를 잘 해준다면 첫 번째 위??공격 목표가 될 가능성은 적다. 왜냐하면 잠재적인 침입자는 대개 그가 최소한의 노력으로 들어갈 수 있는 서버를 고를 것이고, 인터넷에는 이러한 취약한 서버가 절대로 부족하지 않기 때문이다.

그럼에도 불구하고 여전히 서버가 침입당하고 있다면 네트워크에서 서버를 즉시 분리하여 네트워크로 다시 연결하기 전에 운영체제를 다시 설치하고, 모든 보안 패치를 적용하자.

필자가 제공하는 정보는 흔히 알고 있는 보안 수단을 대체하지는 못하지만 다른 수단들과 결합되어 사용될 때 유용할 것이다.

서버가 항상 루트킷으로부터 자유롭기를!
TAG :
댓글 입력
자료실

최근 본 상품0