Any web developer worth their salt has heard of npm. This magical technology has opened up doorways to realms unknown. But the way people tend to use it makes it equally easy to exploit. There was an article in early 2018 that seemed no less than “an episode of black mirror” (top comment on the article). The article talked about how one can misuse npm to inject malicious code in applications and get away with it. Amidst all the charm and sorcery (and panic), there was one thing that caught my eye and I haven’t been able to stop thinking about it since — The Heisenberg Manoeuvre.
What are we talking about here?
I will be discussing the “The Heisenberg Manoeuvre” from I’m harvesting credit card numbers and passwords from your site. Here’s how. Before diving in, let us understand what it is.
Note: You don’t have to read that article to understand this one. But it is a good read.
Imagine you are a hacker and you’ve successfully intruded your target system. Now the goal is to stay undetected inside the system for as long as you can. If everything works out, you can siphon information out of the system for months on the end. Unfortunately, this is easier said than done. With so many people working on different levels, someone will notice an anomaly sooner or later. This is where the heisenberg manoeuvre comes in.
It is essentially a strategy that can help you evade detection. This manoeuvre alone isn’t enough but it can play a major role in the process. Our mantra here is this:
It should be impossible to inspect the code as well as its behaviour simulatenously. In simple words, code will change its behaviour on being observed
A Little Roleplay
Say we are in the world of Jellybean people from Among us. For those who don’t know about it, it is a game where a crew has to do tasks around their spaceship. There are imposters in the crew who keep on sabotaging the ship and try to kill other crewmates.
Say that imposter (you) needs a secret code used to control the reactor. The code is entered into a panel in the reactor section of the ship. But only the captain knows the code.
Fortunately, the panel interface is written using web technologies (If JS is good enough for SpaceX, it is good enough for Jellybean people).
We will make a simple key logger — program that records which keys were pressed. We will then plant it in the reactor panel’s UI which will let us know the secret code. We aim to deliver our spyware payload and then avoid detection.
This is a very simple and perhaps non-practical example. But it is enough to give you an idea of the concept.
Key logger code
This is a very straightforward JS code. The Logger captures keystrokes and sends it to my server.
Since you are with the crew, you can simply take the above snippet and put it in an npm package. You install it indirectly and include it in the UI bundle (go Webpack!). Since its uglified and buried deep inside the npm hierarchy, chances are that no one will bother to check what it is. Like the Greeks, you’ve made a wooden horse and infiltrated Troy (Trojan Horse malware).
Attack in action
You can visit this URL to see the application in action. Whenever you press a key, it is sent to the server. The server response is logged onto the screen so that you can understand the process.
As developers, we spend most of our time observing the code. Typically, we have an inspector window running. We tend to check network requests and debug event listeners as a part of the routine. Anyone observing the inspector window will be able to detect unusual activity.
In essence, any of your peer crewmates can easily detect what you’ve done and render all your efforts futile.
What if we know that we are being monitored? We could then simply stop our key logger in that case. Nothing happening, nothing detected. When we know that no one is watching us, we resume our malicious activities.
Idea is to detect when the developer tools are open. Then we can simply remove the keypress event. A simple width based solution can be found here (Does not work with undocked tools). I have modified this code to use timers. You can find the modified code here. With that out of the way, we can simply write this (
isInspectorOpen is implemented in the modified code):
We check the status of inspector window every
500ms. If it is open, the event listener is removed. We’re good to go. Final application can be found here.
- When inspector window is open, there are no network requests.
- When inspector window is open, there is no
You’ve successfully hidden from your fellow crewmates. Now that you have the codes, you can stop the reactor. While everyone panics and rushes to fix it, you can go for the kill.
As I said, this is a very basic example. But it is something to go on. Can you think of more ways to leverage The Heisenberg Manoeuvre?