In most e-commerce applications, sensitive traffic is usually sent over SSL. It provides an encrypted connection between the Web browser and the Web server, keeping data in transit safe from eavesdroppers. The sole purpose of SSL was to defeat packet sniffing, which allowed malicious eavesdroppers to recover sensitive information from data passing through the system.
When it comes to intrusion detection, SSL is the single greatest obstacle. Most IDSs rely on network packet sniffing to collect activity data. If the data themselves are encrypted, they can't be analyzed to determine whether the ongoing activity is malicious. All IDSs based on network packet sniffing are oblivious to attacks sent via SSL. Figure 17-1 illustrates how IDSs are rendered ineffective in combatting attacks being sent via SSL.
To illustrate how IDSs are blindsided by attacks via SSL, let's look at an example of such an attack launched against a Windows machine running IIS 4.0. The setup is:
IIS listening on ports 80 and 443 on 192.168.7.203
Snort IDS running on "webspy" which is listening on the same network segment as 192.168.7.203
Attacker #1 on 10.0.0.1
Attacker #2 on 10.0.0.2
Four attacks were launched against 192.168.7.203: two MDAC RDS attacks from 10.0.0.1 and two Unicode cmd.exe attacks from 10.0.0.2 between 9:46 P.M. and 9:53 P.M.:
Time | Attacker | SSL | Attack URL |
9:46 P.M. | 10.0.0.1 | No | http://192.168.7.203/msadc/msadcs.dll |
9:47 P.M. | 10.0.0.2 | No | http://192.168.7.203/scripts/..%c0%af../winnt/system32/cmd.exe?/c+set |
9:49 P.M. | 10.0.0.1 | Yes | https://192.168.7.203/msadc/msadcs.dll |
9:53 P.M. | 10.0.0.2 | Yes | https://192.168.7.203/scripts/..%c0%af../winnt/system32/cmd.exe?/c+set |
Upon recovering the IIS log file from 192.168.7.203, we note that all four requests were accurately recorded. The entries from the IIS log file are:
2002-04-22 21:46:44 10.0.0.1 - 192.168.7.203 80 GET /msadc/msadcs.dll 200
Mozilla/4.76+[en]+(Windows+NT+5.0;+U)
2002-04-22 21:47:19 10.0.0.2 - 192.168.7.203 80 GET
/scripts/../../winnt/system32/cmd.exe /c+set 502
Mozilla/4.76+[en]+(Windows+NT+5.0;+U)
2002-04-22 21:49:01 10.0.0.1 - 192.168.7.203 443 GET /msadc/msadcs.dll 200
Mozilla/4.76+[en]+(Windows+NT+5.0;+U)
2002-04-22 21:53:32 10.0.0.2 - 192.168.7.203 443 GET /scripts/../../winnt/system32/cmd.exe /c+set 502
Mozilla/4.76+[en]+(Windows+NT+5.0;+U)
The Snort logs from "webspy," however, contain only two entries:
Apr 22 21:42:20 webspy snort[660]: [1:1023:3] WEB-IIS msadc/msadcs.dll access
[Classification: access to a potentially vulnerable Web application] [Priority:
2]: {TCP} 10.0.0.1:2597 -> 192.168.7.203:80
Apr 22 21:42:53 webspy snort[660]: [102:1:1] spp_http_decode: ISS Unicode attack
detected {TCP} 10.0.0.2:1729 -> 192.168.7.203:80
The two attacks via SSL haven't even been noticed by Snort! Hence, if an attacker chooses to hack 192.168.7.203 via SSL, the attacks will go unnoticed.
Using a browser to launch HTTP attacks via SSL is easy. All an attacker has to do is use URLs beginning with https instead of http. The browser takes care of the SSL session negotiation and encryption. However, if an attacker wants to run a script or a tool that sends attacks via HTTP but doesn't have SSL functionality built into it, a technique called SSL tunneling is used. Simply put, SSL tunneling involves a port-forwarding program that listens on port 80 for standard HTTP requests and forwards them to a particular host on an encrypted SSL connection. In this way, attacks launched against the SSL tunnel program are automatically encrypted and forwarded to the target system.
Constructing an SSL tunnel with OpenSSL is quite easy, especially on Unix systems that use inetd. Let's consider an example where an attacker is on 10.0.0.1 and the target Web server is running on 192.168.7.203 on port 443. The attacker wants to run a vulnerability scanner such as Whisker on the target Web server. The attacker sets up an SSL tunnel on another system, 10.0.0.2. In the /etc/inetd.conf file on 10.0.0.2, the attacker adds:
www stream tcp nowait root /usr/sbin/tcpd /tmp/sslconnect.sh
This addition causes the inetd daemon to pass all TCP traffic on port 80 (WWW) to /tmp/sslconnect.sh. The contents of /tmp/sslconnect.sh are:
#!/bin/sh
openssl s_client -no_tls1 -quiet -connect 192.168.7.203:443 2>/dev/null
Because /tmp/sslconnect.sh is invoked by inetd, all data coming in through TCP port 80 is received as standard input to openssl. The IP address of the target server, 192.168.7.203, is hard-coded in the script. The SSL tunnel can be used against only one system at a time. The "-no_tls1" and "-quiet" options suppress the display of the SSL handshake headers and bypass the SSL authentication warnings for unsigned site certificates. All data returned by openssl are sent back via the incoming TCP connection from inetd, as the script dumps all the data to standard output. Figure 17-2 illustrates how the SSL tunnel works.
The attacker now runs Whisker with 10.0.0.2 port 80 as a target server, instead of 192.168.7.203. The SSL tunnel takes care of encrypting and forwarding the data to 192.168.7.203, and sending the replies back to 10.0.0.1.
A better and more robust SSL tunnel than the one presented here is "stunnel." Based on the OpenSSL libraries (http://www.stunnel.org/); stunnel binaries for Windows are also available from this Web site.
What should we do if SSL defeats intrusion detection? There is no simple answer, but various people have come up with solutions to meet their own needs. Of all these solutions, using a reverse HTTP proxy proves to be the best bet for intrusion detection. Figure 17-3 shows how a reverse HTTP proxy can be used to intercept SSL traffic before it can reach the Web server and pass clear text HTTP traffic to the Web server. The IDS is placed between the reverse HTTP proxy and the Web server. In this way, the IDS can pick up signatures in HTTP traffic.
The only drawback to this system is that the source IP address of the attacking system gets replaced with the IP address of the reverse HTTP proxy system. To track down the source IP address, an attacker would have to correlate the reverse HTTP proxy logs with the IDS logs' time stamps.
The statement that sniffing data passing through an SSL connection is impossible isn't entirely true. SSL relies on public key cryptography to exchange a session key between the Web server and the browser. A symmetric key, the session key is used by the Web server and the browser to encrypt data passing back and forth during the HTTP session.
If the SSL session key can be recovered, the data stream can be decrypted if intercepted. The only way to recover the SSL session key is when it is being exchanged between the Web server and the browser. However, this key exchange is done with public key encryption. To decrypt the session key, an attacker would therefore need access to the server's SSL certificate and the client's SSL certificate, if one is used. Rarely do Web servers force a browser to use a client-side certificate.
Knowing a server's SSL certificate's private key would allow an attacker to decrypt data from an SSL connection if the SSL sniffer was started before the SSL connection was established. Such a sniffer, ssldump, an SSL-enabled tcpdump program, does exist (http://www.rtfm.com/ssldump/). For details on how ssldump works and can be used, look up the document on the Web site sarcastically named "rtfm.com"!
Let's look at an example of ssldump in action. An SSL-enabled Apache Web server is running on 192.168.7.204. The Apache configuration file contains two directives that tell the server where to find the server-side SSL certificate and the corresponding private key.
SSLCertificateFile /etc/httpd/conf/ssl/server.crt
SSLCertificateKeyFile /etc/httpd/conf/ssl/server.key
Here ssldump is running on a system that can sniff network traffic going in and out of 192.168.7.204. For ssldump to decrypt the SSL encrypted data successfully, it has to be supplied with a copy of the SSL certificate's private key namely, server.key. An HTTP session decrypted by ssldump, between 10.0.0.1 and 192.168.7.204, is:
root@webspy:~# ssldump -n -q -d -k ./server.key
New TCP connection #1: 10.0.0.1(1401) <-> 192.168.7.204(443)
1 1 0.0075 (0.0075) C>S SSLv2 compatible client hello
1 2 0.0096 (0.0020) S>C Handshake ServerHello
1 3 0.0097 (0.0001) S>C Handshake Certificate
1 4 0.0097 (0.0000) S>C Handshake ServerHelloDone
1 5 0.0153 (0.0055) C>S Handshake ClientKeyExchange
1 6 0.0531 (0.0377) C>S ChangeCipherSpec
1 7 0.0531 (0.0000) C>S Handshake Finished
1 8 0.0541 (0.0010) S>C ChangeCipherSpec
1 9 0.0541 (0.0000) S>C Handshake Finished
1 10 0.0560 (0.0019) C>S application_data
---------------------------------------------------------------
GET /cgi-bin/test-cgi HTTP/1.0
Connection: Keep-Alive
User-Agent: Mozilla/4.76 [en] (Windows NT 5.0; U)
Host: 192.168.7.204
Accept: */*
Accept-Encoding: gzip
Accept-Language: en
Accept-Charset: iso-8859-1,*,utf-8
---------------------------------------------------------------
1 11 0.1046 (0.0485) S>C application_data
---------------------------------------------------------------
HTTP/1.1 200 OK
Date: Tue, 23 Apr 2002 20:21:11 GMT
Server: Apache/1.3.19 mod_ssl/2.8.2 OpenSSL/0.9.6
Connection: close
Content-Type: text/plain
CGI/1.0 test script report:
argc is 0. argv is .
SERVER_SOFTWARE = Apache/1.3.19 mod_ssl/2.8.2 OpenSSL/0.9.6
SERVER_NAME = 192.168.7.204
GATEWAY_INTERFACE = CGI/1.1
SERVER_PROTOCOL = HTTP/1.0
SERVER_PORT = 443
REQUEST_METHOD = GET
HTTP_ACCEPT = */*
PATH_INFO =
PATH_TRANSLATED =
SCRIPT_NAME = /cgi-bin/test-cgi
QUERY_STRING =
REMOTE_HOST =
REMOTE_ADDR = 10.0.0.1
REMOTE_USER =
AUTH_TYPE =
CONTENT_TYPE =
CONTENT_LENGTH =
POST QUERY:
---------------------------------------------------------------
1 12 0.1131 (0.0084) S>C Alert warning close_notify
1 0.1138 (0.0006) S>C TCP FIN
1 13 0.1168 (0.0030) C>S Alert warning close_notify
1 0.1172 (0.0003) C>S TCP FIN
root@webspy:~#
The system 10.0.0.1 made a request for https://192.168.7.204/cgi-bin/test-cgi. Here ssldump was able to decrypt both the HTTP request and the reply.
Using SSL sniffing for intrusion detection systems has two drawbacks. First, SSL decryption consumes lot of CPU time. To be effective in real-time intrusion detection, SSL sniffing has to be implemented on an extremely fast and powerful system. Second, if multiple servers are running SSL with different server certificates and keys, a separate instance of an SSL sniffer has to be run for each server.