Perl 프로젝트/Simple IDS Project

Ver 0.1 ] Simple IDS in Perl

Safeguard 2012. 12. 18. 10:25

1. IDS 모티브로 구현된 , Ver 0.1 Perl IDS 프로그램입니다.

2. 소스코드를 분석해 보겠습니다.

#!/usr/bin/perl -w
use strict;

# 라이브러리 사용 선언
use Net::PcapUtils;
use NetPacket::Ethernet;
use NetPacket::IP;
use NetPacket::TCP;
use Data::HexDump;
use Sys::Syslog;
use DBI;
use Switch;

# db 연결 속성 설정
my $driver = "mysql";
my $database = "packets";
my $dsn = "DBI:$driver:database=$database";
my $userid = "root";
my $password="1234";

# db 연결
my $dbh= DBI->connect($dsn,$userid,$password) or die $DBI::errstr;


my $i=0;
my $portnum;
 while(1){ #전체에 대한 루프 #
# 메뉴 선택 부분
 print "+- - - - - - - - - - - - - - - - - - - - - - - - -+\n";
 print "+ - =  Simple IDS 입니다. 메뉴를 선택하세요 ! = - +\n";
 print "+   =  IDS] 실행   or    VIEW] 패킷내용 검색  =   + \n";
 print "+- - - - - - - - - - - - - - - - - - - - - - - - -+\n" ."command\>";
 chomp(my $orders=<STDIN>);
 
# IDS 선택시 
 if($orders =~ (/ids/i)){
 # 패킷 조건 설정
 print " 《《《  Network Sequrity Mode :: ver 0.1   》》》\n";
 print "   -+ Enter] input the Port Range :: ex] 80 + - \n";
 print "command\>";
 chomp($portnum=<STDIN>); print "> ok <  $portnum :  Network Monitering and analysis ! \n";
 # 방화벽 추가 횟수 제한
 my $k=0;

 # 덤프 루프부
 Net::PcapUtils::loop(\&process_pkt);

# 패킷 처리부
 sub process_pkt {

 my $ports=$portnum; # portnum 함수내 지정
 
  my ($user_data,$hdr,$pkt)=@_;

   my $eth=NetPacket::Ethernet->decode($pkt);

   if($eth->{type} == 2048){

        my $ip=NetPacket::IP->decode($eth->{data});

     if($ip->{proto} == 1 || 2 || 6 || 17 ){

           my $tcp=NetPacket::TCP->decode($ip->{data});

# protocol 문자열 변환
 my $asciipro;
 switch($ip->{proto}){
 case "1"  {$asciipro="icmp"}
 case "2"  {$asciipro="igmp"}
 case "6"  {$asciipro="tcp"}
 case "17"  {$asciipro="udp"}
 else {$asciipro="Other"}
 }

# 네트워크 내에 발생된 패킷 데이터베이스에 기록
 my $sth= $dbh->prepare("INSERT INTO dump
     (dest_mac,src_mac,dest_ip,src_ip,protocol,flag,block,seqnum,acknum,winsize,urg,ttl,sport,dport)
     values
     ('$eth->{dest_mac}','$eth->{src_mac}','$ip->{dest_ip}','$ip->{src_ip}','$asciipro','$ip->{flags}',0,'$tcp->{seqnum}','$tcp->{acknum}','$tcp->{winsize}','$tcp->{urg}','$ip->{ttl}','$tcp->{src_port}','$tcp->{dest_port}')");

 # 쿼리l 실행
 $sth->execute() or die $DBI::errstr;
 #종료
 $sth->finish();
 #dbms commit 명령
 #$dbh->commit or die $DBI::errstr;
    
    

  #  지정한 아이피 또는 포트에 대한 패킷 분석 부분

   if($tcp->{src_port} eq $ports){ #지정한 포트와 인풋 포트가 같다면
   
    print "+_+_+_+_+_+_+_  $ports 포트 패킷 발견 !!  _+_+_+_+_+_+_+_+ \n";
    print "[ 침입탐지 ] SysLog 에 저장 되었습니다. \n";
     my $fireip = $ip->{dest_ip};
    if($k<1){ 
     # 탐지된 아이피 방화벽에 추가 후 방화벽 재시작
     system("iptables -t filter -A INPUT -s $fireip -j DROP");
     system('service iptables save');
     sleep(1);
     system('/etc/init.d/iptables restart');

     # 탐지된 아이피 Sys log 저장
     openlog(my $program,'cons,pid','user');
     syslog("info",'Warning!! connect ip : \%s  port: %s   ',$ip->{dest_ip},$tcp->{dest_port});
     sleep(1);
     $k++;
      }
   }else{  # 지정한 포트와 인풋 포트가 같지 않으면
     # 패킷 덤프하여 출력
      print "\n\n$i $ip->{src_ip}($tcp->{src_port}) -> $ip->{dest_ip}($tcp->{dest_port})\n";
    
         print HexDump $ip->{data};

           $i++;}
    
     
     

   } 
   }
 } 

 

 }elsif($orders =~(/view/i)){  # VIEW 메뉴 선택시
 while(1){ # 반복 실행   
 print "+ - -《《  IDS Log View   》》 - - +\n";
 print " Port ] 검색시 port 입력, IP ] 검색시 IP 입력 !! Black] Black List 확인  exit] 종료시exit !!    예]port \n";
 print "command\>";
 chomp(my $search=<STDIN>);

 # Port  Search 부
 if($search =~(/port/i)){
  print "검색할 포트번호를 입력 하세요 !! \n";
  print "command\>";
  chomp(my $ptnum=<STDIN>);
  my $sth = $dbh->prepare("select * from dump where sport = ?");
 $sth->execute($ptnum) or die %DBI::Errstr;

 

 
 # Port Search 검색 결과 출력 
 while(my @row = $sth->fetchrow_array()){
 my($dest_mac,$src_mac,$dest_ip,$src_ip,$protocol,$flag,$block,$seqnum,$acknum,$winsize,$urg,$ttl,$sport,$dport)=@row;
 print" MAC : $dest_mac, Ip : $dest_ip , protocol : $protocol , seqnum : $seqnum, acknum : $acknum, winsize : $winsize , urg : $urg, ttl : $ttl sport: $sport , Dest_port : $dport \n";
      }

 print "+- - - - - - - - - - - - - - - - - - - - - - - - -+\n";
 print " 검색 결과 : " . $sth->rows . " 개 검색 되었습니다 \n";
 
 # 차단 여부  설정부
 print " 검색 결과 중, 차단할 포트가 있습니까? yes or no \n";
 print "command\>";
 chomp(my $que = <STDIN>);
  if($que =~(/yes/i)){
  print " 차단할 포트를 입력 하세요 ! \n";
  print "command\>";
  chomp(my $blockport = <STDIN>);
 
  # 방화벽에 추가 후 방화벽 재시작
  system("iptables -t filter -A INPUT -p tcp --sport $blockport -j DROP");
  system('service iptables save');
  system('/etc/init.d/iptables restart');
  
  # db block 추가
  my $query = "UPDATE dump SET block = 1 WHERE dport = $blockport;";
  my $query_handling = $dbh->prepare($query);
  $query_handling->execute();
  }elsif($que=~(/no/i)){
  last;}

 $sth->finish();

 # IP Search 부
  }elsif($search =~ (/ip/i)){
  print "검색할 아이피를 입력 하세요 !! \n";
  print "command\>";
  chomp(my $ipnum=<STDIN>);
  
 my $sth = $dbh->prepare("select * from dump where dest_ip = ?");
 $sth->execute($ipnum) or die %DBI::Errstr;
 
 # IP Search 검색 결과 출력
 while(my @row = $sth->fetchrow_array()){
  my($dest_mac,$src_mac,$dest_ip,$src_ip,$protocol,$flag,$block,$seqnum,$acknum,$winsize,$urg,$ttl,$sport,$dport)=@row;
 print" MAC : $dest_mac, Ip : $dest_ip , protocol : $protocol , seqnum : $seqnum, acknum : $acknum, winsize : $winsize , urg : $urg, ttl : $ttl sport : $sport dport : $dport \n";
      }
 
 print "+- - - - - - - - - - - - - - - - - - - - - - - - -+\n";
 print " 검색 결과 : " . $sth->rows . " 개 검색 되었습니다 \n";
 
 # 아이피 서치 후, 차단 여부 설정 부
 print " 검색 결과 중, 차단할 아이피가 있습니까? yes or no \n";
 print "command\>";
 chomp(my $que2 = <STDIN>);
  if($que2 =~(/yes/i)){
  print " 차단할 아이피를 입력 하세요 ! \n";
  print "command\>";
  chomp(my $bip = <STDIN>);
 
  # 방화벽에 추가 후 방화벽 재시작
  system("iptables -t filter -A INPUT -s $bip -j DROP");
  system('service iptables save');
  system('/etc/init.d/iptables restart');
 # db block 추가
  
  my $query = "UPDATE dump SET block = 1 WHERE dest_ip = '$bip';";
  my $query_handling = $dbh->prepare($query);
  $query_handling->execute();
 
  }elsif($que2=~(/no/i)){
  last;}
 $sth->finish();
 # black list Search 부
 }elsif($search =~(/black/i)){
 
 my $sth = $dbh->prepare("select * from dump where block = 1");
 $sth->execute() or die %DBI::Errstr;
 
 # Black List  검색 결과 출력
 while(my @row = $sth->fetchrow_array()){
  my($dest_mac,$src_mac,$dest_ip,$src_ip,$protocol,$flag,$block,$seqnum,$acknum,$winsize,$urg,$ttl)=@row;
 print" MAC : $dest_mac, Ip : $dest_ip , protocol : $protocol , seqnum : $seqnum, acknum : $acknum, winsize : $winsize , urg : $urg, ttl : $ttl \n";
      }
 
 print "+- - - - - - - - - - - - - - - - - - - - - - - - -+\n";
 print " 검색 결과 : " . $sth->rows . " 개 검색 되었습니다 \n";

 


 }elsif($search =~(/exit/i)){
  last;}
 } #while end
 
 } #else end
 } #전체 루프