Web Encryption Using Javascript

I was analyzing a login page one day, and an odd idea came to me. What if we encrypt the data being sent on a website using Javascript? Admittedly, this idea seems pretty useless seeing that HTTPS does the same thing but better, but what about websites that use self-signed certificates or don’t use HTTPS at all? These sites are everywhere, just not usually on the World Wide Web. I’m talking about the admin login pages used by various services, such as routers or web servers, and although most of these are hidden behind private networks, it’s here where they are most vulnerable to MITM attacks.

A demo of this idea is here!

How This Would Work

Here are three diagrams showing how the protocol would work.

Authentication:

Server sends Login Page with JS → Client sends username + hashed password → Server checks hash

Sending Data from Server to Client:

Server saves login timestamp → Server encrypts data (ex. admin page) with password as key → Client recives and decrypts data with password

Sending Data from Client to Server:

Client sends any post data encrypted with password + timestamp encrypted with password → Server decrypts post data → Server checks timestamp to prevent replay attacks → Server updates last post timestamp

If those didn’t make sense then here’s a more simple explanation: By using the user’s password as a pre-shared key, we can encrypt all the data being sent and received.

What This Protects Against

As you can probably tell this is meant to mitigate MITM attacks. However, it will only prevent some forms due to the inherent vulnerability of plain HTTP. More passive interceptions will be rendered useless as the intruder doesn’t know the pre-shared key (user’s password). Replay attacks, which don’t require decryption, are also stopped by attaching a timestamp to the POST requests. If the timestamp is the same or older than the last POST timestamp, then the server knows it’s a replay attempt. 

What This DOES NOT Protect Against

The biggest issue with plain HTTP is that everything can be modified. Thus, more active MITMs can bypass the JS encryption by removing the encryption code, injecting their own JS, or redirecting to a phishing site. Also, the registration is unencrypted as there is no known pre-shared key between the server and client. (This can be fixed by adding users through an admin account)

EDIT: The registration can be encrypted by having the server send a RSA public key and have the client encrypt the data with it.

An Example Scenario

In case you don’t see how this could be implemented, here’s a fun example to help out:

Imagine you’re a college or university student trying to leverage your school’s free printing service. You go to the school’s web printing page and input your school ID and password. Uh oh, the tech engineer who set up the service was too negligent to enable HTTPS on the website. Coincidentally, a script kiddy taking the cybersecurity course at your university has also noticed the unencrypted site and wants to harvest some credentials to get some blackmail. He whips out Bettercap and Mitmproxy and immediately starts intercepting all the data. Luckily for you, the creators of the web print software have included the JS encryption protocol and all the script kiddie sees is a garbled mess (he’s also still a novice and doesn’t know how to inject JS with Bettercap). Hooray! Your credentials and papers are safe from prying eyes! 

Conclusion

HTTPS should always be preferred over this method of encryption. Not only does HTTPS do the same thing, it also protects against the modification of data, making it a far superior choice. But when HTTPS can’t be used or is improperly implemented, JS encryption is still a great last line of defense.

Comments

Leave a Reply