2계층, 3계층 개념 및 프로토콜 종류 / ip헤더 체크섬 계산 / DNS서버에 에코 리퀘스트 전송 실습에 대해서 정리한다.
2계층의 대표적인 통신 프로토콜
* Ethernet
* ARP
1. 2계층에서는 이더넷 헤더를 통해 통신
-> 2계층의 스위치(L2 S/W)가 이더넷 헤더를 참조해서 패킷을 교환해준다.
2. 호스트는 상대방의 맥 어드레스를 알아야만 통신이 가능
-> ARP 캐시 테이블을 참조하여 전송하려는 호스트를 확인
3. ARP 캐시 테이블을 오염시키는 방법으로 목적지를 속일 수 있었다.
( ARP Cache Poisoning )
- ARP Spoofing: sniffing, MITM attack
- S/W jamming: 맥 테이블을 공격하는 방법( 맥 테이블을 꽉 채우면 스위치가 dummy 환경으로 작동 )
- icmp redirect
* 2계층은 신뢰도가 아주 높은 구간으로 반드시 통신이 되어야만 한다
인터넷이 안될 때 확인할 수 있는 방법
1. 하드웨어 점검
- 케이블 불량, 이더넷 카드, ... 불량
2. 2계층
- 게이트웨이까지의 통신이 가능한가를 확인
- 주변 호스트와 통신이 가능한가 확인
ARP Spoofing을 막을 수 있는 방법은 없다( 아직까진 )
- 백신
- 네트워크 장비
- 과도한 ARP 패킷(request, reply)을 탐지
- 맥 캐시 테이블을 정적으로 사용 ( 가장 확실한 방법 )
* 어떠한 방법도 100% 완벽하게 차단하지 못한다.
취약점 발생 원인
- 인증을 하지 않는다. ( 인증을 하게 되면 너무 느려진다 )
- 동적인 설정
3계층
- 서로 다른 네트워크를 연결
- 서로 다른 스위치를 쓴다( 물리적으로 분리된 공간 )
* 하나의 스위치에 연결 -> 같은 네트워크
- 라우터(L3 S/W), 방화벽, ...
- PDU: packet
- protocol: IP, IPSEC, dynamic routing protocol
* IP( Internet Protocol )
- 목적지까지의 경로를 설정
- IP가 없으면 통신을 할 수 없다.
* ICMP( Internet Control Message Protocol )
- 네트워크의 에러를 전송
- 네트워크가 점점 커져서 이제는 icmp만으로는 관리가 어려워졌다.
- 취약점은 많아졌고, ...
공통 헤더
1). type: 1바이트 ( 0: Echo Reply / 8: Echo Request )
2). code: 1바이트
- icmp의 종류를 나타낸다.
3). chksum: 2바이트
* echo request / reply
1). identifier: 2바이트
2). seq number: 2바이트
3). payload
- payload는 데이터를 전달하는 용도가 아니다.
- icmp의 크기를 조절할때 많이 사용한다.
체크섬( check sum )
- 다 더해서 숫자 값이 일치하면 이상이 없고 다르면 이상이 있음을 확인하는 것
- 모든 경우의 에러를 다 체크하진 못한다.
ex). 100
- 어떤수를 더해서 100을 만들 수 있는 경우는?
- 99 + 1, 98 + 2, 97 + 3, ... ( 이런 여러가지 경우의 수가 존재 하기 때문에 모든 에러를 다 체크하진 못한다 )
- CRC 에러 테크, 패리티 부호, ... 를 같이 사용해서 체크해준다.
ip헤더 체크섬 계산 방법
1. 2바이트씩 잘라서 모두 더해준다
( 헤더에서 체크섬 부분은 0으로 바꾼후 진행한다 )
2. 올림수가 발생하는 경우
- 올림수를 분리해서 더해준다.
- 올림수가 발생하지 않을 때까지 해준다.
3. 1의 보수를 취해준다.
[실습]
- 192.168.6.200에 에코 리퀘스트 전송
프로토콜 스택
이더넷 헤더 + 아이피 헤더 + ICMP 헤더
* icmp 클래스를 정의할때는 다른 프로토콜 클래스를 정의할때와는 다르게 상속을 이용한 정의를 했다.
sniffer.py
import socket
import struct
import time
from header.packet import *
raw.bind( ('eth0', socket.SOCK_RAW) )
data, addr = raw.recvfrom( 65535 )
packet = Packet( data )
(packet.ip.src == '168.126.63.1' or packet.ip.dst == '168.126.63.1') \
and packet.ip.type == 1:
print("data: ", data)
print(packet.ip.src + ' -> ' + packet.ip.dst)
import struct
class Eth:
def __init__( self, raw=None ):
if raw != None:
self._dst = raw[:6]
self._src = raw[6:12]
self._type = raw[12:14]
@property
def header( self ):
return self._dst + self._src + self._type
@property
def dst( self ):
dst = struct.unpack('!6B', self._dst)
dst = '%02x:%02x:%02x:%02x:%02x:%02x' % dst
return dst
@dst.setter
def dst( self, mac ):
mac = mac.split(':')
for i in range( len(mac) ):
mac[i] = int( mac[i] )
self._dst = b''
for i in range( len(mac) ):
self._dst += struct.pack('!B', dst[i])
@property
def src( self ):
src = struct.unpack('!6B', self._src)
src = '%02x:%02x:%02x:%02x:%02x:%02x' % src
return src
@src.setter
def src( self, ip ):
ip = ip.split('.')
for i in range( len(ip) ):
ip[i] = int( ip[i] )
self._src = b''
for i in range( len(ip) ):
self._src += struct.pack('!B', ip[i])
@property
def type( self ):
(type,) = struct.unpack('!H', self._type)
return type
@type.setter
def type( self, type ):
type = struct.pack('!H', type)
self._type = type
import struct
if raw != None:
self._verlen = raw[:1]
self._service = raw[1:2]
self._total = raw[2:4]
self._id = raw[4:6]
self._flag_and_offset = raw[6:8]
self._ttl = raw[8:9]
self._type = raw[9:10]
self._check_sum = raw[10:12]
self._src = raw[12:16]
self._dst = raw[16:20]
else:
self._verlen = b'\x00'
self._flag_and_offset = b'\x00\x00'
@property
def header( self ):
return self._verlan + self._service + self._total + self._id + self._flag_and_offset + self._ttl + self._type + self._check_sum + self._src + self._dst
def ver( self ):
(ver,) = struct.unpack('!B', self._verlen)
ver = verlen >> 4
return ver
def ver( self, ver ):
(len,) = struct.unpack('!B', self._verlen)
len = len & 0x0F
ver = ver << 4
tmp = ver + len
self._verlen = struct.pack('!B', tmp)
def length( self ):
(len,) = struct.unpack('!B', self._verlen)
def length( self, len ):
(ver,) = struct.unpack('!B', self._verlen)
ver = ver & 0xF0
tmp = ver + len
self._verlen = struct.pack('!B', tmp)
def service( self ):
(service,) = struct.unpack('!B', self._service)
return service
def service( self, service ):
self._service = struct.pack('!B', service)
def total( self ):
(total,) = sturct.unpack('!H', self._total)
return total
def total( self, total ):
self._total = struct.pack('!H', total)
def id( self ):
(id,) = struct.unpack('!H', self._id)
return id
def id( self, id ):
self._id = struct.pack('!H', id)
def flag( self ):
(flag,) = struct.unpack('!H', self._flag_and_offset)
flag = flag >> 13
return flag
def flag( self, flag ):
(offset,) = struct.unpack('!H', self._flag_and_offset)
offset = offset & 0x1FFF
tmp = flag + offset
self._flag_and_offset = struct.pack('!H', tmp)
def offset( self ):
(offset,) = struct.unpack('!H', self._flag_and_offset)
offset = (offset & 0x1FFF) << 2
return offset
def offset( self, offset ):
(flag,) = struct.unpack('!H', self._flag_and_offset)
flag = flag & 0xE000
tmp = flag + offset
self._flag_and_offset = struct.pack('!H', tmp)
def ttl( self ):
(ttl,) = struct.unpack('!B', self._ttl)
return ttl
def ttl( self, ttl ):
self._ttl = struct.pack('!B', ttl)
def type( self ):
(type,) = struct.unpack('!B', self_type)
def type( self, type ):
self._type = struct.pack('!B', type)
def check_sum( self ):
(check_sum,) = struct.unpack('!H', self._check_sum)
def check_sum( self, chksum ):
self._check_sum = struct.pack('!H', chksum)
def src( self ):
src = struct.unpack('!4B', self._src)
src = '%d.%d.%d.%d' % src
return src
def src( self, ip ):
ip = ip.split('.')
for i in range( len(ip) ):
ip[i] = int( ip[i] )
for i in range( len(ip) ):
self._src += struct.pack('!B', ip[i])
def dst( self ):
dst = struct.unpack('!4B', self._dst)
dst = '%d.%d.%d.%d' % dst
return dst
def dst( self, ip ):
ip = ip.split('.')
for i in range( len(ip) ):
ip[i] = int( ip[i] )
for i in range( len(ip) ):
self._dst += struct.pack('!B', ip[i])
import struct
class Icmp:
def __init__( self, raw=None ):
if raw != None:
self._type = raw[:1]
self._code = raw[1:2]
self._chksum = raw[2:4]
@property
def header( self ):
return self._type + self._code + self._chksum
@property
def type( self ):
(type,) = struct.unpack('!B', self._type)
return type
@type.setter
def type( self, type ):
self._type = struct.pack('!B', type)
@property
def code( self ):
(code,) = struct.unpack('!B', self._code)
return code
@code.setter
def code( self, code ):
self._code = struct.pack('!B', code)
@property
def chksum( self ):
(chksum,) = struct.unpack('!H', chksum)
return chksum
@chksum.setter
def chksum( self, chksum ):
self._chksum = struct.pack('!H', chksum)
class Echo( Icmp ):
def __init__( self, raw=None ):
if raw != None:
self._id = raw[:2]
self._seq = raw[2:4]
self._payload = raw[4:]
@property
def header( self ):
return self._type + self._code + self._chksum + self._id + self._seq + self._payload
@property
def id( self ):
(id,) = struct.unpack('!H', self._id)
return id
@id.setter
def id ( self, id ):
self._id = struct.pack('!H', id)
@property
def seq( self ):
seq = struct.unpack('!H', self._seq)
return seq
@seq.setter
def seq( self ):
self._seq = struct.pack('!H', seq)
@property
def payload( self ):
return payload.decode( errors='ignore' )
@payload.setter
def payload( self, payload ):
self._payload = payload.encode()
from header.ip import *
from header.udp import *
from header.arp import *
from header.icmp import *
class Packet:
def __init__( self, raw ):
self._eth = Eth( raw[:14] )
if self._eth.type == 0x0800:
self.analyze_ip( raw[14:] )
if self._eth.type == 0x0806:
self.analyze_arp( raw[14:] )
def analyze_ip( self, raw ):
self._ip = Ip( raw )
if self._ip.type == 17:
self.analyze_udp( raw[20:] )
elif self._ip.type == 1:
self.analyze_icmp( raw[20:] )
def analyze_udp( self, raw ):
self._udp = Udp( raw )
def analyze_arp( self, raw ):
self._arp = Arp( raw )
def analyze_icmp( self, raw ):
self._icmp = Icmp( raw )
@property
def raw( self ):
return self._raw
@property
def eth( self ):
return self._eth
@property
def ip( self ):
return self._ip
@property
def arp( self ):
return self._arp
@property
def icmp( self ):
return self._icmp
'프로그래밍 > NETWORK HACKING' 카테고리의 다른 글
[네트워크 보안] udp 체크섬 계산 / 포트 스캐닝 (0) | 2017.07.04 |
---|---|
[네트워크 보안] IP Fragment( 단편화 ) (0) | 2017.07.02 |
[네트워크 보안] ARP Cache Poisoning을 이용한 ARP Spoofing (0) | 2017.06.23 |
[네트워크 보안] ARP 클래스 setter 추가 / arping.py (0) | 2017.06.22 |
[네트워크 보안] ARP / 파이썬3 ARP 클래스 정의 및 packet.py, sniffer.py 수정 (0) | 2017.06.22 |
댓글