IT博客汇
  • 首页
  • 精华
  • 技术
  • 设计
  • 资讯
  • 扯淡
  • 权利声明
  • 登录 注册

    浅谈拒绝服务攻击的原理与防御(2):反射型DDOS

    针发表于 2017-03-06 04:24:50
    love 0

    0×01 前言

    前几天提交了一篇关于DDOS攻击的文章到今天下午才审核通过发表出来,所以晚上闲来无事在接着写下面的内容,今天我就不多说废话了直接来干货。

    目前来说流量型反射DDOS攻击都是以UDP为载体的,毕竟TCP的三次握手就让伪造源地址反射大流量变得不现实(tcp反射ACK倒是还行- -!)

    下面来看看一般能用于反射放大的协议以及放大倍数吧

    现在TFTP也被利用来进行DDOS反射了,据说放大倍数也很可观,根据表中显示看来NTP放大倍数最高,不过NTP服务器不多,而且开了monlist的更少了,我倒是扫描到过一两个,但是DNS和snmp可就是多如牛毛了,而且SNMP的放大倍数也不是他说的那么小,我今天刚测试发送一个140字节左右的报文能收到1400多字节的恢复,因为我那本破SNMP的书没细说SNMP报文的详细构造,我没能精确的构造SNMP的报文,只能去找了一个现成的,好今天我主要就讲NTP、SNMP和DNS的反射攻击和反射资源的扫描。

    0×02 反射放大攻击的原理

    很多协议的请求包要远小于回复包,以一个字节的数据换十个字节的数据回来,这就是一种放大,但是你这单纯的放大攻击的是自己啊,所以说想要攻击别人就要在发送请求包时把源地址写成要攻击的人的地址,这样回复的大字节报文就去你要攻击的人那里了,这都是很简单的道理我想也不用我多说

    这里放大主要利用的是NTP的monlist(listpeers也行)、DNS的AXFR(ANY也行)、SNMP的getbulkrequest

    monlist是返回最近600个与当前NTP服务器通信过的IP地址

    AXFR是区域传送(有地方叫域传送),比如freebuf.com下的所有域名返回给请求者

    SNMPV2版本中新加的getbulkrequest用于一次请求大量的信息,减少管理站与被管理设备的交互次数

    这些协议都是UDP下的协议,我就不详细说了,不然能讲一星期,有兴趣的去找一本TCP/IP的书看看,上面都有详细的介绍。下面直接上扫描这些东西的代码

    #-*- coding: UTF-8 -*- 
    import socket
    import struct
    import thread
        
        
    change = lambda x:sum([256**j*int(i) for j,i in enumerate(x.split('.')[::-1])])    
        
    def NTPscan(IP):
        str_monlist=#空的,各位自己填上NTP的payload吧
        str_listpeers=#空的,各位自己填上NTP的payload吧
        str_dns=(#空的,各位自己填上DNS的payload吧)
                 
        str_snmp=('\x30'+'\x3b'+'\x02'+'\x01'+'\x01'+'\x04'+'\x06'+'\x70'+'\x75'+'\x62'+'\x6c' 
                  +'\x69'+'\x63'+'\xa5'+'\x2e'+'\x02'+'\x04'+'\x4e'+'\x73'+'\x68'+'\xe1'+'\x02' 
                  +'\x01'+'\x00'+'\x02'+'\x01'+'\x0a'+'\x30'+'\x20'+'\x30'+'\x0e'+'\x06'+'\x0a' 
                  +'\x2b'+'\x06'+'\x01'+'\x02'+'\x01'+'\x19'+'\x03'+'\x03'+'\x01'+'\x01'+'\x05' 
                  +'\x00'+'\x30'+'\x0e'+'\x06'+'\x0a'+'\x2b'+'\x06'+'\x01'+'\x02'+'\x01'+'\x19' 
                  +'\x03'+'\x03'+'\x01'+'\x02'+'\x05'+'\x00')
        
        
        port_ntp=123
        port_echo=7
        port_ch=13
        port_dns=53
        port_snmp=161
        NTP1=(port_ntp,str_monlist)
        NTP2=(port_ntp,str_listpeers)
        CHANGE=(port_ch,str_ch)
        DNS=(port_dns,str_dns)
        SNMP=(port_snmp,str_snmp)
        port_pool=(NTP1,CHANGE,DNS,SNMP)
        
        for i in range(len(port_pool)): 
            s=socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
            s.settimeout(1)
            port_str=port_pool[i]
            s.sendto(port_str[1],(IP,port_str[0]))
        
            try:
                recvbuff=s.recvfrom(1024)
                addr=recvbuff[1]
                data=recvbuff[0]
                port=addr[1]
                ip=addr[0]
                if port in [7,13,53,123,161]:
                    if port==123:
                        if len(data)>200:
                            ip_x=(ip,port,len(data))
                            ip_pool.append(ip_x)
    
                    elif port==53:
                        if len(data)>100:
                            ip_x=(ip,port,len(data))
                            ip_pool.append(ip_x)
    
                    elif port==161:
                        if len(data)>200:
                            ip_x=(ip,port,len(data))
                            ip_pool.append(ip_x)
                    else:        
                        #print ip,':',port,' ',len(data),'\n'
                        ip_x=(ip,port,len(data))
                        ip_pool.append(ip_x)
    
            except:
                pass           
            s.close()                  
    
    def main():
        IP=raw_input("输入IP:")
        threads=int(input("线程数threads:"))
        IP_a=[]
        locks=[]
        if IP.find(',') != -1: #检查是否有,
            IP_a=IP.split(',') #按,分割字符串成一个数组
    
        elif IP.find('-') != -1: #检查是否有-
            IP_b=IP.split('-')
            IP_start=IP_b[0] #设定起始IP地址
            IP_end=IP_b[1]
            IP_start_num=change(IP_start)
            IP_end_num=change(IP_end)
            num=IP_start_num
            while num <= IP_end_num:
              ip_i=socket.inet_ntoa(struct.pack('I',socket.htonl(num))) #把数字转换成ip
          
              IP_a.append(ip_i)
              #print IP_a
              num+=1
        else:
            IP_a.append(IP)
    
    
        for i in range(threads):  
            lock = thread.allocate_lock()   #创建锁对象  
            lock.acquire()                  #获取锁对象 加锁  
            locks.append(lock)
        for i in range(threads):
            thread.start_new_thread(scan,(IP_a,i,locks[i],threads))
        for i in range(threads):
            while locks[i].locked():
                pass    
    def scan(IP_a,i,lock,threads):
        
        while i<len(IP_a):
            NTPscan(IP_a[i])
            #print addrs[q]
            i=i+threads
        lock.release()
    ip_pool=[]
    
    if __name__ == '__main__':   
        main()
    
    print "所有线程运行结束success!"
    print "-----IP--------port---len"
    #a=open('d:\\address.txt','w')
    #a.writelines(ip_pool)
    #a.close()
    for i in ip_pool:
        print i
    exitt=raw_input("输入任意键exit:")
    exit()    

    用python打开,只能在windows下,因为这个多线程thread在linux下好像不能用,输入IP的时候可以输入 x.x.x.x-x.x.x.x形式,或者以逗号分隔 x.x.x.x,a.a.a.a,s.s.s.s又或者只输入一个ip也行,线程数要是扫描1.1.0.0-1.2.0.0 这样大段的话推荐1000-2000线程就可以,要是扫描2.0.0.0-3.0.0.0这样一千多万地址,你直接上10000线程吧,不然慢死,我编程水平比较low,所以代码写的很杂乱,大家别嘲笑我啊,还有为了防止大家去做坏事我吧DNS和NTP的payload删掉了,留下了SNMP的,大家自己去学习学习这俩协议,自己补全payload吧,就算是家庭作业了。

    攻击代码我也写好了,只不过嘿嘿……现在还不发呢,下期再发吧。



沪ICP备19023445号-2号
友情链接