|
「ハニーポット」というのは、クラッカーに対して脆弱に見せかけて好き勝手やらせ、ログをとったりして笑う、ではなく資料にしたり、悪事の証拠にしたりするためのものである。狭義ではそういった鯖プログラムを指すと考えてもよいだろう。
こういったもんはきちっとしたものも多少は作られているが、あまりない。まあ、あったってそうそう使われないのだろう。本気でクラッカーと戦おうという場合以外は(それが仕事なら別だ)。それに既成のものはマジメすぎて面白くない。だいたいネットワークセキュリティーについて考えるなんてのは大変疲れるので、マジメ1本でやってたら気が狂う。そこで、楽しいものを作ってみよー!ということなのだ。 というわけで作ってみた。自分は C言語では多少まともな鯖など作ったことがあるが、大変だったので、今回は Perl で書いてみた。 Perl は慣れているつもりだったし、ソケットプログラミングはなんとなく分かるから素早く書けるだろう、と思っていたのだが、素早く書けなかった(笑)。そこで、手元にあった Perl の本を参考にほとんど丸写しした(泣)。「Perl for expert (秀和システム)」というこの本は安いのに内容が充実していて素晴らしいので、持っていて損はない。しかし、Perl だと楽に書けるもんだ。 ■ 概要 ■
変数 $log の値を変更して、ログファイルの出力先を決めたら、 keronet_server.pl を置いたディレクトリに入って hoge.fuga$ perl ./keronet_server.pl & でバックグラウンドで起動します(フォアでもいいけど)。 他の端末から telnet でポートを指定してアクセスします。 keronet_server の走っているホストを hoge とすると uhyo.fuga$ telnet > open hoge 54321 > ...あとは telnet ログインの要領で、遊び方が分かったら、ソースをイジって(# as you like !! や # scenario2 の部分など)自分好みの動きを記述して、 $port_server 変数を 23(telnet) とか、22(ssh) とかにして走らせましょう。 そういった特権ポートで動かすには root になってください。それから当然そのポートを使っているほかのデーモンを止めてからです。 そのうちバカなクラッカーが引っかかってきますぜ、ひひ。 ログを見て大笑いしましょう。 というのはウソです。 ぜひ「自分だけ」で遊んでください。下手なことをすると恐ろしい逆襲に遭うでしょう。 ■ ご注意 ■
###################################################################
#!/usr/bin/perl
#
# keronet_server.pl
# shimakero
# 2001.11.06
#
use sigtrap;
use Socket;
my %CHILD;
#
# dynamic configuration
#
my $proto = 'tcp';
my $port_server = 54321;
my $welcome_msg = "Ultra Linux 2.4 (Flog)\n"
."Kernel 2.4.13-4649 on an i686\n";
my $log = "$ENV{HOME}/dvlp/perl/keronet_server.log";
my $scn = 1;
my $waiting_clients = 3;
# as you like !!
if($scn == 1){
$span_lastlogin = 80000;
$host_lastlogin = 'smtp2';
$login_msg = "\n\n>> Wellcome to kero's Honey Pot <<\n\n";
$repeated_msg = "I love you.";
$quit_msg = "Thieves start as liars. :-( ";
$prompt = 'honeypot.kero$';
$command_max = 5;
}
&main;
#
# handler
#
sub sigchld()
{
my $pid = wait;
$SIG{CHLD} = \&sigchld;
print "CLOSED{$pid} "
, scalar localtime(), ' : '
, time - $CHILD{$pid} , "sec.\n";
delete $CHILD{$pid};
}
sub main
{
my $protonum;
{# get protocol number
$protonum = getprotobyname($proto)
or die("ERROR: getprotobyname(): $!");
}
{# create socket
socket(SH
, Socket::AF_INET
, Socket::SOCK_STREAM
, $protonum
)
or die("ERROR: socket(): $!");
}
{# set socket options
setsockopt(SH
, Socket::SOL_SOCKET
, Socket::SO_REUSEADDR
, pack('l', 1)
)
or die("ERROR: setsockopt(): $!");
}
{# bind
bind(SH
, sockaddr_in($port_server, Socket::INADDR_ANY)
)
or die("ERROR: bind(): $!");
}
{# listen
listen(SH, $waiting_clients) or die("ERROR: listen(): $!");
}
{# handler SIGCHLD
$SIG{CHLD} = \&sigchld;
}
{# accept...
my($peeraddr, $now, $pid, $born);
my($port_client, $inetaddr, $peername);
while($peeraddr = accept(CH, SH)){
{# get client information
($port_client, $inetaddr) = Socket::sockaddr_in($peeraddr);
$peername = gethostbyaddr($inetaddr, Socket::AF_INET);
$inetaddr = Socket::inet_ntoa($inetaddr);
}
#
# create child process
#
my $pid = fork;
if($pid){
#
# primary
#
print "ACCEPT[$pid] "
, scalar localtime() , ' : '
, $peername || $inetaddr
, ":$port_client\n";
$CHILD{$pid} = time;
}elsif(defined $pid){
#
# child
#
open(STDIN, '<&CH')
or die("ERROR: open(STDIN, '<&CH'): $!");
open(STDOUT, '>&CH')
or die("ERROR: open(STDOUT, '>&CH'): $!");
open(STDERR, '>&CH')
or die("ERROR: open(STDERR, '>&CH'): $!");
select((select(STDIN), $|=1)[0]);
select((select(STDOUT), $|=1)[0]);
select((select(STDERR), $|=1)[0]);
#
# like telnetd
#
print "\n"
, "$welcome_msg\n"
,"login: ";
my $lop = 0;
my $acount;
my $command;
INPUT_LOOP:
while(<>){
$_ =~ s/\x0a//;
$_ =~ s/\x0d//;
if($lop == 0){
$acount = $_;
}
$command = $_;
local(*LOG);
{# error abort
if(open (LOG, ">>$log")){
flock(LOG, 2);
my $temp
= $peername eq '' ? 'unknown' : $peername;
if($lop == 0){
print LOG substr(scalar localtime(), 4)
,"$pid{$$} $temp "
, "$inetaddr:$port_client "
, "$acount [ LOGIN ]\n";
}else{
print LOG substr(scalar localtime(), 4)
,"$pid{$$} $temp "
, "$inetaddr:$port_client "
, "$acount $command\n";
}
flock(LOG, 8);
close(LOG);
}
}
SWITCH:
{
$scn == 1 and do{
#
# scenario 1
# accept any password
# But, The server always says "I love you."
# finally, says "Thieves start as liars"
#
if($lop == 0){
#
# ignore password(pretends as not being set a password)
# print "Password: ";
print "Last login: "
, scalar localtime(time()
- $span_lastlogin)
, " from $host_lastlogin\n"
, "$login_msg\n"
, "$prompt ";
}elsif($command eq 'exit' or $lop > $command_max){
print "\n\n$quit_msg\n\n";
last INPUT_LOOP;
}else{
print "$repeated_msg\n"
, "$prompt ";
}
last SWITCH;
};
# $scn == 2 and do{
#
# scenario 2 .....
# ( place holder )
# last SWITCH;
# };
print "\nbye\n\n";
last INPUT_LOOP;
}
$lop++;
}
exit 0;
}
}
die("ERROR: accept(): $!");
}
}
|